1 
2 // Copyright Contributors to the OpenVDB Project
3 // SPDX-License-Identifier: MPL-2.0
4 
5 /*!
6     \file   PNanoVDB.h
7 
8     \author Andrew Reidmeyer
9 
10     \brief  This file is a portable (e.g. pointer-less) C99/GLSL/HLSL port
11             of NanoVDB.h, which is compatible with most graphics APIs.
12 */
13 
14 #ifndef NANOVDB_PNANOVDB_H_HAS_BEEN_INCLUDED
15 #define NANOVDB_PNANOVDB_H_HAS_BEEN_INCLUDED
16 
17 // ------------------------------------------------ Configuration -----------------------------------------------------------
18 
19 // platforms
20 //#define PNANOVDB_C
21 //#define PNANOVDB_HLSL
22 //#define PNANOVDB_GLSL
23 
24 // addressing mode
25 // PNANOVDB_ADDRESS_32
26 // PNANOVDB_ADDRESS_64
27 #if defined(PNANOVDB_C)
28 #ifndef PNANOVDB_ADDRESS_32
29 #define PNANOVDB_ADDRESS_64
30 #endif
31 #elif defined(PNANOVDB_HLSL)
32 #ifndef PNANOVDB_ADDRESS_64
33 #define PNANOVDB_ADDRESS_32
34 #endif
35 #elif defined(PNANOVDB_GLSL)
36 #ifndef PNANOVDB_ADDRESS_64
37 #define PNANOVDB_ADDRESS_32
38 #endif
39 #endif
40 
41 // bounds checking
42 //#define PNANOVDB_BUF_BOUNDS_CHECK
43 
44 // enable HDDA by default on HLSL/GLSL, make explicit on C
45 #if defined(PNANOVDB_C)
46 //#define PNANOVDB_HDDA
47 #ifdef PNANOVDB_HDDA
48 #ifndef PNANOVDB_CMATH
49 #define PNANOVDB_CMATH
50 #endif
51 #endif
52 #elif defined(PNANOVDB_HLSL)
53 #define PNANOVDB_HDDA
54 #elif defined(PNANOVDB_GLSL)
55 #define PNANOVDB_HDDA
56 #endif
57 
58 #ifdef PNANOVDB_CMATH
59 #include <math.h>
60 #endif
61 
62 // ------------------------------------------------ Buffer -----------------------------------------------------------
63 
64 #if defined(PNANOVDB_BUF_CUSTOM)
65 // NOP
66 #elif defined(PNANOVDB_C)
67 #define PNANOVDB_BUF_C
68 #elif defined(PNANOVDB_HLSL)
69 #define PNANOVDB_BUF_HLSL
70 #elif defined(PNANOVDB_GLSL)
71 #define PNANOVDB_BUF_GLSL
72 #endif
73 
74 #if defined(PNANOVDB_BUF_C)
75 #include <stdint.h>
76 #if defined(_WIN32)
77 #define PNANOVDB_BUF_FORCE_INLINE static inline __forceinline
78 #else
79 #define PNANOVDB_BUF_FORCE_INLINE static inline __attribute__((always_inline))
80 #endif
81 typedef struct pnanovdb_buf_t
82 {
83     uint32_t* data;
84 #ifdef PNANOVDB_BUF_BOUNDS_CHECK
85     uint64_t size_in_words;
86 #endif
87 }pnanovdb_buf_t;
pnanovdb_make_buf(uint32_t * data,uint64_t size_in_words)88 PNANOVDB_BUF_FORCE_INLINE pnanovdb_buf_t pnanovdb_make_buf(uint32_t* data, uint64_t size_in_words)
89 {
90     pnanovdb_buf_t ret;
91     ret.data = data;
92 #ifdef PNANOVDB_BUF_BOUNDS_CHECK
93     ret.size_in_words = size_in_words;
94 #endif
95     return ret;
96 }
97 #if defined(PNANOVDB_ADDRESS_32)
pnanovdb_buf_read_uint32(pnanovdb_buf_t buf,uint32_t byte_offset)98 PNANOVDB_BUF_FORCE_INLINE uint32_t pnanovdb_buf_read_uint32(pnanovdb_buf_t buf, uint32_t byte_offset)
99 {
100     uint32_t wordaddress = (byte_offset >> 2u);
101 #ifdef PNANOVDB_BUF_BOUNDS_CHECK
102     return wordaddress < buf.size_in_words ? buf.data[wordaddress] : 0u;
103 #else
104     return buf.data[wordaddress];
105 #endif
106 }
pnanovdb_buf_read_uint64(pnanovdb_buf_t buf,uint32_t byte_offset)107 PNANOVDB_BUF_FORCE_INLINE uint64_t pnanovdb_buf_read_uint64(pnanovdb_buf_t buf, uint32_t byte_offset)
108 {
109     uint64_t* data64 = (uint64_t*)buf.data;
110     uint32_t wordaddress64 = (byte_offset >> 3u);
111 #ifdef PNANOVDB_BUF_BOUNDS_CHECK
112     uint64_t size_in_words64 = buf.size_in_words >> 1u;
113     return wordaddress64 < size_in_words64 ? data64[wordaddress64] : 0llu;
114 #else
115     return data64[wordaddress64];
116 #endif
117 }
118 #elif defined(PNANOVDB_ADDRESS_64)
pnanovdb_buf_read_uint32(pnanovdb_buf_t buf,uint64_t byte_offset)119 PNANOVDB_BUF_FORCE_INLINE uint32_t pnanovdb_buf_read_uint32(pnanovdb_buf_t buf, uint64_t byte_offset)
120 {
121     uint64_t wordaddress = (byte_offset >> 2u);
122 #ifdef PNANOVDB_BUF_BOUNDS_CHECK
123     return wordaddress < buf.size_in_words ? buf.data[wordaddress] : 0u;
124 #else
125     return buf.data[wordaddress];
126 #endif
127 }
pnanovdb_buf_read_uint64(pnanovdb_buf_t buf,uint64_t byte_offset)128 PNANOVDB_BUF_FORCE_INLINE uint64_t pnanovdb_buf_read_uint64(pnanovdb_buf_t buf, uint64_t byte_offset)
129 {
130     uint64_t* data64 = (uint64_t*)buf.data;
131     uint64_t wordaddress64 = (byte_offset >> 3u);
132 #ifdef PNANOVDB_BUF_BOUNDS_CHECK
133     uint64_t size_in_words64 = buf.size_in_words >> 1u;
134     return wordaddress64 < size_in_words64 ? data64[wordaddress64] : 0llu;
135 #else
136     return data64[wordaddress64];
137 #endif
138 }
139 #endif
140 typedef uint32_t pnanovdb_grid_type_t;
141 #define PNANOVDB_GRID_TYPE_GET(grid_typeIn, nameIn) pnanovdb_grid_type_constants[grid_typeIn].nameIn
142 #elif defined(PNANOVDB_BUF_HLSL)
143 #if defined(PNANOVDB_ADDRESS_32)
144 #define pnanovdb_buf_t StructuredBuffer<uint>
pnanovdb_buf_read_uint32(pnanovdb_buf_t buf,uint byte_offset)145 uint pnanovdb_buf_read_uint32(pnanovdb_buf_t buf, uint byte_offset)
146 {
147     return buf[(byte_offset >> 2u)];
148 }
pnanovdb_buf_read_uint64(pnanovdb_buf_t buf,uint byte_offset)149 uint2 pnanovdb_buf_read_uint64(pnanovdb_buf_t buf, uint byte_offset)
150 {
151     uint2 ret;
152     ret.x = pnanovdb_buf_read_uint32(buf, byte_offset + 0u);
153     ret.y = pnanovdb_buf_read_uint32(buf, byte_offset + 4u);
154     return ret;
155 }
156 #elif defined(PNANOVDB_ADDRESS_64)
157 #define pnanovdb_buf_t StructuredBuffer<uint>
pnanovdb_buf_read_uint32(pnanovdb_buf_t buf,uint64_t byte_offset)158 uint pnanovdb_buf_read_uint32(pnanovdb_buf_t buf, uint64_t byte_offset)
159 {
160     return buf[uint(byte_offset >> 2u)];
161 }
pnanovdb_buf_read_uint64(pnanovdb_buf_t buf,uint64_t byte_offset)162 uint64_t pnanovdb_buf_read_uint64(pnanovdb_buf_t buf, uint64_t byte_offset)
163 {
164     uint64_t ret;
165     ret = pnanovdb_buf_read_uint32(buf, byte_offset + 0u);
166     ret = ret + (uint64_t(pnanovdb_buf_read_uint32(buf, byte_offset + 4u)) << 32u);
167     return ret;
168 }
169 #endif
170 #define pnanovdb_grid_type_t uint
171 #define PNANOVDB_GRID_TYPE_GET(grid_typeIn, nameIn) pnanovdb_grid_type_constants[grid_typeIn].nameIn
172 #elif defined(PNANOVDB_BUF_GLSL)
173 struct pnanovdb_buf_t
174 {
175     uint unused;    // to satisfy min struct size?
176 };
pnanovdb_buf_read_uint32(pnanovdb_buf_t buf,uint byte_offset)177 uint pnanovdb_buf_read_uint32(pnanovdb_buf_t buf, uint byte_offset)
178 {
179     return pnanovdb_buf_data[(byte_offset >> 2u)];
180 }
pnanovdb_buf_read_uint64(pnanovdb_buf_t buf,uint byte_offset)181 uvec2 pnanovdb_buf_read_uint64(pnanovdb_buf_t buf, uint byte_offset)
182 {
183     uvec2 ret;
184     ret.x = pnanovdb_buf_read_uint32(buf, byte_offset + 0u);
185     ret.y = pnanovdb_buf_read_uint32(buf, byte_offset + 4u);
186     return ret;
187 }
188 #define pnanovdb_grid_type_t uint
189 #define PNANOVDB_GRID_TYPE_GET(grid_typeIn, nameIn) pnanovdb_grid_type_constants[grid_typeIn].nameIn
190 #endif
191 
192 // ------------------------------------------------ Basic Types -----------------------------------------------------------
193 
194 // force inline
195 #if defined(PNANOVDB_C)
196 #if defined(_WIN32)
197 #define PNANOVDB_FORCE_INLINE static inline __forceinline
198 #else
199 #define PNANOVDB_FORCE_INLINE static inline __attribute__((always_inline))
200 #endif
201 #elif defined(PNANOVDB_HLSL)
202 #define PNANOVDB_FORCE_INLINE
203 #elif defined(PNANOVDB_GLSL)
204 #define PNANOVDB_FORCE_INLINE
205 #endif
206 
207 // struct typedef, static const, inout
208 #if defined(PNANOVDB_C)
209 #define PNANOVDB_STRUCT_TYPEDEF(X) typedef struct X X;
210 #define PNANOVDB_STATIC_CONST static const
211 #define PNANOVDB_INOUT(X) X*
212 #define PNANOVDB_IN(X) const X*
213 #define PNANOVDB_DEREF(X) (*X)
214 #define PNANOVDB_REF(X) &X
215 #elif defined(PNANOVDB_HLSL)
216 #define PNANOVDB_STRUCT_TYPEDEF(X)
217 #define PNANOVDB_STATIC_CONST static const
218 #define PNANOVDB_INOUT(X) inout X
219 #define PNANOVDB_IN(X) X
220 #define PNANOVDB_DEREF(X) X
221 #define PNANOVDB_REF(X) X
222 #elif defined(PNANOVDB_GLSL)
223 #define PNANOVDB_STRUCT_TYPEDEF(X)
224 #define PNANOVDB_STATIC_CONST const
225 #define PNANOVDB_INOUT(X) inout X
226 #define PNANOVDB_IN(X) X
227 #define PNANOVDB_DEREF(X) X
228 #define PNANOVDB_REF(X) X
229 #endif
230 
231 // basic types, type conversion
232 #if defined(PNANOVDB_C)
233 #define PNANOVDB_NATIVE_64
234 #include <stdint.h>
235 #if !defined(PNANOVDB_MEMCPY_CUSTOM)
236 #include <string.h>
237 #define pnanovdb_memcpy memcpy
238 #endif
239 typedef uint32_t pnanovdb_uint32_t;
240 typedef int32_t pnanovdb_int32_t;
241 typedef int32_t pnanovdb_bool_t;
242 #define PNANOVDB_FALSE 0
243 #define PNANOVDB_TRUE 1
244 typedef uint64_t pnanovdb_uint64_t;
245 typedef int64_t pnanovdb_int64_t;
246 typedef struct pnanovdb_coord_t
247 {
248     pnanovdb_int32_t x, y, z;
249 }pnanovdb_coord_t;
250 typedef struct pnanovdb_vec3_t
251 {
252     float x, y, z;
253 }pnanovdb_vec3_t;
pnanovdb_uint32_as_int32(pnanovdb_uint32_t v)254 PNANOVDB_FORCE_INLINE pnanovdb_int32_t pnanovdb_uint32_as_int32(pnanovdb_uint32_t v) { return (pnanovdb_int32_t)v; }
pnanovdb_uint64_as_int64(pnanovdb_uint64_t v)255 PNANOVDB_FORCE_INLINE pnanovdb_int64_t pnanovdb_uint64_as_int64(pnanovdb_uint64_t v) { return (pnanovdb_int64_t)v; }
pnanovdb_int64_as_uint64(pnanovdb_int64_t v)256 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_int64_as_uint64(pnanovdb_int64_t v) { return (pnanovdb_uint64_t)v; }
pnanovdb_int32_as_uint32(pnanovdb_int32_t v)257 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_int32_as_uint32(pnanovdb_int32_t v) { return (pnanovdb_uint32_t)v; }
pnanovdb_uint32_as_float(pnanovdb_uint32_t v)258 PNANOVDB_FORCE_INLINE float pnanovdb_uint32_as_float(pnanovdb_uint32_t v) { float vf; pnanovdb_memcpy(&vf, &v, sizeof(vf)); return vf; }
pnanovdb_uint64_as_double(pnanovdb_uint64_t v)259 PNANOVDB_FORCE_INLINE double pnanovdb_uint64_as_double(pnanovdb_uint64_t v) { double vf; pnanovdb_memcpy(&vf, &v, sizeof(vf)); return vf; }
pnanovdb_uint64_low(pnanovdb_uint64_t v)260 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_uint64_low(pnanovdb_uint64_t v) { return (pnanovdb_uint32_t)v; }
pnanovdb_uint64_high(pnanovdb_uint64_t v)261 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_uint64_high(pnanovdb_uint64_t v) { return (pnanovdb_uint32_t)(v >> 32u); }
pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x,pnanovdb_uint32_t y)262 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x, pnanovdb_uint32_t y) { return ((pnanovdb_uint64_t)x) | (((pnanovdb_uint64_t)y) << 32u); }
pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x)263 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x) { return ((pnanovdb_uint64_t)x); }
pnanovdb_uint64_is_equal(pnanovdb_uint64_t a,pnanovdb_uint64_t b)264 PNANOVDB_FORCE_INLINE pnanovdb_int32_t pnanovdb_uint64_is_equal(pnanovdb_uint64_t a, pnanovdb_uint64_t b) { return a == b; }
pnanovdb_int64_is_zero(pnanovdb_int64_t a)265 PNANOVDB_FORCE_INLINE pnanovdb_int32_t pnanovdb_int64_is_zero(pnanovdb_int64_t a) { return a == 0; }
266 #ifdef PNANOVDB_CMATH
pnanovdb_floor(float v)267 PNANOVDB_FORCE_INLINE float pnanovdb_floor(float v) { return floorf(v); }
268 #endif
pnanovdb_float_to_int32(float v)269 PNANOVDB_FORCE_INLINE pnanovdb_int32_t pnanovdb_float_to_int32(float v) { return (pnanovdb_int32_t)v; }
pnanovdb_int32_to_float(pnanovdb_int32_t v)270 PNANOVDB_FORCE_INLINE float pnanovdb_int32_to_float(pnanovdb_int32_t v) { return (float)v; }
pnanovdb_uint32_to_float(pnanovdb_uint32_t v)271 PNANOVDB_FORCE_INLINE float pnanovdb_uint32_to_float(pnanovdb_uint32_t v) { return (float)v; }
pnanovdb_min(float a,float b)272 PNANOVDB_FORCE_INLINE float pnanovdb_min(float a, float b) { return a < b ? a : b; }
pnanovdb_max(float a,float b)273 PNANOVDB_FORCE_INLINE float pnanovdb_max(float a, float b) { return a > b ? a : b; }
274 #elif defined(PNANOVDB_HLSL)
275 typedef uint pnanovdb_uint32_t;
276 typedef int pnanovdb_int32_t;
277 typedef bool pnanovdb_bool_t;
278 #define PNANOVDB_FALSE false
279 #define PNANOVDB_TRUE true
280 typedef int3 pnanovdb_coord_t;
281 typedef float3 pnanovdb_vec3_t;
pnanovdb_uint32_as_int32(pnanovdb_uint32_t v)282 pnanovdb_int32_t pnanovdb_uint32_as_int32(pnanovdb_uint32_t v) { return int(v); }
pnanovdb_int32_as_uint32(pnanovdb_int32_t v)283 pnanovdb_uint32_t pnanovdb_int32_as_uint32(pnanovdb_int32_t v) { return uint(v); }
pnanovdb_uint32_as_float(pnanovdb_uint32_t v)284 float pnanovdb_uint32_as_float(pnanovdb_uint32_t v) { return asfloat(v); }
pnanovdb_floor(float v)285 float pnanovdb_floor(float v) { return floor(v); }
pnanovdb_float_to_int32(float v)286 pnanovdb_int32_t pnanovdb_float_to_int32(float v) { return int(v); }
pnanovdb_int32_to_float(pnanovdb_int32_t v)287 float pnanovdb_int32_to_float(pnanovdb_int32_t v) { return float(v); }
pnanovdb_uint32_to_float(pnanovdb_uint32_t v)288 float pnanovdb_uint32_to_float(pnanovdb_uint32_t v) { return float(v); }
pnanovdb_min(float a,float b)289 float pnanovdb_min(float a, float b) { return min(a, b); }
pnanovdb_max(float a,float b)290 float pnanovdb_max(float a, float b) { return max(a, b); }
291 #if defined(PNANOVDB_ADDRESS_32)
292 typedef uint2 pnanovdb_uint64_t;
293 typedef int2 pnanovdb_int64_t;
pnanovdb_uint64_as_int64(pnanovdb_uint64_t v)294 pnanovdb_int64_t pnanovdb_uint64_as_int64(pnanovdb_uint64_t v) { return int2(v); }
pnanovdb_int64_as_uint64(pnanovdb_int64_t v)295 pnanovdb_uint64_t pnanovdb_int64_as_uint64(pnanovdb_int64_t v) { return uint2(v); }
pnanovdb_uint64_as_double(pnanovdb_uint64_t v)296 double pnanovdb_uint64_as_double(pnanovdb_uint64_t v) { return asdouble(v.x, v.y); }
pnanovdb_uint64_low(pnanovdb_uint64_t v)297 pnanovdb_uint32_t pnanovdb_uint64_low(pnanovdb_uint64_t v) { return v.x; }
pnanovdb_uint64_high(pnanovdb_uint64_t v)298 pnanovdb_uint32_t pnanovdb_uint64_high(pnanovdb_uint64_t v) { return v.y; }
pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x,pnanovdb_uint32_t y)299 pnanovdb_uint64_t pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x, pnanovdb_uint32_t y) { return uint2(x, y); }
pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x)300 pnanovdb_uint64_t pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x) { return uint2(x, 0); }
pnanovdb_uint64_is_equal(pnanovdb_uint64_t a,pnanovdb_uint64_t b)301 bool pnanovdb_uint64_is_equal(pnanovdb_uint64_t a, pnanovdb_uint64_t b) { return (a.x == b.x) && (a.y == b.y); }
pnanovdb_int64_is_zero(pnanovdb_int64_t a)302 bool pnanovdb_int64_is_zero(pnanovdb_int64_t a) { return a.x == 0 && a.y == 0; }
303 #else
304 typedef uint64_t pnanovdb_uint64_t;
305 typedef int64_t pnanovdb_int64_t;
pnanovdb_uint64_as_int64(pnanovdb_uint64_t v)306 pnanovdb_int64_t pnanovdb_uint64_as_int64(pnanovdb_uint64_t v) { return int64_t(v); }
pnanovdb_int64_as_uint64(pnanovdb_int64_t v)307 pnanovdb_uint64_t pnanovdb_int64_as_uint64(pnanovdb_int64_t v) { return uint64_t(v); }
pnanovdb_uint64_as_double(pnanovdb_uint64_t v)308 double pnanovdb_uint64_as_double(pnanovdb_uint64_t v) { return asdouble(uint(v), uint(v >> 32u)); }
pnanovdb_uint64_low(pnanovdb_uint64_t v)309 pnanovdb_uint32_t pnanovdb_uint64_low(pnanovdb_uint64_t v) { return uint(v); }
pnanovdb_uint64_high(pnanovdb_uint64_t v)310 pnanovdb_uint32_t pnanovdb_uint64_high(pnanovdb_uint64_t v) { return uint(v >> 32u); }
pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x,pnanovdb_uint32_t y)311 pnanovdb_uint64_t pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x, pnanovdb_uint32_t y) { return uint64_t(x) + (uint64_t(y) << 32u); }
pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x)312 pnanovdb_uint64_t pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x) { return uint64_t(x); }
pnanovdb_uint64_is_equal(pnanovdb_uint64_t a,pnanovdb_uint64_t b)313 bool pnanovdb_uint64_is_equal(pnanovdb_uint64_t a, pnanovdb_uint64_t b) { return a == b; }
pnanovdb_int64_is_zero(pnanovdb_int64_t a)314 bool pnanovdb_int64_is_zero(pnanovdb_int64_t a) { return a == 0; }
315 #endif
316 #elif defined(PNANOVDB_GLSL)
317 #define pnanovdb_uint32_t uint
318 #define pnanovdb_int32_t int
319 #define pnanovdb_bool_t bool
320 #define PNANOVDB_FALSE false
321 #define PNANOVDB_TRUE true
322 #define pnanovdb_uint64_t uvec2
323 #define pnanovdb_int64_t ivec2
324 #define pnanovdb_coord_t ivec3
325 #define pnanovdb_vec3_t vec3
pnanovdb_uint32_as_int32(pnanovdb_uint32_t v)326 pnanovdb_int32_t pnanovdb_uint32_as_int32(pnanovdb_uint32_t v) { return int(v); }
pnanovdb_uint64_as_int64(pnanovdb_uint64_t v)327 pnanovdb_int64_t pnanovdb_uint64_as_int64(pnanovdb_uint64_t v) { return ivec2(v); }
pnanovdb_int64_as_uint64(pnanovdb_int64_t v)328 pnanovdb_uint64_t pnanovdb_int64_as_uint64(pnanovdb_int64_t v) { return uvec2(v); }
pnanovdb_int32_as_uint32(pnanovdb_int32_t v)329 pnanovdb_uint32_t pnanovdb_int32_as_uint32(pnanovdb_int32_t v) { return uint(v); }
pnanovdb_uint32_as_float(pnanovdb_uint32_t v)330 float pnanovdb_uint32_as_float(pnanovdb_uint32_t v) { return uintBitsToFloat(v); }
pnanovdb_uint64_as_double(pnanovdb_uint64_t v)331 double pnanovdb_uint64_as_double(pnanovdb_uint64_t v) { return packDouble2x32(uvec2(v.x, v.y)); }
pnanovdb_uint64_low(pnanovdb_uint64_t v)332 pnanovdb_uint32_t pnanovdb_uint64_low(pnanovdb_uint64_t v) { return v.x; }
pnanovdb_uint64_high(pnanovdb_uint64_t v)333 pnanovdb_uint32_t pnanovdb_uint64_high(pnanovdb_uint64_t v) { return v.y; }
pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x,pnanovdb_uint32_t y)334 pnanovdb_uint64_t pnanovdb_uint32_as_uint64(pnanovdb_uint32_t x, pnanovdb_uint32_t y) { return uvec2(x, y); }
pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x)335 pnanovdb_uint64_t pnanovdb_uint32_as_uint64_low(pnanovdb_uint32_t x) { return uvec2(x, 0); }
pnanovdb_uint64_is_equal(pnanovdb_uint64_t a,pnanovdb_uint64_t b)336 bool pnanovdb_uint64_is_equal(pnanovdb_uint64_t a, pnanovdb_uint64_t b) { return (a.x == b.x) && (a.y == b.y); }
pnanovdb_int64_is_zero(pnanovdb_int64_t a)337 bool pnanovdb_int64_is_zero(pnanovdb_int64_t a) { return a.x == 0 && a.y == 0; }
pnanovdb_floor(float v)338 float pnanovdb_floor(float v) { return floor(v); }
pnanovdb_float_to_int32(float v)339 pnanovdb_int32_t pnanovdb_float_to_int32(float v) { return int(v); }
pnanovdb_int32_to_float(pnanovdb_int32_t v)340 float pnanovdb_int32_to_float(pnanovdb_int32_t v) { return float(v); }
pnanovdb_uint32_to_float(pnanovdb_uint32_t v)341 float pnanovdb_uint32_to_float(pnanovdb_uint32_t v) { return float(v); }
pnanovdb_min(float a,float b)342 float pnanovdb_min(float a, float b) { return min(a, b); }
pnanovdb_max(float a,float b)343 float pnanovdb_max(float a, float b) { return max(a, b); }
344 #endif
345 
346 // ------------------------------------------------ Coord/Vec3 Utilties -----------------------------------------------------------
347 
348 #if defined(PNANOVDB_C)
pnanovdb_vec3_uniform(float a)349 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_vec3_uniform(float a)
350 {
351     pnanovdb_vec3_t v;
352     v.x = a;
353     v.y = a;
354     v.z = a;
355     return v;
356 }
pnanovdb_vec3_add(const pnanovdb_vec3_t a,const pnanovdb_vec3_t b)357 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_vec3_add(const pnanovdb_vec3_t a, const pnanovdb_vec3_t b)
358 {
359     pnanovdb_vec3_t v;
360     v.x = a.x + b.x;
361     v.y = a.y + b.y;
362     v.z = a.z + b.z;
363     return v;
364 }
pnanovdb_vec3_sub(const pnanovdb_vec3_t a,const pnanovdb_vec3_t b)365 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_vec3_sub(const pnanovdb_vec3_t a, const pnanovdb_vec3_t b)
366 {
367     pnanovdb_vec3_t v;
368     v.x = a.x - b.x;
369     v.y = a.y - b.y;
370     v.z = a.z - b.z;
371     return v;
372 }
pnanovdb_vec3_mul(const pnanovdb_vec3_t a,const pnanovdb_vec3_t b)373 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_vec3_mul(const pnanovdb_vec3_t a, const pnanovdb_vec3_t b)
374 {
375     pnanovdb_vec3_t v;
376     v.x = a.x * b.x;
377     v.y = a.y * b.y;
378     v.z = a.z * b.z;
379     return v;
380 }
pnanovdb_vec3_div(const pnanovdb_vec3_t a,const pnanovdb_vec3_t b)381 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_vec3_div(const pnanovdb_vec3_t a, const pnanovdb_vec3_t b)
382 {
383     pnanovdb_vec3_t v;
384     v.x = a.x / b.x;
385     v.y = a.y / b.y;
386     v.z = a.z / b.z;
387     return v;
388 }
pnanovdb_vec3_min(const pnanovdb_vec3_t a,const pnanovdb_vec3_t b)389 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_vec3_min(const pnanovdb_vec3_t a, const pnanovdb_vec3_t b)
390 {
391     pnanovdb_vec3_t v;
392     v.x = a.x < b.x ? a.x : b.x;
393     v.y = a.y < b.y ? a.y : b.y;
394     v.z = a.z < b.z ? a.z : b.z;
395     return v;
396 }
pnanovdb_vec3_max(const pnanovdb_vec3_t a,const pnanovdb_vec3_t b)397 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_vec3_max(const pnanovdb_vec3_t a, const pnanovdb_vec3_t b)
398 {
399     pnanovdb_vec3_t v;
400     v.x = a.x > b.x ? a.x : b.x;
401     v.y = a.y > b.y ? a.y : b.y;
402     v.z = a.z > b.z ? a.z : b.z;
403     return v;
404 }
pnanovdb_coord_to_vec3(const pnanovdb_coord_t coord)405 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_coord_to_vec3(const pnanovdb_coord_t coord)
406 {
407     pnanovdb_vec3_t v;
408     v.x = pnanovdb_int32_to_float(coord.x);
409     v.y = pnanovdb_int32_to_float(coord.y);
410     v.z = pnanovdb_int32_to_float(coord.z);
411     return v;
412 }
pnanovdb_coord_uniform(const pnanovdb_int32_t a)413 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_coord_uniform(const pnanovdb_int32_t a)
414 {
415     pnanovdb_coord_t v;
416     v.x = a;
417     v.y = a;
418     v.z = a;
419     return v;
420 }
pnanovdb_coord_add(pnanovdb_coord_t a,pnanovdb_coord_t b)421 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_coord_add(pnanovdb_coord_t a, pnanovdb_coord_t b)
422 {
423     pnanovdb_coord_t v;
424     v.x = a.x + b.x;
425     v.y = a.y + b.y;
426     v.z = a.z + b.z;
427     return v;
428 }
429 #elif defined(PNANOVDB_HLSL)
pnanovdb_vec3_uniform(float a)430 pnanovdb_vec3_t pnanovdb_vec3_uniform(float a) { return float3(a, a, a); }
pnanovdb_vec3_add(pnanovdb_vec3_t a,pnanovdb_vec3_t b)431 pnanovdb_vec3_t pnanovdb_vec3_add(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a + b; }
pnanovdb_vec3_sub(pnanovdb_vec3_t a,pnanovdb_vec3_t b)432 pnanovdb_vec3_t pnanovdb_vec3_sub(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a - b; }
pnanovdb_vec3_mul(pnanovdb_vec3_t a,pnanovdb_vec3_t b)433 pnanovdb_vec3_t pnanovdb_vec3_mul(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a * b; }
pnanovdb_vec3_div(pnanovdb_vec3_t a,pnanovdb_vec3_t b)434 pnanovdb_vec3_t pnanovdb_vec3_div(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a / b; }
pnanovdb_vec3_min(pnanovdb_vec3_t a,pnanovdb_vec3_t b)435 pnanovdb_vec3_t pnanovdb_vec3_min(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return min(a, b); }
pnanovdb_vec3_max(pnanovdb_vec3_t a,pnanovdb_vec3_t b)436 pnanovdb_vec3_t pnanovdb_vec3_max(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return max(a, b); }
pnanovdb_coord_to_vec3(pnanovdb_coord_t coord)437 pnanovdb_vec3_t pnanovdb_coord_to_vec3(pnanovdb_coord_t coord) { return float3(coord); }
pnanovdb_coord_uniform(pnanovdb_int32_t a)438 pnanovdb_coord_t pnanovdb_coord_uniform(pnanovdb_int32_t a) { return int3(a, a, a); }
pnanovdb_coord_add(pnanovdb_coord_t a,pnanovdb_coord_t b)439 pnanovdb_coord_t pnanovdb_coord_add(pnanovdb_coord_t a, pnanovdb_coord_t b) { return a + b; }
440 #elif defined(PNANOVDB_GLSL)
pnanovdb_vec3_uniform(float a)441 pnanovdb_vec3_t pnanovdb_vec3_uniform(float a) { return vec3(a, a, a); }
pnanovdb_vec3_add(pnanovdb_vec3_t a,pnanovdb_vec3_t b)442 pnanovdb_vec3_t pnanovdb_vec3_add(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a + b; }
pnanovdb_vec3_sub(pnanovdb_vec3_t a,pnanovdb_vec3_t b)443 pnanovdb_vec3_t pnanovdb_vec3_sub(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a - b; }
pnanovdb_vec3_mul(pnanovdb_vec3_t a,pnanovdb_vec3_t b)444 pnanovdb_vec3_t pnanovdb_vec3_mul(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a * b; }
pnanovdb_vec3_div(pnanovdb_vec3_t a,pnanovdb_vec3_t b)445 pnanovdb_vec3_t pnanovdb_vec3_div(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return a / b; }
pnanovdb_vec3_min(pnanovdb_vec3_t a,pnanovdb_vec3_t b)446 pnanovdb_vec3_t pnanovdb_vec3_min(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return min(a, b); }
pnanovdb_vec3_max(pnanovdb_vec3_t a,pnanovdb_vec3_t b)447 pnanovdb_vec3_t pnanovdb_vec3_max(pnanovdb_vec3_t a, pnanovdb_vec3_t b) { return max(a, b); }
pnanovdb_coord_to_vec3(const pnanovdb_coord_t coord)448 pnanovdb_vec3_t pnanovdb_coord_to_vec3(const pnanovdb_coord_t coord) { return vec3(coord); }
pnanovdb_coord_uniform(pnanovdb_int32_t a)449 pnanovdb_coord_t pnanovdb_coord_uniform(pnanovdb_int32_t a) { return ivec3(a, a, a); }
pnanovdb_coord_add(pnanovdb_coord_t a,pnanovdb_coord_t b)450 pnanovdb_coord_t pnanovdb_coord_add(pnanovdb_coord_t a, pnanovdb_coord_t b) { return a + b; }
451 #endif
452 
453 // ------------------------------------------------ Address Type -----------------------------------------------------------
454 
455 #if defined(PNANOVDB_ADDRESS_32)
456 struct pnanovdb_address_t
457 {
458     pnanovdb_uint32_t byte_offset;
459 };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_address_t)460 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_address_t)
461 
462 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset(pnanovdb_address_t address, pnanovdb_uint32_t byte_offset)
463 {
464     pnanovdb_address_t ret = address;
465     ret.byte_offset += byte_offset;
466     return ret;
467 }
pnanovdb_address_offset_neg(pnanovdb_address_t address,pnanovdb_uint32_t byte_offset)468 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset_neg(pnanovdb_address_t address, pnanovdb_uint32_t byte_offset)
469 {
470     pnanovdb_address_t ret = address;
471     ret.byte_offset -= byte_offset;
472     return ret;
473 }
pnanovdb_address_offset_product(pnanovdb_address_t address,pnanovdb_uint32_t byte_offset,pnanovdb_uint32_t multiplier)474 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset_product(pnanovdb_address_t address, pnanovdb_uint32_t byte_offset, pnanovdb_uint32_t multiplier)
475 {
476     pnanovdb_address_t ret = address;
477     ret.byte_offset += byte_offset * multiplier;
478     return ret;
479 }
pnanovdb_address_offset64(pnanovdb_address_t address,pnanovdb_uint64_t byte_offset)480 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset64(pnanovdb_address_t address, pnanovdb_uint64_t byte_offset)
481 {
482     pnanovdb_address_t ret = address;
483     // lose high bits on 32-bit
484     ret.byte_offset += pnanovdb_uint64_low(byte_offset);
485     return ret;
486 }
pnanovdb_address_mask(pnanovdb_address_t address,pnanovdb_uint32_t mask)487 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_address_mask(pnanovdb_address_t address, pnanovdb_uint32_t mask)
488 {
489     return address.byte_offset & mask;
490 }
pnanovdb_address_mask_inv(pnanovdb_address_t address,pnanovdb_uint32_t mask)491 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_mask_inv(pnanovdb_address_t address, pnanovdb_uint32_t mask)
492 {
493     pnanovdb_address_t ret = address;
494     ret.byte_offset &= (~mask);
495     return ret;
496 }
pnanovdb_address_null()497 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_null()
498 {
499     pnanovdb_address_t ret = { 0 };
500     return ret;
501 }
pnanovdb_address_is_null(pnanovdb_address_t address)502 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_address_is_null(pnanovdb_address_t address)
503 {
504     return address.byte_offset == 0u;
505 }
pnanovdb_address_in_interval(pnanovdb_address_t address,pnanovdb_address_t min_address,pnanovdb_address_t max_address)506 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_address_in_interval(pnanovdb_address_t address, pnanovdb_address_t min_address, pnanovdb_address_t max_address)
507 {
508     return address.byte_offset >= min_address.byte_offset && address.byte_offset < max_address.byte_offset;
509 }
510 #elif defined(PNANOVDB_ADDRESS_64)
511 struct pnanovdb_address_t
512 {
513     pnanovdb_uint64_t byte_offset;
514 };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_address_t)515 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_address_t)
516 
517 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset(pnanovdb_address_t address, pnanovdb_uint32_t byte_offset)
518 {
519     pnanovdb_address_t ret = address;
520     ret.byte_offset += byte_offset;
521     return ret;
522 }
pnanovdb_address_offset_neg(pnanovdb_address_t address,pnanovdb_uint32_t byte_offset)523 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset_neg(pnanovdb_address_t address, pnanovdb_uint32_t byte_offset)
524 {
525     pnanovdb_address_t ret = address;
526     ret.byte_offset -= byte_offset;
527     return ret;
528 }
pnanovdb_address_offset_product(pnanovdb_address_t address,pnanovdb_uint32_t byte_offset,pnanovdb_uint32_t multiplier)529 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset_product(pnanovdb_address_t address, pnanovdb_uint32_t byte_offset, pnanovdb_uint32_t multiplier)
530 {
531     pnanovdb_address_t ret = address;
532     ret.byte_offset += pnanovdb_uint32_as_uint64_low(byte_offset) * pnanovdb_uint32_as_uint64_low(multiplier);
533     return ret;
534 }
pnanovdb_address_offset64(pnanovdb_address_t address,pnanovdb_uint64_t byte_offset)535 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_offset64(pnanovdb_address_t address, pnanovdb_uint64_t byte_offset)
536 {
537     pnanovdb_address_t ret = address;
538     ret.byte_offset += byte_offset;
539     return ret;
540 }
pnanovdb_address_mask(pnanovdb_address_t address,pnanovdb_uint32_t mask)541 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_address_mask(pnanovdb_address_t address, pnanovdb_uint32_t mask)
542 {
543     return pnanovdb_uint64_low(address.byte_offset) & mask;
544 }
pnanovdb_address_mask_inv(pnanovdb_address_t address,pnanovdb_uint32_t mask)545 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_mask_inv(pnanovdb_address_t address, pnanovdb_uint32_t mask)
546 {
547     pnanovdb_address_t ret = address;
548     ret.byte_offset &= (~pnanovdb_uint32_as_uint64_low(mask));
549     return ret;
550 }
pnanovdb_address_null()551 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_address_null()
552 {
553     pnanovdb_address_t ret = { 0 };
554     return ret;
555 }
pnanovdb_address_is_null(pnanovdb_address_t address)556 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_address_is_null(pnanovdb_address_t address)
557 {
558     return address.byte_offset == 0llu;
559 }
pnanovdb_address_in_interval(pnanovdb_address_t address,pnanovdb_address_t min_address,pnanovdb_address_t max_address)560 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_address_in_interval(pnanovdb_address_t address, pnanovdb_address_t min_address, pnanovdb_address_t max_address)
561 {
562     return address.byte_offset >= min_address.byte_offset && address.byte_offset < max_address.byte_offset;
563 }
564 #endif
565 
566 // ------------------------------------------------ High Level Buffer Read -----------------------------------------------------------
567 
pnanovdb_read_uint32(pnanovdb_buf_t buf,pnanovdb_address_t address)568 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_read_uint32(pnanovdb_buf_t buf, pnanovdb_address_t address)
569 {
570     return pnanovdb_buf_read_uint32(buf, address.byte_offset);
571 }
pnanovdb_read_uint64(pnanovdb_buf_t buf,pnanovdb_address_t address)572 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_read_uint64(pnanovdb_buf_t buf, pnanovdb_address_t address)
573 {
574     return pnanovdb_buf_read_uint64(buf, address.byte_offset);
575 }
pnanovdb_read_int32(pnanovdb_buf_t buf,pnanovdb_address_t address)576 PNANOVDB_FORCE_INLINE pnanovdb_int32_t pnanovdb_read_int32(pnanovdb_buf_t buf, pnanovdb_address_t address)
577 {
578     return pnanovdb_uint32_as_int32(pnanovdb_read_uint32(buf, address));
579 }
pnanovdb_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address)580 PNANOVDB_FORCE_INLINE float pnanovdb_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address)
581 {
582     return pnanovdb_uint32_as_float(pnanovdb_read_uint32(buf, address));
583 }
pnanovdb_read_int64(pnanovdb_buf_t buf,pnanovdb_address_t address)584 PNANOVDB_FORCE_INLINE pnanovdb_int64_t pnanovdb_read_int64(pnanovdb_buf_t buf, pnanovdb_address_t address)
585 {
586     return pnanovdb_uint64_as_int64(pnanovdb_read_uint64(buf, address));
587 }
pnanovdb_read_double(pnanovdb_buf_t buf,pnanovdb_address_t address)588 PNANOVDB_FORCE_INLINE double pnanovdb_read_double(pnanovdb_buf_t buf, pnanovdb_address_t address)
589 {
590     return pnanovdb_uint64_as_double(pnanovdb_read_uint64(buf, address));
591 }
pnanovdb_read_coord(pnanovdb_buf_t buf,pnanovdb_address_t address)592 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_read_coord(pnanovdb_buf_t buf, pnanovdb_address_t address)
593 {
594     pnanovdb_coord_t ret;
595     ret.x = pnanovdb_uint32_as_int32(pnanovdb_read_uint32(buf, pnanovdb_address_offset(address, 0u)));
596     ret.y = pnanovdb_uint32_as_int32(pnanovdb_read_uint32(buf, pnanovdb_address_offset(address, 4u)));
597     ret.z = pnanovdb_uint32_as_int32(pnanovdb_read_uint32(buf, pnanovdb_address_offset(address, 8u)));
598     return ret;
599 }
600 
pnanovdb_read_bit(pnanovdb_buf_t buf,pnanovdb_address_t address,pnanovdb_uint32_t bit_offset)601 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_read_bit(pnanovdb_buf_t buf, pnanovdb_address_t address, pnanovdb_uint32_t bit_offset)
602 {
603     pnanovdb_address_t word_address = pnanovdb_address_mask_inv(address, 3u);
604     pnanovdb_uint32_t bit_index = (pnanovdb_address_mask(address, 3u) << 3u) + bit_offset;
605     pnanovdb_uint32_t value_word = pnanovdb_buf_read_uint32(buf, word_address.byte_offset);
606     return ((value_word >> bit_index) & 1) != 0u;
607 }
608 
609 #if defined(PNANOVDB_C)
pnanovdb_read_half(pnanovdb_buf_t buf,pnanovdb_address_t address)610 PNANOVDB_FORCE_INLINE short pnanovdb_read_half(pnanovdb_buf_t buf, pnanovdb_address_t address)
611 {
612     pnanovdb_uint32_t raw = pnanovdb_read_uint32(buf, address);
613     return (short)(raw >> (pnanovdb_address_mask(address, 2) << 3));
614 }
615 #elif defined(PNANOVDB_HLSL)
pnanovdb_read_half(pnanovdb_buf_t buf,pnanovdb_address_t address)616 PNANOVDB_FORCE_INLINE float pnanovdb_read_half(pnanovdb_buf_t buf, pnanovdb_address_t address)
617 {
618     pnanovdb_uint32_t raw = pnanovdb_read_uint32(buf, address);
619     return f16tof32(raw >> (pnanovdb_address_mask(address, 2) << 3));
620 }
621 #elif defined(PNANOVDB_GLSL)
pnanovdb_read_half(pnanovdb_buf_t buf,pnanovdb_address_t address)622 PNANOVDB_FORCE_INLINE float pnanovdb_read_half(pnanovdb_buf_t buf, pnanovdb_address_t address)
623 {
624     pnanovdb_uint32_t raw = pnanovdb_read_uint32(buf, address);
625     return unpackHalf2x16(raw >> (pnanovdb_address_mask(address, 2) << 3)).x;
626 }
627 #endif
628 
629 // ------------------------------------------------ Core Structures -----------------------------------------------------------
630 
631 #define PNANOVDB_MAGIC_NUMBER 0x304244566f6e614eUL// "NanoVDB0" in hex - little endian (uint64_t)
632 
633 #define PNANOVDB_MAJOR_VERSION_NUMBER 32// reflects changes to the ABI
634 #define PNANOVDB_MINOR_VERSION_NUMBER  3// reflects changes to the API but not ABI
635 #define PNANOVDB_PATCH_VERSION_NUMBER  3// reflects bug-fixes with no ABI or API changes
636 
637 #define PNANOVDB_GRID_TYPE_UNKNOWN 0
638 #define PNANOVDB_GRID_TYPE_FLOAT 1
639 #define PNANOVDB_GRID_TYPE_DOUBLE 2
640 #define PNANOVDB_GRID_TYPE_INT16 3
641 #define PNANOVDB_GRID_TYPE_INT32 4
642 #define PNANOVDB_GRID_TYPE_INT64 5
643 #define PNANOVDB_GRID_TYPE_VEC3F 6
644 #define PNANOVDB_GRID_TYPE_VEC3D 7
645 #define PNANOVDB_GRID_TYPE_MASK 8
646 #define PNANOVDB_GRID_TYPE_HALF 9
647 #define PNANOVDB_GRID_TYPE_UINT32 10
648 #define PNANOVDB_GRID_TYPE_BOOLEAN 11
649 #define PNANOVDB_GRID_TYPE_RGBA8 12
650 #define PNANOVDB_GRID_TYPE_FP4 13
651 #define PNANOVDB_GRID_TYPE_FP8 14
652 #define PNANOVDB_GRID_TYPE_FP16 15
653 #define PNANOVDB_GRID_TYPE_FPN 16
654 #define PNANOVDB_GRID_TYPE_VEC4F 17
655 #define PNANOVDB_GRID_TYPE_VEC4D 18
656 #define PNANOVDB_GRID_TYPE_END 19
657 
658 #define PNANOVDB_GRID_CLASS_UNKNOWN 0
659 #define PNANOVDB_GRID_CLASS_LEVEL_SET 1     // narrow band levelset, e.g. SDF
660 #define PNANOVDB_GRID_CLASS_FOG_VOLUME 2    // fog volume, e.g. density
661 #define PNANOVDB_GRID_CLASS_STAGGERED 3     // staggered MAC grid, e.g. velocity
662 #define PNANOVDB_GRID_CLASS_POINT_INDEX 4   // point index grid
663 #define PNANOVDB_GRID_CLASS_POINT_DATA 5    // point data grid
664 #define PNANOVDB_GRID_CLASS_TOPOLOGY 6      // grid with active states only (no values)
665 #define PNANOVDB_GRID_CLASS_VOXEL_VOLUME 7  // volume of geometric cubes, e.g. minecraft
666 #define PNANOVDB_GRID_CLASS_END 8
667 
668 #define PNANOVDB_GRID_FLAGS_HAS_LONG_GRID_NAME (1 << 0)
669 #define PNANOVDB_GRID_FLAGS_HAS_BBOX (1 << 1)
670 #define PNANOVDB_GRID_FLAGS_HAS_MIN_MAX (1 << 2)
671 #define PNANOVDB_GRID_FLAGS_HAS_AVERAGE (1 << 3)
672 #define PNANOVDB_GRID_FLAGS_HAS_STD_DEVIATION (1 << 4)
673 #define PNANOVDB_GRID_FLAGS_IS_BREADTH_FIRST (1 << 5)
674 #define PNANOVDB_GRID_FLAGS_END (1 << 6)
675 
676 #define PNANOVDB_LEAF_TYPE_DEFAULT 0
677 #define PNANOVDB_LEAF_TYPE_LITE 1
678 #define PNANOVDB_LEAF_TYPE_FP 2
679 
680 PNANOVDB_STATIC_CONST pnanovdb_uint32_t pnanovdb_grid_type_value_strides_bits[PNANOVDB_GRID_TYPE_END]  = {  0, 32, 64, 16, 32, 64, 96,  192,  0, 16, 32,  1, 32,  4,  8, 16,  0, 128, 256 };
681 PNANOVDB_STATIC_CONST pnanovdb_uint32_t pnanovdb_grid_type_table_strides_bits[PNANOVDB_GRID_TYPE_END] =  { 64, 64, 64, 64, 64, 64, 128, 192, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 256 };
682 PNANOVDB_STATIC_CONST pnanovdb_uint32_t pnanovdb_grid_type_minmax_strides_bits[PNANOVDB_GRID_TYPE_END] = {  0, 32, 64, 16, 32, 64, 96,  192,  8, 16, 32,  8, 32, 32, 32, 32, 32, 128, 256 };
683 PNANOVDB_STATIC_CONST pnanovdb_uint32_t pnanovdb_grid_type_minmax_aligns_bits[PNANOVDB_GRID_TYPE_END]  = {  0, 32, 64, 16, 32, 64, 32,   64,  8, 16, 32,  8, 32, 32, 32, 32, 32,  32,  64 };
684 PNANOVDB_STATIC_CONST pnanovdb_uint32_t pnanovdb_grid_type_stat_strides_bits[PNANOVDB_GRID_TYPE_END]   = {  0, 32, 64, 32, 32, 64, 32,   64,  8, 32, 32,  8, 32, 32, 32, 32, 32,  32,  64 };
685 PNANOVDB_STATIC_CONST pnanovdb_uint32_t pnanovdb_grid_type_leaf_type[PNANOVDB_GRID_TYPE_END]           = {  0,  0,  0,  0,  0,  0,  0,    0,  1,  0,  0,  1,  0,  2,  2,  2,  2,   0,   0 };
686 
687 struct pnanovdb_map_t
688 {
689     float matf[9];
690     float invmatf[9];
691     float vecf[3];
692     float taperf;
693     double matd[9];
694     double invmatd[9];
695     double vecd[3];
696     double taperd;
697 };
698 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_map_t)
699 struct pnanovdb_map_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_map_handle_t)700 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_map_handle_t)
701 
702 #define PNANOVDB_MAP_SIZE 264
703 
704 #define PNANOVDB_MAP_OFF_MATF 0
705 #define PNANOVDB_MAP_OFF_INVMATF 36
706 #define PNANOVDB_MAP_OFF_VECF 72
707 #define PNANOVDB_MAP_OFF_TAPERF 84
708 #define PNANOVDB_MAP_OFF_MATD 88
709 #define PNANOVDB_MAP_OFF_INVMATD 160
710 #define PNANOVDB_MAP_OFF_VECD 232
711 #define PNANOVDB_MAP_OFF_TAPERD 256
712 
713 PNANOVDB_FORCE_INLINE float pnanovdb_map_get_matf(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
714     return pnanovdb_read_float(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_MATF + 4u * index));
715 }
pnanovdb_map_get_invmatf(pnanovdb_buf_t buf,pnanovdb_map_handle_t p,pnanovdb_uint32_t index)716 PNANOVDB_FORCE_INLINE float pnanovdb_map_get_invmatf(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
717     return pnanovdb_read_float(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_INVMATF + 4u * index));
718 }
pnanovdb_map_get_vecf(pnanovdb_buf_t buf,pnanovdb_map_handle_t p,pnanovdb_uint32_t index)719 PNANOVDB_FORCE_INLINE float pnanovdb_map_get_vecf(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
720     return pnanovdb_read_float(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_VECF + 4u * index));
721 }
pnanovdb_map_get_taperf(pnanovdb_buf_t buf,pnanovdb_map_handle_t p,pnanovdb_uint32_t index)722 PNANOVDB_FORCE_INLINE float pnanovdb_map_get_taperf(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
723     return pnanovdb_read_float(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_TAPERF));
724 }
pnanovdb_map_get_matd(pnanovdb_buf_t buf,pnanovdb_map_handle_t p,pnanovdb_uint32_t index)725 PNANOVDB_FORCE_INLINE double pnanovdb_map_get_matd(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
726     return pnanovdb_read_double(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_MATD + 8u * index));
727 }
pnanovdb_map_get_invmatd(pnanovdb_buf_t buf,pnanovdb_map_handle_t p,pnanovdb_uint32_t index)728 PNANOVDB_FORCE_INLINE double pnanovdb_map_get_invmatd(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
729     return pnanovdb_read_double(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_INVMATD + 8u * index));
730 }
pnanovdb_map_get_vecd(pnanovdb_buf_t buf,pnanovdb_map_handle_t p,pnanovdb_uint32_t index)731 PNANOVDB_FORCE_INLINE double pnanovdb_map_get_vecd(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
732     return pnanovdb_read_double(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_VECD + 8u * index));
733 }
pnanovdb_map_get_taperd(pnanovdb_buf_t buf,pnanovdb_map_handle_t p,pnanovdb_uint32_t index)734 PNANOVDB_FORCE_INLINE double pnanovdb_map_get_taperd(pnanovdb_buf_t buf, pnanovdb_map_handle_t p, pnanovdb_uint32_t index) {
735     return pnanovdb_read_double(buf, pnanovdb_address_offset(p.address, PNANOVDB_MAP_OFF_TAPERD));
736 }
737 
738 struct pnanovdb_grid_t
739 {
740     pnanovdb_uint64_t magic;                    // 8 bytes,     0
741     pnanovdb_uint64_t checksum;                 // 8 bytes,     8
742     pnanovdb_uint32_t version;                  // 4 bytes,     16
743     pnanovdb_uint32_t flags;                    // 4 bytes,     20
744     pnanovdb_uint32_t grid_index;               // 4 bytes,     24
745     pnanovdb_uint32_t grid_count;               // 4 bytes,     28
746     pnanovdb_uint64_t grid_size;                // 8 bytes,     32
747     pnanovdb_uint32_t grid_name[256 / 4];       // 256 bytes,   40
748     pnanovdb_map_t map;                         // 264 bytes,   296
749     double world_bbox[6];                       // 48 bytes,    560
750     double voxel_size[3];                       // 24 bytes,    608
751     pnanovdb_uint32_t grid_class;               // 4 bytes,     632
752     pnanovdb_uint32_t grid_type;                // 4 bytes,     636
753     pnanovdb_int64_t blind_metadata_offset;     // 8 bytes,     640
754     pnanovdb_uint32_t blind_metadata_count;     // 4 bytes,     648
755     pnanovdb_uint32_t pad[5];                   // 20 bytes,    652
756 };
757 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_grid_t)
758 struct pnanovdb_grid_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_grid_handle_t)759 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_grid_handle_t)
760 
761 #define PNANOVDB_GRID_SIZE 672
762 
763 #define PNANOVDB_GRID_OFF_MAGIC 0
764 #define PNANOVDB_GRID_OFF_CHECKSUM 8
765 #define PNANOVDB_GRID_OFF_VERSION 16
766 #define PNANOVDB_GRID_OFF_FLAGS 20
767 #define PNANOVDB_GRID_OFF_GRID_INDEX 24
768 #define PNANOVDB_GRID_OFF_GRID_COUNT 28
769 #define PNANOVDB_GRID_OFF_GRID_SIZE 32
770 #define PNANOVDB_GRID_OFF_GRID_NAME 40
771 #define PNANOVDB_GRID_OFF_MAP 296
772 #define PNANOVDB_GRID_OFF_WORLD_BBOX 560
773 #define PNANOVDB_GRID_OFF_VOXEL_SIZE 608
774 #define PNANOVDB_GRID_OFF_GRID_CLASS 632
775 #define PNANOVDB_GRID_OFF_GRID_TYPE 636
776 #define PNANOVDB_GRID_OFF_BLIND_METADATA_OFFSET 640
777 #define PNANOVDB_GRID_OFF_BLIND_METADATA_COUNT 648
778 
779 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_grid_get_magic(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
780     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_MAGIC));
781 }
pnanovdb_grid_get_checksum(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)782 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_grid_get_checksum(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
783     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_CHECKSUM));
784 }
pnanovdb_grid_get_version(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)785 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_version(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
786     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_VERSION));
787 }
pnanovdb_grid_get_flags(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)788 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_flags(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
789     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_FLAGS));
790 }
pnanovdb_grid_get_grid_index(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)791 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_grid_index(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
792     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_GRID_INDEX));
793 }
pnanovdb_grid_get_grid_count(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)794 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_grid_count(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
795     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_GRID_COUNT));
796 }
pnanovdb_grid_get_grid_size(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)797 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_grid_get_grid_size(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
798     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_GRID_SIZE));
799 }
pnanovdb_grid_get_grid_name(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p,pnanovdb_uint32_t index)800 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_grid_name(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p, pnanovdb_uint32_t index) {
801     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_GRID_NAME + 4u * index));
802 }
pnanovdb_grid_get_map(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)803 PNANOVDB_FORCE_INLINE pnanovdb_map_handle_t pnanovdb_grid_get_map(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
804     pnanovdb_map_handle_t ret;
805     ret.address = pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_MAP);
806     return ret;
807 }
pnanovdb_grid_get_world_bbox(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p,pnanovdb_uint32_t index)808 PNANOVDB_FORCE_INLINE double pnanovdb_grid_get_world_bbox(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p, pnanovdb_uint32_t index) {
809     return pnanovdb_read_double(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_WORLD_BBOX + 8u * index));
810 }
pnanovdb_grid_get_voxel_size(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p,pnanovdb_uint32_t index)811 PNANOVDB_FORCE_INLINE double pnanovdb_grid_get_voxel_size(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p, pnanovdb_uint32_t index) {
812     return pnanovdb_read_double(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_VOXEL_SIZE + 8u * index));
813 }
pnanovdb_grid_get_grid_class(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)814 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_grid_class(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
815     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_GRID_CLASS));
816 }
pnanovdb_grid_get_grid_type(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)817 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_grid_type(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
818     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_GRID_TYPE));
819 }
pnanovdb_grid_get_blind_metadata_offset(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)820 PNANOVDB_FORCE_INLINE pnanovdb_int64_t pnanovdb_grid_get_blind_metadata_offset(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
821     return pnanovdb_read_int64(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_BLIND_METADATA_OFFSET));
822 }
pnanovdb_grid_get_blind_metadata_count(pnanovdb_buf_t buf,pnanovdb_grid_handle_t p)823 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_grid_get_blind_metadata_count(pnanovdb_buf_t buf, pnanovdb_grid_handle_t p) {
824     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRID_OFF_BLIND_METADATA_COUNT));
825 }
826 
pnanovdb_version_get_major(pnanovdb_uint32_t version)827 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_version_get_major(pnanovdb_uint32_t version)
828 {
829     return (version >> 21u) & ((1u << 11u) - 1u);
830 }
pnanovdb_version_get_minor(pnanovdb_uint32_t version)831 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_version_get_minor(pnanovdb_uint32_t version)
832 {
833     return (version >> 10u) & ((1u << 11u) - 1u);
834 }
pnanovdb_version_get_patch(pnanovdb_uint32_t version)835 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_version_get_patch(pnanovdb_uint32_t version)
836 {
837     return version & ((1u << 10u) - 1u);
838 }
839 
840 struct pnanovdb_gridblindmetadata_t
841 {
842     pnanovdb_int64_t byte_offset;       // 8 bytes,     0
843     pnanovdb_uint64_t element_count;    // 8 bytes,     8
844     pnanovdb_uint32_t flags;            // 4 bytes,     16
845     pnanovdb_uint32_t semantic;         // 4 bytes,     20
846     pnanovdb_uint32_t data_class;       // 4 bytes,     24
847     pnanovdb_uint32_t data_type;        // 4 bytes,     28
848     pnanovdb_uint32_t name[256 / 4];    // 256 bytes,   32
849 };
850 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_gridblindmetadata_t)
851 struct pnanovdb_gridblindmetadata_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_gridblindmetadata_handle_t)852 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_gridblindmetadata_handle_t)
853 
854 #define PNANOVDB_GRIDBLINDMETADATA_SIZE 288
855 
856 #define PNANOVDB_GRIDBLINDMETADATA_OFF_BYTE_OFFSET 0
857 #define PNANOVDB_GRIDBLINDMETADATA_OFF_ELEMENT_COUNT 8
858 #define PNANOVDB_GRIDBLINDMETADATA_OFF_FLAGS 16
859 #define PNANOVDB_GRIDBLINDMETADATA_OFF_SEMANTIC 20
860 #define PNANOVDB_GRIDBLINDMETADATA_OFF_DATA_CLASS 24
861 #define PNANOVDB_GRIDBLINDMETADATA_OFF_DATA_TYPE 28
862 #define PNANOVDB_GRIDBLINDMETADATA_OFF_NAME 32
863 
864 PNANOVDB_FORCE_INLINE pnanovdb_int64_t pnanovdb_gridblindmetadata_get_byte_offset(pnanovdb_buf_t buf, pnanovdb_gridblindmetadata_handle_t p) {
865     return pnanovdb_read_int64(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRIDBLINDMETADATA_OFF_BYTE_OFFSET));
866 }
pnanovdb_gridblindmetadata_get_element_count(pnanovdb_buf_t buf,pnanovdb_gridblindmetadata_handle_t p)867 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_gridblindmetadata_get_element_count(pnanovdb_buf_t buf, pnanovdb_gridblindmetadata_handle_t p) {
868     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRIDBLINDMETADATA_OFF_ELEMENT_COUNT));
869 }
pnanovdb_gridblindmetadata_get_flags(pnanovdb_buf_t buf,pnanovdb_gridblindmetadata_handle_t p)870 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_gridblindmetadata_get_flags(pnanovdb_buf_t buf, pnanovdb_gridblindmetadata_handle_t p) {
871     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRIDBLINDMETADATA_OFF_FLAGS));
872 }
pnanovdb_gridblindmetadata_get_semantic(pnanovdb_buf_t buf,pnanovdb_gridblindmetadata_handle_t p)873 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_gridblindmetadata_get_semantic(pnanovdb_buf_t buf, pnanovdb_gridblindmetadata_handle_t p) {
874     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRIDBLINDMETADATA_OFF_SEMANTIC));
875 }
pnanovdb_gridblindmetadata_get_data_class(pnanovdb_buf_t buf,pnanovdb_gridblindmetadata_handle_t p)876 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_gridblindmetadata_get_data_class(pnanovdb_buf_t buf, pnanovdb_gridblindmetadata_handle_t p) {
877     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRIDBLINDMETADATA_OFF_DATA_CLASS));
878 }
pnanovdb_gridblindmetadata_get_data_type(pnanovdb_buf_t buf,pnanovdb_gridblindmetadata_handle_t p)879 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_gridblindmetadata_get_data_type(pnanovdb_buf_t buf, pnanovdb_gridblindmetadata_handle_t p) {
880     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRIDBLINDMETADATA_OFF_DATA_TYPE));
881 }
pnanovdb_gridblindmetadata_get_name(pnanovdb_buf_t buf,pnanovdb_gridblindmetadata_handle_t p,pnanovdb_uint32_t index)882 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_gridblindmetadata_get_name(pnanovdb_buf_t buf, pnanovdb_gridblindmetadata_handle_t p, pnanovdb_uint32_t index) {
883     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_GRIDBLINDMETADATA_OFF_NAME + 4u * index));
884 }
885 
886 struct pnanovdb_tree_t
887 {
888     pnanovdb_uint64_t node_offset_leaf;
889     pnanovdb_uint64_t node_offset_lower;
890     pnanovdb_uint64_t node_offset_upper;
891     pnanovdb_uint64_t node_offset_root;
892     pnanovdb_uint32_t node_count_leaf;
893     pnanovdb_uint32_t node_count_lower;
894     pnanovdb_uint32_t node_count_upper;
895     pnanovdb_uint32_t tile_count_leaf;
896     pnanovdb_uint32_t tile_count_lower;
897     pnanovdb_uint32_t tile_count_upper;
898     pnanovdb_uint64_t voxel_count;
899 };
900 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_tree_t)
901 struct pnanovdb_tree_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_tree_handle_t)902 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_tree_handle_t)
903 
904 #define PNANOVDB_TREE_SIZE 64
905 
906 #define PNANOVDB_TREE_OFF_NODE_OFFSET_LEAF 0
907 #define PNANOVDB_TREE_OFF_NODE_OFFSET_LOWER 8
908 #define PNANOVDB_TREE_OFF_NODE_OFFSET_UPPER 16
909 #define PNANOVDB_TREE_OFF_NODE_OFFSET_ROOT 24
910 #define PNANOVDB_TREE_OFF_NODE_COUNT_LEAF 32
911 #define PNANOVDB_TREE_OFF_NODE_COUNT_LOWER 36
912 #define PNANOVDB_TREE_OFF_NODE_COUNT_UPPER 40
913 #define PNANOVDB_TREE_OFF_TILE_COUNT_LEAF 44
914 #define PNANOVDB_TREE_OFF_TILE_COUNT_LOWER 48
915 #define PNANOVDB_TREE_OFF_TILE_COUNT_UPPER 52
916 #define PNANOVDB_TREE_OFF_VOXEL_COUNT 56
917 
918 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_tree_get_node_offset_leaf(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
919     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_NODE_OFFSET_LEAF));
920 }
pnanovdb_tree_get_node_offset_lower(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)921 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_tree_get_node_offset_lower(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
922     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_NODE_OFFSET_LOWER));
923 }
pnanovdb_tree_get_node_offset_upper(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)924 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_tree_get_node_offset_upper(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
925     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_NODE_OFFSET_UPPER));
926 }
pnanovdb_tree_get_node_offset_root(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)927 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_tree_get_node_offset_root(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
928     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_NODE_OFFSET_ROOT));
929 }
pnanovdb_tree_get_node_count_leaf(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)930 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_tree_get_node_count_leaf(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
931     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_NODE_COUNT_LEAF));
932 }
pnanovdb_tree_get_node_count_lower(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)933 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_tree_get_node_count_lower(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
934     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_NODE_COUNT_LOWER));
935 }
pnanovdb_tree_get_node_count_upper(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)936 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_tree_get_node_count_upper(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
937     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_NODE_COUNT_UPPER));
938 }
pnanovdb_tree_get_tile_count_leaf(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)939 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_tree_get_tile_count_leaf(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
940     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_TILE_COUNT_LEAF));
941 }
pnanovdb_tree_get_tile_count_lower(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)942 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_tree_get_tile_count_lower(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
943     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_TILE_COUNT_LOWER));
944 }
pnanovdb_tree_get_tile_count_upper(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)945 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_tree_get_tile_count_upper(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
946     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_TILE_COUNT_UPPER));
947 }
pnanovdb_tree_get_voxel_count(pnanovdb_buf_t buf,pnanovdb_tree_handle_t p)948 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_tree_get_voxel_count(pnanovdb_buf_t buf, pnanovdb_tree_handle_t p) {
949     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_TREE_OFF_VOXEL_COUNT));
950 }
951 
952 struct pnanovdb_root_t
953 {
954     pnanovdb_coord_t bbox_min;
955     pnanovdb_coord_t bbox_max;
956     pnanovdb_uint32_t table_size;
957     pnanovdb_uint32_t pad1;         // background can start here
958     // background, min, max
959 };
960 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_root_t)
961 struct pnanovdb_root_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_root_handle_t)962 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_root_handle_t)
963 
964 #define PNANOVDB_ROOT_BASE_SIZE 28
965 
966 #define PNANOVDB_ROOT_OFF_BBOX_MIN 0
967 #define PNANOVDB_ROOT_OFF_BBOX_MAX 12
968 #define PNANOVDB_ROOT_OFF_TABLE_SIZE 24
969 
970 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_root_get_bbox_min(pnanovdb_buf_t buf, pnanovdb_root_handle_t p) {
971     return pnanovdb_read_coord(buf, pnanovdb_address_offset(p.address, PNANOVDB_ROOT_OFF_BBOX_MIN));
972 }
pnanovdb_root_get_bbox_max(pnanovdb_buf_t buf,pnanovdb_root_handle_t p)973 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_root_get_bbox_max(pnanovdb_buf_t buf, pnanovdb_root_handle_t p) {
974     return pnanovdb_read_coord(buf, pnanovdb_address_offset(p.address, PNANOVDB_ROOT_OFF_BBOX_MAX));
975 }
pnanovdb_root_get_tile_count(pnanovdb_buf_t buf,pnanovdb_root_handle_t p)976 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_root_get_tile_count(pnanovdb_buf_t buf, pnanovdb_root_handle_t p) {
977     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_ROOT_OFF_TABLE_SIZE));
978 }
979 
980 struct pnanovdb_root_tile_t
981 {
982     pnanovdb_uint64_t key;
983     pnanovdb_int64_t child;         // signed byte offset from root to the child node, 0 means it is a constant tile, so use value
984     pnanovdb_uint32_t state;
985     pnanovdb_uint32_t pad1;         // value can start here
986     // value
987 };
988 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_root_tile_t)
989 struct pnanovdb_root_tile_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_root_tile_handle_t)990 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_root_tile_handle_t)
991 
992 #define PNANOVDB_ROOT_TILE_BASE_SIZE 20
993 
994 #define PNANOVDB_ROOT_TILE_OFF_KEY 0
995 #define PNANOVDB_ROOT_TILE_OFF_CHILD 8
996 #define PNANOVDB_ROOT_TILE_OFF_STATE 16
997 
998 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_root_tile_get_key(pnanovdb_buf_t buf, pnanovdb_root_tile_handle_t p) {
999     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_ROOT_TILE_OFF_KEY));
1000 }
pnanovdb_root_tile_get_child(pnanovdb_buf_t buf,pnanovdb_root_tile_handle_t p)1001 PNANOVDB_FORCE_INLINE pnanovdb_int64_t pnanovdb_root_tile_get_child(pnanovdb_buf_t buf, pnanovdb_root_tile_handle_t p) {
1002     return pnanovdb_read_int64(buf, pnanovdb_address_offset(p.address, PNANOVDB_ROOT_TILE_OFF_CHILD));
1003 }
pnanovdb_root_tile_get_state(pnanovdb_buf_t buf,pnanovdb_root_tile_handle_t p)1004 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_root_tile_get_state(pnanovdb_buf_t buf, pnanovdb_root_tile_handle_t p) {
1005     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_ROOT_TILE_OFF_STATE));
1006 }
1007 
1008 struct pnanovdb_upper_t
1009 {
1010     pnanovdb_coord_t bbox_min;
1011     pnanovdb_coord_t bbox_max;
1012     pnanovdb_uint64_t flags;
1013     pnanovdb_uint32_t value_mask[1024];
1014     pnanovdb_uint32_t child_mask[1024];
1015     // min, max
1016     // alignas(32) pnanovdb_uint32_t table[];
1017 };
1018 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_upper_t)
1019 struct pnanovdb_upper_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_upper_handle_t)1020 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_upper_handle_t)
1021 
1022 #define PNANOVDB_UPPER_TABLE_COUNT 32768
1023 #define PNANOVDB_UPPER_BASE_SIZE 8224
1024 
1025 #define PNANOVDB_UPPER_OFF_BBOX_MIN 0
1026 #define PNANOVDB_UPPER_OFF_BBOX_MAX 12
1027 #define PNANOVDB_UPPER_OFF_FLAGS 24
1028 #define PNANOVDB_UPPER_OFF_VALUE_MASK 32
1029 #define PNANOVDB_UPPER_OFF_CHILD_MASK 4128
1030 
1031 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_upper_get_bbox_min(pnanovdb_buf_t buf, pnanovdb_upper_handle_t p) {
1032     return pnanovdb_read_coord(buf, pnanovdb_address_offset(p.address, PNANOVDB_UPPER_OFF_BBOX_MIN));
1033 }
pnanovdb_upper_get_bbox_max(pnanovdb_buf_t buf,pnanovdb_upper_handle_t p)1034 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_upper_get_bbox_max(pnanovdb_buf_t buf, pnanovdb_upper_handle_t p) {
1035     return pnanovdb_read_coord(buf, pnanovdb_address_offset(p.address, PNANOVDB_UPPER_OFF_BBOX_MAX));
1036 }
pnanovdb_upper_get_flags(pnanovdb_buf_t buf,pnanovdb_upper_handle_t p)1037 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_upper_get_flags(pnanovdb_buf_t buf, pnanovdb_upper_handle_t p) {
1038     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_UPPER_OFF_FLAGS));
1039 }
pnanovdb_upper_get_value_mask(pnanovdb_buf_t buf,pnanovdb_upper_handle_t p,pnanovdb_uint32_t bit_index)1040 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_upper_get_value_mask(pnanovdb_buf_t buf, pnanovdb_upper_handle_t p, pnanovdb_uint32_t bit_index) {
1041     pnanovdb_uint32_t value = pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_UPPER_OFF_VALUE_MASK + 4u * (bit_index >> 5u)));
1042     return ((value >> (bit_index & 31u)) & 1) != 0u;
1043 }
pnanovdb_upper_get_child_mask(pnanovdb_buf_t buf,pnanovdb_upper_handle_t p,pnanovdb_uint32_t bit_index)1044 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_upper_get_child_mask(pnanovdb_buf_t buf, pnanovdb_upper_handle_t p, pnanovdb_uint32_t bit_index) {
1045     pnanovdb_uint32_t value = pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_UPPER_OFF_CHILD_MASK + 4u * (bit_index >> 5u)));
1046     return ((value >> (bit_index & 31u)) & 1) != 0u;
1047 }
1048 
1049 struct pnanovdb_lower_t
1050 {
1051     pnanovdb_coord_t bbox_min;
1052     pnanovdb_coord_t bbox_max;
1053     pnanovdb_uint64_t flags;
1054     pnanovdb_uint32_t value_mask[128];
1055     pnanovdb_uint32_t child_mask[128];
1056     // min, max
1057     // alignas(32) pnanovdb_uint32_t table[];
1058 };
1059 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_lower_t)
1060 struct pnanovdb_lower_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_lower_handle_t)1061 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_lower_handle_t)
1062 
1063 #define PNANOVDB_LOWER_TABLE_COUNT 4096
1064 #define PNANOVDB_LOWER_BASE_SIZE 1056
1065 
1066 #define PNANOVDB_LOWER_OFF_BBOX_MIN 0
1067 #define PNANOVDB_LOWER_OFF_BBOX_MAX 12
1068 #define PNANOVDB_LOWER_OFF_FLAGS 24
1069 #define PNANOVDB_LOWER_OFF_VALUE_MASK 32
1070 #define PNANOVDB_LOWER_OFF_CHILD_MASK 544
1071 
1072 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_lower_get_bbox_min(pnanovdb_buf_t buf, pnanovdb_lower_handle_t p) {
1073     return pnanovdb_read_coord(buf, pnanovdb_address_offset(p.address, PNANOVDB_LOWER_OFF_BBOX_MIN));
1074 }
pnanovdb_lower_get_bbox_max(pnanovdb_buf_t buf,pnanovdb_lower_handle_t p)1075 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_lower_get_bbox_max(pnanovdb_buf_t buf, pnanovdb_lower_handle_t p) {
1076     return pnanovdb_read_coord(buf, pnanovdb_address_offset(p.address, PNANOVDB_LOWER_OFF_BBOX_MAX));
1077 }
pnanovdb_lower_get_flags(pnanovdb_buf_t buf,pnanovdb_lower_handle_t p)1078 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_lower_get_flags(pnanovdb_buf_t buf, pnanovdb_lower_handle_t p) {
1079     return pnanovdb_read_uint64(buf, pnanovdb_address_offset(p.address, PNANOVDB_LOWER_OFF_FLAGS));
1080 }
pnanovdb_lower_get_value_mask(pnanovdb_buf_t buf,pnanovdb_lower_handle_t p,pnanovdb_uint32_t bit_index)1081 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_lower_get_value_mask(pnanovdb_buf_t buf, pnanovdb_lower_handle_t p, pnanovdb_uint32_t bit_index) {
1082     pnanovdb_uint32_t value = pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_LOWER_OFF_VALUE_MASK + 4u * (bit_index >> 5u)));
1083     return ((value >> (bit_index & 31u)) & 1) != 0u;
1084 }
pnanovdb_lower_get_child_mask(pnanovdb_buf_t buf,pnanovdb_lower_handle_t p,pnanovdb_uint32_t bit_index)1085 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_lower_get_child_mask(pnanovdb_buf_t buf, pnanovdb_lower_handle_t p, pnanovdb_uint32_t bit_index) {
1086     pnanovdb_uint32_t value = pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_LOWER_OFF_CHILD_MASK + 4u * (bit_index >> 5u)));
1087     return ((value >> (bit_index & 31u)) & 1) != 0u;
1088 }
1089 
1090 struct pnanovdb_leaf_t
1091 {
1092     pnanovdb_coord_t bbox_min;
1093     pnanovdb_uint32_t bbox_dif_and_flags;
1094     pnanovdb_uint32_t value_mask[16];
1095     // min, max
1096     // alignas(32) pnanovdb_uint32_t values[];
1097 };
1098 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_leaf_t)
1099 struct pnanovdb_leaf_handle_t { pnanovdb_address_t address; };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_leaf_handle_t)1100 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_leaf_handle_t)
1101 
1102 #define PNANOVDB_LEAF_TABLE_COUNT 512
1103 #define PNANOVDB_LEAF_BASE_SIZE 80
1104 
1105 #define PNANOVDB_LEAF_OFF_BBOX_MIN 0
1106 #define PNANOVDB_LEAF_OFF_BBOX_DIF_AND_FLAGS 12
1107 #define PNANOVDB_LEAF_OFF_VALUE_MASK 16
1108 
1109 #define PNANOVDB_LEAF_TABLE_NEG_OFF_BBOX_DIF_AND_FLAGS 84
1110 #define PNANOVDB_LEAF_TABLE_NEG_OFF_MINIMUM 16
1111 #define PNANOVDB_LEAF_TABLE_NEG_OFF_QUANTUM 12
1112 
1113 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_leaf_get_bbox_min(pnanovdb_buf_t buf, pnanovdb_leaf_handle_t p) {
1114     return pnanovdb_read_coord(buf, pnanovdb_address_offset(p.address, PNANOVDB_LEAF_OFF_BBOX_MIN));
1115 }
pnanovdb_leaf_get_bbox_dif_and_flags(pnanovdb_buf_t buf,pnanovdb_leaf_handle_t p)1116 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_leaf_get_bbox_dif_and_flags(pnanovdb_buf_t buf, pnanovdb_leaf_handle_t p) {
1117     return pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_LEAF_OFF_BBOX_DIF_AND_FLAGS));
1118 }
pnanovdb_leaf_get_value_mask(pnanovdb_buf_t buf,pnanovdb_leaf_handle_t p,pnanovdb_uint32_t bit_index)1119 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_leaf_get_value_mask(pnanovdb_buf_t buf, pnanovdb_leaf_handle_t p, pnanovdb_uint32_t bit_index) {
1120     pnanovdb_uint32_t value = pnanovdb_read_uint32(buf, pnanovdb_address_offset(p.address, PNANOVDB_LEAF_OFF_VALUE_MASK + 4u * (bit_index >> 5u)));
1121     return ((value >> (bit_index & 31u)) & 1) != 0u;
1122 }
1123 
1124 struct pnanovdb_grid_type_constants_t
1125 {
1126     pnanovdb_uint32_t root_off_background;
1127     pnanovdb_uint32_t root_off_min;
1128     pnanovdb_uint32_t root_off_max;
1129     pnanovdb_uint32_t root_off_ave;
1130     pnanovdb_uint32_t root_off_stddev;
1131     pnanovdb_uint32_t root_size;
1132     pnanovdb_uint32_t value_stride_bits;
1133     pnanovdb_uint32_t table_stride;
1134     pnanovdb_uint32_t root_tile_off_value;
1135     pnanovdb_uint32_t root_tile_size;
1136     pnanovdb_uint32_t upper_off_min;
1137     pnanovdb_uint32_t upper_off_max;
1138     pnanovdb_uint32_t upper_off_ave;
1139     pnanovdb_uint32_t upper_off_stddev;
1140     pnanovdb_uint32_t upper_off_table;
1141     pnanovdb_uint32_t upper_size;
1142     pnanovdb_uint32_t lower_off_min;
1143     pnanovdb_uint32_t lower_off_max;
1144     pnanovdb_uint32_t lower_off_ave;
1145     pnanovdb_uint32_t lower_off_stddev;
1146     pnanovdb_uint32_t lower_off_table;
1147     pnanovdb_uint32_t lower_size;
1148     pnanovdb_uint32_t leaf_off_min;
1149     pnanovdb_uint32_t leaf_off_max;
1150     pnanovdb_uint32_t leaf_off_ave;
1151     pnanovdb_uint32_t leaf_off_stddev;
1152     pnanovdb_uint32_t leaf_off_table;
1153     pnanovdb_uint32_t leaf_size;
1154 };
1155 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_grid_type_constants_t)
1156 
1157 PNANOVDB_STATIC_CONST pnanovdb_grid_type_constants_t pnanovdb_grid_type_constants[PNANOVDB_GRID_TYPE_END] =
1158 {
1159     {28, 28, 28, 28, 28, 32,  0, 8, 20, 32,  8224, 8224, 8224, 8224, 8224, 270368,  1056, 1056, 1056, 1056, 1056, 33824,  80, 80, 80, 80, 96, 96},
1160     {28, 32, 36, 40, 44, 64,  32, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  80, 84, 88, 92, 96, 2144},
1161     {32, 40, 48, 56, 64, 96,  64, 8, 24, 32,  8224, 8232, 8240, 8248, 8256, 270400,  1056, 1064, 1072, 1080, 1088, 33856,  80, 88, 96, 104, 128, 4224},
1162     {28, 30, 32, 36, 40, 64,  16, 8, 20, 32,  8224, 8226, 8228, 8232, 8256, 270400,  1056, 1058, 1060, 1064, 1088, 33856,  80, 82, 84, 88, 96, 1120},
1163     {28, 32, 36, 40, 44, 64,  32, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  80, 84, 88, 92, 96, 2144},
1164     {32, 40, 48, 56, 64, 96,  64, 8, 24, 32,  8224, 8232, 8240, 8248, 8256, 270400,  1056, 1064, 1072, 1080, 1088, 33856,  80, 88, 96, 104, 128, 4224},
1165     {28, 40, 52, 64, 68, 96,  96, 16, 20, 32,  8224, 8236, 8248, 8252, 8256, 532544,  1056, 1068, 1080, 1084, 1088, 66624,  80, 92, 104, 108, 128, 6272},
1166     {32, 56, 80, 104, 112, 128,  192, 24, 24, 64,  8224, 8248, 8272, 8280, 8288, 794720,  1056, 1080, 1104, 1112, 1120, 99424,  80, 104, 128, 136, 160, 12448},
1167     {28, 29, 30, 31, 32, 64,  0, 8, 20, 32,  8224, 8225, 8226, 8227, 8256, 270400,  1056, 1057, 1058, 1059, 1088, 33856,  80, 80, 80, 80, 96, 96},
1168     {28, 30, 32, 36, 40, 64,  16, 8, 20, 32,  8224, 8226, 8228, 8232, 8256, 270400,  1056, 1058, 1060, 1064, 1088, 33856,  80, 82, 84, 88, 96, 1120},
1169     {28, 32, 36, 40, 44, 64,  32, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  80, 84, 88, 92, 96, 2144},
1170     {28, 29, 30, 31, 32, 64,  1, 8, 20, 32,  8224, 8225, 8226, 8227, 8256, 270400,  1056, 1057, 1058, 1059, 1088, 33856,  80, 80, 80, 80, 96, 160},
1171     {28, 32, 36, 40, 44, 64,  32, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  80, 84, 88, 92, 96, 2144},
1172     {28, 32, 36, 40, 44, 64,  0, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  88, 90, 92, 94, 96, 352},
1173     {28, 32, 36, 40, 44, 64,  0, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  88, 90, 92, 94, 96, 608},
1174     {28, 32, 36, 40, 44, 64,  0, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  88, 90, 92, 94, 96, 1120},
1175     {28, 32, 36, 40, 44, 64,  0, 8, 20, 32,  8224, 8228, 8232, 8236, 8256, 270400,  1056, 1060, 1064, 1068, 1088, 33856,  88, 90, 92, 94, 96, 96},
1176     {28, 44, 60, 76, 80, 96,  128, 16, 20, 64,  8224, 8240, 8256, 8260, 8288, 532576,  1056, 1072, 1088, 1092, 1120, 66656,  80, 96, 112, 116, 128, 8320},
1177     {32, 64, 96, 128, 136, 160,  256, 32, 24, 64,  8224, 8256, 8288, 8296, 8320, 1056896,  1056, 1088, 1120, 1128, 1152, 132224,  80, 112, 144, 152, 160, 16544},
1178 };
1179 
1180 // ------------------------------------------------ Basic Lookup -----------------------------------------------------------
1181 
pnanovdb_grid_get_gridblindmetadata(pnanovdb_buf_t buf,pnanovdb_grid_handle_t grid,pnanovdb_uint32_t index)1182 PNANOVDB_FORCE_INLINE pnanovdb_gridblindmetadata_handle_t pnanovdb_grid_get_gridblindmetadata(pnanovdb_buf_t buf, pnanovdb_grid_handle_t grid, pnanovdb_uint32_t index)
1183 {
1184     pnanovdb_gridblindmetadata_handle_t meta = { grid.address };
1185     pnanovdb_uint64_t byte_offset = pnanovdb_grid_get_blind_metadata_offset(buf, grid);
1186     meta.address = pnanovdb_address_offset64(meta.address, byte_offset);
1187     meta.address = pnanovdb_address_offset_product(meta.address, PNANOVDB_GRIDBLINDMETADATA_SIZE, index);
1188     return meta;
1189 }
1190 
pnanodvb_grid_get_gridblindmetadata_value_address(pnanovdb_buf_t buf,pnanovdb_grid_handle_t grid,pnanovdb_uint32_t index)1191 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanodvb_grid_get_gridblindmetadata_value_address(pnanovdb_buf_t buf, pnanovdb_grid_handle_t grid, pnanovdb_uint32_t index)
1192 {
1193     pnanovdb_gridblindmetadata_handle_t meta = pnanovdb_grid_get_gridblindmetadata(buf, grid, index);
1194     pnanovdb_int64_t byte_offset = pnanovdb_gridblindmetadata_get_byte_offset(buf, meta);
1195     pnanovdb_address_t address = grid.address;
1196     address = pnanovdb_address_offset64(address, pnanovdb_int64_as_uint64(byte_offset));
1197     return address;
1198 }
1199 
pnanovdb_grid_get_tree(pnanovdb_buf_t buf,pnanovdb_grid_handle_t grid)1200 PNANOVDB_FORCE_INLINE pnanovdb_tree_handle_t pnanovdb_grid_get_tree(pnanovdb_buf_t buf, pnanovdb_grid_handle_t grid)
1201 {
1202     pnanovdb_tree_handle_t tree = { grid.address };
1203     tree.address = pnanovdb_address_offset(tree.address, PNANOVDB_GRID_SIZE);
1204     return tree;
1205 }
1206 
pnanovdb_tree_get_root(pnanovdb_buf_t buf,pnanovdb_tree_handle_t tree)1207 PNANOVDB_FORCE_INLINE pnanovdb_root_handle_t pnanovdb_tree_get_root(pnanovdb_buf_t buf, pnanovdb_tree_handle_t tree)
1208 {
1209     pnanovdb_root_handle_t root = { tree.address };
1210     pnanovdb_uint64_t byte_offset = pnanovdb_tree_get_node_offset_root(buf, tree);
1211     root.address = pnanovdb_address_offset64(root.address, byte_offset);
1212     return root;
1213 }
1214 
pnanovdb_root_get_tile(pnanovdb_grid_type_t grid_type,pnanovdb_root_handle_t root,pnanovdb_uint32_t n)1215 PNANOVDB_FORCE_INLINE pnanovdb_root_tile_handle_t pnanovdb_root_get_tile(pnanovdb_grid_type_t grid_type, pnanovdb_root_handle_t root, pnanovdb_uint32_t n)
1216 {
1217     pnanovdb_root_tile_handle_t tile = { root.address };
1218     tile.address = pnanovdb_address_offset(tile.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_size));
1219     tile.address = pnanovdb_address_offset_product(tile.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_tile_size), n);
1220     return tile;
1221 }
1222 
pnanovdb_root_get_tile_zero(pnanovdb_grid_type_t grid_type,pnanovdb_root_handle_t root)1223 PNANOVDB_FORCE_INLINE pnanovdb_root_tile_handle_t pnanovdb_root_get_tile_zero(pnanovdb_grid_type_t grid_type, pnanovdb_root_handle_t root)
1224 {
1225     pnanovdb_root_tile_handle_t tile = { root.address };
1226     tile.address = pnanovdb_address_offset(tile.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_size));
1227     return tile;
1228 }
1229 
pnanovdb_root_get_child(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,pnanovdb_root_tile_handle_t tile)1230 PNANOVDB_FORCE_INLINE pnanovdb_upper_handle_t pnanovdb_root_get_child(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, pnanovdb_root_tile_handle_t tile)
1231 {
1232     pnanovdb_upper_handle_t upper = { root.address };
1233     upper.address = pnanovdb_address_offset64(upper.address, pnanovdb_int64_as_uint64(pnanovdb_root_tile_get_child(buf, tile)));
1234     return upper;
1235 }
1236 
pnanovdb_coord_to_key(PNANOVDB_IN (pnanovdb_coord_t)ijk)1237 PNANOVDB_FORCE_INLINE pnanovdb_uint64_t pnanovdb_coord_to_key(PNANOVDB_IN(pnanovdb_coord_t) ijk)
1238 {
1239 #if defined(PNANOVDB_NATIVE_64)
1240     pnanovdb_uint64_t iu = pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).x) >> 12u;
1241     pnanovdb_uint64_t ju = pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).y) >> 12u;
1242     pnanovdb_uint64_t ku = pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).z) >> 12u;
1243     return (ku) | (ju << 21u) | (iu << 42u);
1244 #else
1245     pnanovdb_uint32_t iu = pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).x) >> 12u;
1246     pnanovdb_uint32_t ju = pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).y) >> 12u;
1247     pnanovdb_uint32_t ku = pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).z) >> 12u;
1248     pnanovdb_uint32_t key_x = ku | (ju << 21);
1249     pnanovdb_uint32_t key_y = (iu << 10) | (ju >> 11);
1250     return pnanovdb_uint32_as_uint64(key_x, key_y);
1251 #endif
1252 }
1253 
pnanovdb_root_find_tile(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk)1254 PNANOVDB_FORCE_INLINE pnanovdb_root_tile_handle_t pnanovdb_root_find_tile(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1255 {
1256     pnanovdb_uint32_t tile_count = pnanovdb_uint32_as_int32(pnanovdb_root_get_tile_count(buf, root));
1257     pnanovdb_root_tile_handle_t tile = pnanovdb_root_get_tile_zero(grid_type, root);
1258     pnanovdb_uint64_t key = pnanovdb_coord_to_key(ijk);
1259     for (pnanovdb_uint32_t i = 0u; i < tile_count; i++)
1260     {
1261         if (pnanovdb_uint64_is_equal(key, pnanovdb_root_tile_get_key(buf, tile)))
1262         {
1263             return tile;
1264         }
1265         tile.address = pnanovdb_address_offset(tile.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_tile_size));
1266     }
1267     pnanovdb_root_tile_handle_t null_handle = { pnanovdb_address_null() };
1268     return null_handle;
1269 }
1270 
pnanovdb_leaf_coord_to_offset(PNANOVDB_IN (pnanovdb_coord_t)ijk)1271 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_leaf_coord_to_offset(PNANOVDB_IN(pnanovdb_coord_t) ijk)
1272 {
1273     return (((PNANOVDB_DEREF(ijk).x & 7) >> 0) << (2 * 3)) +
1274         (((PNANOVDB_DEREF(ijk).y & 7) >> 0) << (3)) +
1275         ((PNANOVDB_DEREF(ijk).z & 7) >> 0);
1276 }
1277 
pnanovdb_leaf_get_min_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t node)1278 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_leaf_get_min_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t node)
1279 {
1280     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, leaf_off_min);
1281     return pnanovdb_address_offset(node.address, byte_offset);
1282 }
1283 
pnanovdb_leaf_get_max_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t node)1284 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_leaf_get_max_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t node)
1285 {
1286     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, leaf_off_max);
1287     return pnanovdb_address_offset(node.address, byte_offset);
1288 }
1289 
pnanovdb_leaf_get_ave_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t node)1290 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_leaf_get_ave_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t node)
1291 {
1292     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, leaf_off_ave);
1293     return pnanovdb_address_offset(node.address, byte_offset);
1294 }
1295 
pnanovdb_leaf_get_stddev_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t node)1296 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_leaf_get_stddev_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t node)
1297 {
1298     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, leaf_off_stddev);
1299     return pnanovdb_address_offset(node.address, byte_offset);
1300 }
1301 
pnanovdb_leaf_get_table_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t node,pnanovdb_uint32_t n)1302 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_leaf_get_table_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t node, pnanovdb_uint32_t n)
1303 {
1304     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, leaf_off_table) + ((PNANOVDB_GRID_TYPE_GET(grid_type, value_stride_bits) * n) >> 3u);
1305     return pnanovdb_address_offset(node.address, byte_offset);
1306 }
1307 
pnanovdb_leaf_get_value_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t leaf,PNANOVDB_IN (pnanovdb_coord_t)ijk)1308 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_leaf_get_value_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t leaf, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1309 {
1310     pnanovdb_uint32_t n = pnanovdb_leaf_coord_to_offset(ijk);
1311     return pnanovdb_leaf_get_table_address(grid_type, buf, leaf, n);
1312 }
1313 
pnanovdb_leaf_fp_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk,pnanovdb_uint32_t value_log_bits)1314 PNANOVDB_FORCE_INLINE float pnanovdb_leaf_fp_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk, pnanovdb_uint32_t value_log_bits)
1315 {
1316     //  value_log_bits                                                          //   2     3       4
1317     pnanovdb_uint32_t value_bits = 1u << value_log_bits;                        //   4     8      16
1318     pnanovdb_uint32_t value_mask = (1u << value_bits) - 1u;                     // 0xF  0xFF  0xFFFF
1319     pnanovdb_uint32_t values_per_word_bits = 5u - value_log_bits;               //   3     2       1
1320     pnanovdb_uint32_t values_per_word_mask = (1u << values_per_word_bits) - 1u; //   7     3       1
1321 
1322     pnanovdb_uint32_t n = pnanovdb_leaf_coord_to_offset(ijk);
1323     float minimum = pnanovdb_read_float(buf, pnanovdb_address_offset_neg(address, PNANOVDB_LEAF_TABLE_NEG_OFF_MINIMUM));
1324     float quantum = pnanovdb_read_float(buf, pnanovdb_address_offset_neg(address, PNANOVDB_LEAF_TABLE_NEG_OFF_QUANTUM));
1325     pnanovdb_uint32_t raw = pnanovdb_read_uint32(buf, pnanovdb_address_offset(address, ((n >> values_per_word_bits) << 2u)));
1326     pnanovdb_uint32_t value_compressed = (raw >> ((n & values_per_word_mask) << value_log_bits)) & value_mask;
1327     return pnanovdb_uint32_to_float(value_compressed) * quantum + minimum;
1328 }
1329 
pnanovdb_leaf_fp4_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk)1330 PNANOVDB_FORCE_INLINE float pnanovdb_leaf_fp4_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1331 {
1332     return pnanovdb_leaf_fp_read_float(buf, address, ijk, 2u);
1333 }
1334 
pnanovdb_leaf_fp8_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk)1335 PNANOVDB_FORCE_INLINE float pnanovdb_leaf_fp8_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1336 {
1337     return pnanovdb_leaf_fp_read_float(buf, address, ijk, 3u);
1338 }
1339 
pnanovdb_leaf_fp16_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk)1340 PNANOVDB_FORCE_INLINE float pnanovdb_leaf_fp16_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1341 {
1342     return pnanovdb_leaf_fp_read_float(buf, address, ijk, 4u);
1343 }
1344 
pnanovdb_leaf_fpn_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk)1345 PNANOVDB_FORCE_INLINE float pnanovdb_leaf_fpn_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1346 {
1347     pnanovdb_uint32_t bbox_dif_and_flags = pnanovdb_read_uint32(buf, pnanovdb_address_offset_neg(address, PNANOVDB_LEAF_TABLE_NEG_OFF_BBOX_DIF_AND_FLAGS));
1348     pnanovdb_uint32_t flags = bbox_dif_and_flags >> 24u;
1349     pnanovdb_uint32_t value_log_bits = flags >> 5; // b = 0, 1, 2, 3, 4 corresponding to 1, 2, 4, 8, 16 bits
1350     return pnanovdb_leaf_fp_read_float(buf, address, ijk, value_log_bits);
1351 }
1352 
pnanovdb_lower_coord_to_offset(PNANOVDB_IN (pnanovdb_coord_t)ijk)1353 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_lower_coord_to_offset(PNANOVDB_IN(pnanovdb_coord_t) ijk)
1354 {
1355     return (((PNANOVDB_DEREF(ijk).x & 127) >> 3) << (2 * 4)) +
1356         (((PNANOVDB_DEREF(ijk).y & 127) >> 3) << (4)) +
1357         ((PNANOVDB_DEREF(ijk).z & 127) >> 3);
1358 }
1359 
pnanovdb_lower_get_min_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t node)1360 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_min_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t node)
1361 {
1362     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, lower_off_min);
1363     return pnanovdb_address_offset(node.address, byte_offset);
1364 }
1365 
pnanovdb_lower_get_max_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t node)1366 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_max_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t node)
1367 {
1368     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, lower_off_max);
1369     return pnanovdb_address_offset(node.address, byte_offset);
1370 }
1371 
pnanovdb_lower_get_ave_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t node)1372 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_ave_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t node)
1373 {
1374     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, lower_off_ave);
1375     return pnanovdb_address_offset(node.address, byte_offset);
1376 }
1377 
pnanovdb_lower_get_stddev_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t node)1378 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_stddev_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t node)
1379 {
1380     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, lower_off_stddev);
1381     return pnanovdb_address_offset(node.address, byte_offset);
1382 }
1383 
pnanovdb_lower_get_table_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t node,pnanovdb_uint32_t n)1384 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_table_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t node, pnanovdb_uint32_t n)
1385 {
1386     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, lower_off_table) + PNANOVDB_GRID_TYPE_GET(grid_type, table_stride) * n;
1387     return pnanovdb_address_offset(node.address, byte_offset);
1388 }
1389 
pnanovdb_lower_get_table_child(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t node,pnanovdb_uint32_t n)1390 PNANOVDB_FORCE_INLINE pnanovdb_int64_t pnanovdb_lower_get_table_child(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t node, pnanovdb_uint32_t n)
1391 {
1392     pnanovdb_address_t table_address = pnanovdb_lower_get_table_address(grid_type, buf, node, n);
1393     return pnanovdb_read_int64(buf, table_address);
1394 }
1395 
pnanovdb_lower_get_child(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t lower,pnanovdb_uint32_t n)1396 PNANOVDB_FORCE_INLINE pnanovdb_leaf_handle_t pnanovdb_lower_get_child(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t lower, pnanovdb_uint32_t n)
1397 {
1398     pnanovdb_leaf_handle_t leaf = { lower.address };
1399     leaf.address = pnanovdb_address_offset64(leaf.address, pnanovdb_int64_as_uint64(pnanovdb_lower_get_table_child(grid_type, buf, lower, n)));
1400     return leaf;
1401 }
1402 
pnanovdb_lower_get_value_address_and_level(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t lower,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_uint32_t)level)1403 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_value_address_and_level(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t lower, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_uint32_t) level)
1404 {
1405     pnanovdb_uint32_t n = pnanovdb_lower_coord_to_offset(ijk);
1406     pnanovdb_address_t value_address;
1407     if (pnanovdb_lower_get_child_mask(buf, lower, n))
1408     {
1409         pnanovdb_leaf_handle_t child = pnanovdb_lower_get_child(grid_type, buf, lower, n);
1410         value_address = pnanovdb_leaf_get_value_address(grid_type, buf, child, ijk);
1411         PNANOVDB_DEREF(level) = 0u;
1412     }
1413     else
1414     {
1415         value_address = pnanovdb_lower_get_table_address(grid_type, buf, lower, n);
1416         PNANOVDB_DEREF(level) = 1u;
1417     }
1418     return value_address;
1419 }
1420 
pnanovdb_lower_get_value_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t lower,PNANOVDB_IN (pnanovdb_coord_t)ijk)1421 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_value_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t lower, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1422 {
1423     pnanovdb_uint32_t level;
1424     return pnanovdb_lower_get_value_address_and_level(grid_type, buf, lower, ijk, PNANOVDB_REF(level));
1425 }
1426 
pnanovdb_upper_coord_to_offset(PNANOVDB_IN (pnanovdb_coord_t)ijk)1427 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_upper_coord_to_offset(PNANOVDB_IN(pnanovdb_coord_t) ijk)
1428 {
1429     return (((PNANOVDB_DEREF(ijk).x & 4095) >> 7) << (2 * 5)) +
1430         (((PNANOVDB_DEREF(ijk).y & 4095) >> 7) << (5)) +
1431         ((PNANOVDB_DEREF(ijk).z & 4095) >> 7);
1432 }
1433 
pnanovdb_upper_get_min_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t node)1434 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_min_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t node)
1435 {
1436     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, upper_off_min);
1437     return pnanovdb_address_offset(node.address, byte_offset);
1438 }
1439 
pnanovdb_upper_get_max_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t node)1440 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_max_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t node)
1441 {
1442     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, upper_off_max);
1443     return pnanovdb_address_offset(node.address, byte_offset);
1444 }
1445 
pnanovdb_upper_get_ave_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t node)1446 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_ave_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t node)
1447 {
1448     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, upper_off_ave);
1449     return pnanovdb_address_offset(node.address, byte_offset);
1450 }
1451 
pnanovdb_upper_get_stddev_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t node)1452 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_stddev_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t node)
1453 {
1454     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, upper_off_stddev);
1455     return pnanovdb_address_offset(node.address, byte_offset);
1456 }
1457 
pnanovdb_upper_get_table_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t node,pnanovdb_uint32_t n)1458 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_table_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t node, pnanovdb_uint32_t n)
1459 {
1460     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, upper_off_table) + PNANOVDB_GRID_TYPE_GET(grid_type, table_stride) * n;
1461     return pnanovdb_address_offset(node.address, byte_offset);
1462 }
1463 
pnanovdb_upper_get_table_child(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t node,pnanovdb_uint32_t n)1464 PNANOVDB_FORCE_INLINE pnanovdb_int64_t pnanovdb_upper_get_table_child(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t node, pnanovdb_uint32_t n)
1465 {
1466     pnanovdb_address_t bufAddress = pnanovdb_upper_get_table_address(grid_type, buf, node, n);
1467     return pnanovdb_read_int64(buf, bufAddress);
1468 }
1469 
pnanovdb_upper_get_child(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t upper,pnanovdb_uint32_t n)1470 PNANOVDB_FORCE_INLINE pnanovdb_lower_handle_t pnanovdb_upper_get_child(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t upper, pnanovdb_uint32_t n)
1471 {
1472     pnanovdb_lower_handle_t lower = { upper.address };
1473     lower.address = pnanovdb_address_offset64(lower.address, pnanovdb_int64_as_uint64(pnanovdb_upper_get_table_child(grid_type, buf, upper, n)));
1474     return lower;
1475 }
1476 
pnanovdb_upper_get_value_address_and_level(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t upper,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_uint32_t)level)1477 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_value_address_and_level(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t upper, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_uint32_t) level)
1478 {
1479     pnanovdb_uint32_t n = pnanovdb_upper_coord_to_offset(ijk);
1480     pnanovdb_address_t value_address;
1481     if (pnanovdb_upper_get_child_mask(buf, upper, n))
1482     {
1483         pnanovdb_lower_handle_t child = pnanovdb_upper_get_child(grid_type, buf, upper, n);
1484         value_address = pnanovdb_lower_get_value_address_and_level(grid_type, buf, child, ijk, level);
1485     }
1486     else
1487     {
1488         value_address = pnanovdb_upper_get_table_address(grid_type, buf, upper, n);
1489         PNANOVDB_DEREF(level) = 2u;
1490     }
1491     return value_address;
1492 }
1493 
pnanovdb_upper_get_value_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t upper,PNANOVDB_IN (pnanovdb_coord_t)ijk)1494 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_value_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t upper, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1495 {
1496     pnanovdb_uint32_t level;
1497     return pnanovdb_upper_get_value_address_and_level(grid_type, buf, upper, ijk, PNANOVDB_REF(level));
1498 }
1499 
pnanovdb_root_get_min_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root)1500 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_min_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root)
1501 {
1502     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, root_off_min);
1503     return pnanovdb_address_offset(root.address, byte_offset);
1504 }
1505 
pnanovdb_root_get_max_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root)1506 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_max_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root)
1507 {
1508     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, root_off_max);
1509     return pnanovdb_address_offset(root.address, byte_offset);
1510 }
1511 
pnanovdb_root_get_ave_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root)1512 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_ave_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root)
1513 {
1514     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, root_off_ave);
1515     return pnanovdb_address_offset(root.address, byte_offset);
1516 }
1517 
pnanovdb_root_get_stddev_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root)1518 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_stddev_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root)
1519 {
1520     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, root_off_stddev);
1521     return pnanovdb_address_offset(root.address, byte_offset);
1522 }
1523 
pnanovdb_root_tile_get_value_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_tile_handle_t root_tile)1524 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_tile_get_value_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_tile_handle_t root_tile)
1525 {
1526     pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, root_tile_off_value);
1527     return pnanovdb_address_offset(root_tile.address, byte_offset);
1528 }
1529 
pnanovdb_root_get_value_address_and_level(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_uint32_t)level)1530 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_value_address_and_level(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_uint32_t) level)
1531 {
1532     pnanovdb_root_tile_handle_t tile = pnanovdb_root_find_tile(grid_type, buf, root, ijk);
1533     pnanovdb_address_t ret;
1534     if (pnanovdb_address_is_null(tile.address))
1535     {
1536         ret = pnanovdb_address_offset(root.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_off_background));
1537         PNANOVDB_DEREF(level) = 4u;
1538     }
1539     else if (pnanovdb_int64_is_zero(pnanovdb_root_tile_get_child(buf, tile)))
1540     {
1541         ret = pnanovdb_address_offset(tile.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_tile_off_value));
1542         PNANOVDB_DEREF(level) = 3u;
1543     }
1544     else
1545     {
1546         pnanovdb_upper_handle_t child = pnanovdb_root_get_child(grid_type, buf, root, tile);
1547         ret = pnanovdb_upper_get_value_address_and_level(grid_type, buf, child, ijk, level);
1548     }
1549     return ret;
1550 }
1551 
pnanovdb_root_get_value_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk)1552 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_value_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1553 {
1554     pnanovdb_uint32_t level;
1555     return pnanovdb_root_get_value_address_and_level(grid_type, buf, root, ijk, PNANOVDB_REF(level));
1556 }
1557 
pnanovdb_root_get_value_address_bit(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_uint32_t)bit_index)1558 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_value_address_bit(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_uint32_t) bit_index)
1559 {
1560     pnanovdb_uint32_t level;
1561     pnanovdb_address_t address = pnanovdb_root_get_value_address_and_level(grid_type, buf, root, ijk, PNANOVDB_REF(level));
1562     PNANOVDB_DEREF(bit_index) = level == 0u ? pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).x & 7) : 0u;
1563     return address;
1564 }
1565 
pnanovdb_root_fp4_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk,pnanovdb_uint32_t level)1566 PNANOVDB_FORCE_INLINE float pnanovdb_root_fp4_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk, pnanovdb_uint32_t level)
1567 {
1568     float ret;
1569     if (level == 0)
1570     {
1571         ret = pnanovdb_leaf_fp4_read_float(buf, address, ijk);
1572     }
1573     else
1574     {
1575         ret = pnanovdb_read_float(buf, address);
1576     }
1577     return ret;
1578 }
1579 
pnanovdb_root_fp8_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk,pnanovdb_uint32_t level)1580 PNANOVDB_FORCE_INLINE float pnanovdb_root_fp8_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk, pnanovdb_uint32_t level)
1581 {
1582     float ret;
1583     if (level == 0)
1584     {
1585         ret = pnanovdb_leaf_fp8_read_float(buf, address, ijk);
1586     }
1587     else
1588     {
1589         ret = pnanovdb_read_float(buf, address);
1590     }
1591     return ret;
1592 }
1593 
pnanovdb_root_fp16_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk,pnanovdb_uint32_t level)1594 PNANOVDB_FORCE_INLINE float pnanovdb_root_fp16_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk, pnanovdb_uint32_t level)
1595 {
1596     float ret;
1597     if (level == 0)
1598     {
1599         ret = pnanovdb_leaf_fp16_read_float(buf, address, ijk);
1600     }
1601     else
1602     {
1603         ret = pnanovdb_read_float(buf, address);
1604     }
1605     return ret;
1606 }
1607 
pnanovdb_root_fpn_read_float(pnanovdb_buf_t buf,pnanovdb_address_t address,PNANOVDB_IN (pnanovdb_coord_t)ijk,pnanovdb_uint32_t level)1608 PNANOVDB_FORCE_INLINE float pnanovdb_root_fpn_read_float(pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk, pnanovdb_uint32_t level)
1609 {
1610     float ret;
1611     if (level == 0)
1612     {
1613         ret = pnanovdb_leaf_fpn_read_float(buf, address, ijk);
1614     }
1615     else
1616     {
1617         ret = pnanovdb_read_float(buf, address);
1618     }
1619     return ret;
1620 }
1621 
1622 // ------------------------------------------------ ReadAccessor -----------------------------------------------------------
1623 
1624 struct pnanovdb_readaccessor_t
1625 {
1626     pnanovdb_coord_t key;
1627     pnanovdb_leaf_handle_t leaf;
1628     pnanovdb_lower_handle_t lower;
1629     pnanovdb_upper_handle_t upper;
1630     pnanovdb_root_handle_t root;
1631 };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_readaccessor_t)1632 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_readaccessor_t)
1633 
1634 PNANOVDB_FORCE_INLINE void pnanovdb_readaccessor_init(PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, pnanovdb_root_handle_t root)
1635 {
1636     PNANOVDB_DEREF(acc).key.x = 0x7FFFFFFF;
1637     PNANOVDB_DEREF(acc).key.y = 0x7FFFFFFF;
1638     PNANOVDB_DEREF(acc).key.z = 0x7FFFFFFF;
1639     PNANOVDB_DEREF(acc).leaf.address = pnanovdb_address_null();
1640     PNANOVDB_DEREF(acc).lower.address = pnanovdb_address_null();
1641     PNANOVDB_DEREF(acc).upper.address = pnanovdb_address_null();
1642     PNANOVDB_DEREF(acc).root = root;
1643 }
1644 
pnanovdb_readaccessor_iscached0(PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,int dirty)1645 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_readaccessor_iscached0(PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, int dirty)
1646 {
1647     if (pnanovdb_address_is_null(PNANOVDB_DEREF(acc).leaf.address)) { return PNANOVDB_FALSE; }
1648     if ((dirty & ~((1u << 3) - 1u)) != 0)
1649     {
1650         PNANOVDB_DEREF(acc).leaf.address = pnanovdb_address_null();
1651         return PNANOVDB_FALSE;
1652     }
1653     return PNANOVDB_TRUE;
1654 }
pnanovdb_readaccessor_iscached1(PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,int dirty)1655 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_readaccessor_iscached1(PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, int dirty)
1656 {
1657     if (pnanovdb_address_is_null(PNANOVDB_DEREF(acc).lower.address)) { return PNANOVDB_FALSE; }
1658     if ((dirty & ~((1u << 7) - 1u)) != 0)
1659     {
1660         PNANOVDB_DEREF(acc).lower.address = pnanovdb_address_null();
1661         return PNANOVDB_FALSE;
1662     }
1663     return PNANOVDB_TRUE;
1664 }
pnanovdb_readaccessor_iscached2(PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,int dirty)1665 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_readaccessor_iscached2(PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, int dirty)
1666 {
1667     if (pnanovdb_address_is_null(PNANOVDB_DEREF(acc).upper.address)) { return PNANOVDB_FALSE; }
1668     if ((dirty & ~((1u << 12) - 1u)) != 0)
1669     {
1670         PNANOVDB_DEREF(acc).upper.address = pnanovdb_address_null();
1671         return PNANOVDB_FALSE;
1672     }
1673     return PNANOVDB_TRUE;
1674 }
pnanovdb_readaccessor_computedirty(PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_IN (pnanovdb_coord_t)ijk)1675 PNANOVDB_FORCE_INLINE int pnanovdb_readaccessor_computedirty(PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1676 {
1677     return (PNANOVDB_DEREF(ijk).x ^ PNANOVDB_DEREF(acc).key.x) | (PNANOVDB_DEREF(ijk).y ^ PNANOVDB_DEREF(acc).key.y) | (PNANOVDB_DEREF(ijk).z ^ PNANOVDB_DEREF(acc).key.z);
1678 }
1679 
pnanovdb_leaf_get_value_address_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t leaf,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1680 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_leaf_get_value_address_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t leaf, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1681 {
1682     pnanovdb_uint32_t n = pnanovdb_leaf_coord_to_offset(ijk);
1683     return pnanovdb_leaf_get_table_address(grid_type, buf, leaf, n);
1684 }
1685 
pnanovdb_lower_get_value_address_and_level_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t lower,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_INOUT (pnanovdb_uint32_t)level)1686 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_value_address_and_level_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t lower, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_INOUT(pnanovdb_uint32_t) level)
1687 {
1688     pnanovdb_uint32_t n = pnanovdb_lower_coord_to_offset(ijk);
1689     pnanovdb_address_t value_address;
1690     if (pnanovdb_lower_get_child_mask(buf, lower, n))
1691     {
1692         pnanovdb_leaf_handle_t child = pnanovdb_lower_get_child(grid_type, buf, lower, n);
1693         PNANOVDB_DEREF(acc).leaf = child;
1694         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1695         value_address = pnanovdb_leaf_get_value_address_and_cache(grid_type, buf, child, ijk, acc);
1696         PNANOVDB_DEREF(level) = 0u;
1697     }
1698     else
1699     {
1700         value_address = pnanovdb_lower_get_table_address(grid_type, buf, lower, n);
1701         PNANOVDB_DEREF(level) = 1u;
1702     }
1703     return value_address;
1704 }
1705 
pnanovdb_lower_get_value_address_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t lower,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1706 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_lower_get_value_address_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t lower, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1707 {
1708     pnanovdb_uint32_t level;
1709     return pnanovdb_lower_get_value_address_and_level_and_cache(grid_type, buf, lower, ijk, acc, PNANOVDB_REF(level));
1710 }
1711 
pnanovdb_upper_get_value_address_and_level_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t upper,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_INOUT (pnanovdb_uint32_t)level)1712 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_value_address_and_level_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t upper, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_INOUT(pnanovdb_uint32_t) level)
1713 {
1714     pnanovdb_uint32_t n = pnanovdb_upper_coord_to_offset(ijk);
1715     pnanovdb_address_t value_address;
1716     if (pnanovdb_upper_get_child_mask(buf, upper, n))
1717     {
1718         pnanovdb_lower_handle_t child = pnanovdb_upper_get_child(grid_type, buf, upper, n);
1719         PNANOVDB_DEREF(acc).lower = child;
1720         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1721         value_address = pnanovdb_lower_get_value_address_and_level_and_cache(grid_type, buf, child, ijk, acc, level);
1722     }
1723     else
1724     {
1725         value_address = pnanovdb_upper_get_table_address(grid_type, buf, upper, n);
1726         PNANOVDB_DEREF(level) = 2u;
1727     }
1728     return value_address;
1729 }
1730 
pnanovdb_upper_get_value_address_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t upper,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1731 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_upper_get_value_address_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t upper, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1732 {
1733     pnanovdb_uint32_t level;
1734     return pnanovdb_upper_get_value_address_and_level_and_cache(grid_type, buf, upper, ijk, acc, PNANOVDB_REF(level));
1735 }
1736 
pnanovdb_root_get_value_address_and_level_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_INOUT (pnanovdb_uint32_t)level)1737 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_value_address_and_level_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_INOUT(pnanovdb_uint32_t) level)
1738 {
1739     pnanovdb_root_tile_handle_t tile = pnanovdb_root_find_tile(grid_type, buf, root, ijk);
1740     pnanovdb_address_t ret;
1741     if (pnanovdb_address_is_null(tile.address))
1742     {
1743         ret = pnanovdb_address_offset(root.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_off_background));
1744         PNANOVDB_DEREF(level) = 4u;
1745     }
1746     else if (pnanovdb_int64_is_zero(pnanovdb_root_tile_get_child(buf, tile)))
1747     {
1748         ret = pnanovdb_address_offset(tile.address, PNANOVDB_GRID_TYPE_GET(grid_type, root_tile_off_value));
1749         PNANOVDB_DEREF(level) = 3u;
1750     }
1751     else
1752     {
1753         pnanovdb_upper_handle_t child = pnanovdb_root_get_child(grid_type, buf, root, tile);
1754         PNANOVDB_DEREF(acc).upper = child;
1755         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1756         ret = pnanovdb_upper_get_value_address_and_level_and_cache(grid_type, buf, child, ijk, acc, level);
1757     }
1758     return ret;
1759 }
1760 
pnanovdb_root_get_value_address_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1761 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_root_get_value_address_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1762 {
1763     pnanovdb_uint32_t level;
1764     return pnanovdb_root_get_value_address_and_level_and_cache(grid_type, buf, root, ijk, acc, PNANOVDB_REF(level));
1765 }
1766 
pnanovdb_readaccessor_get_value_address_and_level(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_uint32_t)level)1767 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_readaccessor_get_value_address_and_level(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_uint32_t) level)
1768 {
1769     int dirty = pnanovdb_readaccessor_computedirty(acc, ijk);
1770 
1771     pnanovdb_address_t value_address;
1772     if (pnanovdb_readaccessor_iscached0(acc, dirty))
1773     {
1774         value_address = pnanovdb_leaf_get_value_address_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).leaf, ijk, acc);
1775         PNANOVDB_DEREF(level) = 0u;
1776     }
1777     else if (pnanovdb_readaccessor_iscached1(acc, dirty))
1778     {
1779         value_address = pnanovdb_lower_get_value_address_and_level_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).lower, ijk, acc, level);
1780     }
1781     else if (pnanovdb_readaccessor_iscached2(acc, dirty))
1782     {
1783         value_address = pnanovdb_upper_get_value_address_and_level_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).upper, ijk, acc, level);
1784     }
1785     else
1786     {
1787         value_address = pnanovdb_root_get_value_address_and_level_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).root, ijk, acc, level);
1788     }
1789     return value_address;
1790 }
1791 
pnanovdb_readaccessor_get_value_address(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_IN (pnanovdb_coord_t)ijk)1792 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_readaccessor_get_value_address(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1793 {
1794     pnanovdb_uint32_t level;
1795     return pnanovdb_readaccessor_get_value_address_and_level(grid_type, buf, acc, ijk, PNANOVDB_REF(level));
1796 }
1797 
pnanovdb_readaccessor_get_value_address_bit(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_uint32_t)bit_index)1798 PNANOVDB_FORCE_INLINE pnanovdb_address_t pnanovdb_readaccessor_get_value_address_bit(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_uint32_t) bit_index)
1799 {
1800     pnanovdb_uint32_t level;
1801     pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address_and_level(grid_type, buf, acc, ijk, PNANOVDB_REF(level));
1802     PNANOVDB_DEREF(bit_index) = level == 0u ? pnanovdb_int32_as_uint32(PNANOVDB_DEREF(ijk).x & 7) : 0u;
1803     return address;
1804 }
1805 
1806 // ------------------------------------------------ ReadAccessor GetDim -----------------------------------------------------------
1807 
pnanovdb_leaf_get_dim_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t leaf,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1808 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_leaf_get_dim_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t leaf, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1809 {
1810     return 1u;
1811 }
1812 
pnanovdb_lower_get_dim_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t lower,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1813 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_lower_get_dim_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t lower, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1814 {
1815     pnanovdb_uint32_t n = pnanovdb_lower_coord_to_offset(ijk);
1816     pnanovdb_uint32_t ret;
1817     if (pnanovdb_lower_get_child_mask(buf, lower, n))
1818     {
1819         pnanovdb_leaf_handle_t child = pnanovdb_lower_get_child(grid_type, buf, lower, n);
1820         PNANOVDB_DEREF(acc).leaf = child;
1821         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1822         ret = pnanovdb_leaf_get_dim_and_cache(grid_type, buf, child, ijk, acc);
1823     }
1824     else
1825     {
1826         ret = (1u << (3u)); // node 0 dim
1827     }
1828     return ret;
1829 }
1830 
pnanovdb_upper_get_dim_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t upper,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1831 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_upper_get_dim_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t upper, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1832 {
1833     pnanovdb_uint32_t n = pnanovdb_upper_coord_to_offset(ijk);
1834     pnanovdb_uint32_t ret;
1835     if (pnanovdb_upper_get_child_mask(buf, upper, n))
1836     {
1837         pnanovdb_lower_handle_t child = pnanovdb_upper_get_child(grid_type, buf, upper, n);
1838         PNANOVDB_DEREF(acc).lower = child;
1839         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1840         ret = pnanovdb_lower_get_dim_and_cache(grid_type, buf, child, ijk, acc);
1841     }
1842     else
1843     {
1844         ret = (1u << (4u + 3u)); // node 1 dim
1845     }
1846     return ret;
1847 }
1848 
pnanovdb_root_get_dim_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1849 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_root_get_dim_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1850 {
1851     pnanovdb_root_tile_handle_t tile = pnanovdb_root_find_tile(grid_type, buf, root, ijk);
1852     pnanovdb_uint32_t ret;
1853     if (pnanovdb_address_is_null(tile.address))
1854     {
1855         ret = 1u << (5u + 4u + 3u); // background, node 2 dim
1856     }
1857     else if (pnanovdb_int64_is_zero(pnanovdb_root_tile_get_child(buf, tile)))
1858     {
1859         ret = 1u << (5u + 4u + 3u); // tile value, node 2 dim
1860     }
1861     else
1862     {
1863         pnanovdb_upper_handle_t child = pnanovdb_root_get_child(grid_type, buf, root, tile);
1864         PNANOVDB_DEREF(acc).upper = child;
1865         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1866         ret = pnanovdb_upper_get_dim_and_cache(grid_type, buf, child, ijk, acc);
1867     }
1868     return ret;
1869 }
1870 
pnanovdb_readaccessor_get_dim(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_IN (pnanovdb_coord_t)ijk)1871 PNANOVDB_FORCE_INLINE pnanovdb_uint32_t pnanovdb_readaccessor_get_dim(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1872 {
1873     int dirty = pnanovdb_readaccessor_computedirty(acc, ijk);
1874 
1875     pnanovdb_uint32_t dim;
1876     if (pnanovdb_readaccessor_iscached0(acc, dirty))
1877     {
1878         dim = pnanovdb_leaf_get_dim_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).leaf, ijk, acc);
1879     }
1880     else if (pnanovdb_readaccessor_iscached1(acc, dirty))
1881     {
1882         dim = pnanovdb_lower_get_dim_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).lower, ijk, acc);
1883     }
1884     else if (pnanovdb_readaccessor_iscached2(acc, dirty))
1885     {
1886         dim = pnanovdb_upper_get_dim_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).upper, ijk, acc);
1887     }
1888     else
1889     {
1890         dim = pnanovdb_root_get_dim_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).root, ijk, acc);
1891     }
1892     return dim;
1893 }
1894 
1895 // ------------------------------------------------ ReadAccessor IsActive -----------------------------------------------------------
1896 
pnanovdb_leaf_is_active_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_leaf_handle_t leaf,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1897 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_leaf_is_active_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_leaf_handle_t leaf, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1898 {
1899     pnanovdb_uint32_t n = pnanovdb_leaf_coord_to_offset(ijk);
1900     return pnanovdb_leaf_get_value_mask(buf, leaf, n);
1901 }
1902 
pnanovdb_lower_is_active_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_lower_handle_t lower,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1903 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_lower_is_active_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_lower_handle_t lower, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1904 {
1905     pnanovdb_uint32_t n = pnanovdb_lower_coord_to_offset(ijk);
1906     pnanovdb_bool_t is_active;
1907     if (pnanovdb_lower_get_child_mask(buf, lower, n))
1908     {
1909         pnanovdb_leaf_handle_t child = pnanovdb_lower_get_child(grid_type, buf, lower, n);
1910         PNANOVDB_DEREF(acc).leaf = child;
1911         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1912         is_active = pnanovdb_leaf_is_active_and_cache(grid_type, buf, child, ijk, acc);
1913     }
1914     else
1915     {
1916         is_active = pnanovdb_lower_get_value_mask(buf, lower, n);
1917     }
1918     return is_active;
1919 }
1920 
pnanovdb_upper_is_active_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_upper_handle_t upper,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1921 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_upper_is_active_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_upper_handle_t upper, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1922 {
1923     pnanovdb_uint32_t n = pnanovdb_upper_coord_to_offset(ijk);
1924     pnanovdb_bool_t is_active;
1925     if (pnanovdb_upper_get_child_mask(buf, upper, n))
1926     {
1927         pnanovdb_lower_handle_t child = pnanovdb_upper_get_child(grid_type, buf, upper, n);
1928         PNANOVDB_DEREF(acc).lower = child;
1929         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1930         is_active = pnanovdb_lower_is_active_and_cache(grid_type, buf, child, ijk, acc);
1931     }
1932     else
1933     {
1934         is_active = pnanovdb_upper_get_value_mask(buf, upper, n);
1935     }
1936     return is_active;
1937 }
1938 
pnanovdb_root_is_active_and_cache(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,pnanovdb_root_handle_t root,PNANOVDB_IN (pnanovdb_coord_t)ijk,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc)1939 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_root_is_active_and_cache(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc)
1940 {
1941     pnanovdb_root_tile_handle_t tile = pnanovdb_root_find_tile(grid_type, buf, root, ijk);
1942     pnanovdb_bool_t is_active;
1943     if (pnanovdb_address_is_null(tile.address))
1944     {
1945         is_active = PNANOVDB_FALSE; // background
1946     }
1947     else if (pnanovdb_int64_is_zero(pnanovdb_root_tile_get_child(buf, tile)))
1948     {
1949         pnanovdb_uint32_t state = pnanovdb_root_tile_get_state(buf, tile);
1950         is_active = state != 0u; // tile value
1951     }
1952     else
1953     {
1954         pnanovdb_upper_handle_t child = pnanovdb_root_get_child(grid_type, buf, root, tile);
1955         PNANOVDB_DEREF(acc).upper = child;
1956         PNANOVDB_DEREF(acc).key = PNANOVDB_DEREF(ijk);
1957         is_active = pnanovdb_upper_is_active_and_cache(grid_type, buf, child, ijk, acc);
1958     }
1959     return is_active;
1960 }
1961 
pnanovdb_readaccessor_is_active(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_IN (pnanovdb_coord_t)ijk)1962 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_readaccessor_is_active(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk)
1963 {
1964     int dirty = pnanovdb_readaccessor_computedirty(acc, ijk);
1965 
1966     pnanovdb_bool_t is_active;
1967     if (pnanovdb_readaccessor_iscached0(acc, dirty))
1968     {
1969         is_active = pnanovdb_leaf_is_active_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).leaf, ijk, acc);
1970     }
1971     else if (pnanovdb_readaccessor_iscached1(acc, dirty))
1972     {
1973         is_active = pnanovdb_lower_is_active_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).lower, ijk, acc);
1974     }
1975     else if (pnanovdb_readaccessor_iscached2(acc, dirty))
1976     {
1977         is_active = pnanovdb_upper_is_active_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).upper, ijk, acc);
1978     }
1979     else
1980     {
1981         is_active = pnanovdb_root_is_active_and_cache(grid_type, buf, PNANOVDB_DEREF(acc).root, ijk, acc);
1982     }
1983     return is_active;
1984 }
1985 
1986 // ------------------------------------------------ Map Transforms -----------------------------------------------------------
1987 
pnanovdb_map_apply(pnanovdb_buf_t buf,pnanovdb_map_handle_t map,PNANOVDB_IN (pnanovdb_vec3_t)src)1988 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_map_apply(pnanovdb_buf_t buf, pnanovdb_map_handle_t map, PNANOVDB_IN(pnanovdb_vec3_t) src)
1989 {
1990     pnanovdb_vec3_t  dst;
1991     float sx = PNANOVDB_DEREF(src).x;
1992     float sy = PNANOVDB_DEREF(src).y;
1993     float sz = PNANOVDB_DEREF(src).z;
1994     dst.x = sx * pnanovdb_map_get_matf(buf, map, 0) + sy * pnanovdb_map_get_matf(buf, map, 1) + sz * pnanovdb_map_get_matf(buf, map, 2) + pnanovdb_map_get_vecf(buf, map, 0);
1995     dst.y = sx * pnanovdb_map_get_matf(buf, map, 3) + sy * pnanovdb_map_get_matf(buf, map, 4) + sz * pnanovdb_map_get_matf(buf, map, 5) + pnanovdb_map_get_vecf(buf, map, 1);
1996     dst.z = sx * pnanovdb_map_get_matf(buf, map, 6) + sy * pnanovdb_map_get_matf(buf, map, 7) + sz * pnanovdb_map_get_matf(buf, map, 8) + pnanovdb_map_get_vecf(buf, map, 2);
1997     return dst;
1998 }
1999 
pnanovdb_map_apply_inverse(pnanovdb_buf_t buf,pnanovdb_map_handle_t map,PNANOVDB_IN (pnanovdb_vec3_t)src)2000 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_map_apply_inverse(pnanovdb_buf_t buf, pnanovdb_map_handle_t map, PNANOVDB_IN(pnanovdb_vec3_t) src)
2001 {
2002     pnanovdb_vec3_t  dst;
2003     float sx = PNANOVDB_DEREF(src).x - pnanovdb_map_get_vecf(buf, map, 0);
2004     float sy = PNANOVDB_DEREF(src).y - pnanovdb_map_get_vecf(buf, map, 1);
2005     float sz = PNANOVDB_DEREF(src).z - pnanovdb_map_get_vecf(buf, map, 2);
2006     dst.x = sx * pnanovdb_map_get_invmatf(buf, map, 0) + sy * pnanovdb_map_get_invmatf(buf, map, 1) + sz * pnanovdb_map_get_invmatf(buf, map, 2);
2007     dst.y = sx * pnanovdb_map_get_invmatf(buf, map, 3) + sy * pnanovdb_map_get_invmatf(buf, map, 4) + sz * pnanovdb_map_get_invmatf(buf, map, 5);
2008     dst.z = sx * pnanovdb_map_get_invmatf(buf, map, 6) + sy * pnanovdb_map_get_invmatf(buf, map, 7) + sz * pnanovdb_map_get_invmatf(buf, map, 8);
2009     return dst;
2010 }
2011 
pnanovdb_map_apply_jacobi(pnanovdb_buf_t buf,pnanovdb_map_handle_t map,PNANOVDB_IN (pnanovdb_vec3_t)src)2012 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_map_apply_jacobi(pnanovdb_buf_t buf, pnanovdb_map_handle_t map, PNANOVDB_IN(pnanovdb_vec3_t) src)
2013 {
2014     pnanovdb_vec3_t  dst;
2015     float sx = PNANOVDB_DEREF(src).x;
2016     float sy = PNANOVDB_DEREF(src).y;
2017     float sz = PNANOVDB_DEREF(src).z;
2018     dst.x = sx * pnanovdb_map_get_matf(buf, map, 0) + sy * pnanovdb_map_get_matf(buf, map, 1) + sz * pnanovdb_map_get_matf(buf, map, 2);
2019     dst.y = sx * pnanovdb_map_get_matf(buf, map, 3) + sy * pnanovdb_map_get_matf(buf, map, 4) + sz * pnanovdb_map_get_matf(buf, map, 5);
2020     dst.z = sx * pnanovdb_map_get_matf(buf, map, 6) + sy * pnanovdb_map_get_matf(buf, map, 7) + sz * pnanovdb_map_get_matf(buf, map, 8);
2021     return dst;
2022 }
2023 
pnanovdb_map_apply_inverse_jacobi(pnanovdb_buf_t buf,pnanovdb_map_handle_t map,PNANOVDB_IN (pnanovdb_vec3_t)src)2024 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_map_apply_inverse_jacobi(pnanovdb_buf_t buf, pnanovdb_map_handle_t map, PNANOVDB_IN(pnanovdb_vec3_t) src)
2025 {
2026     pnanovdb_vec3_t  dst;
2027     float sx = PNANOVDB_DEREF(src).x;
2028     float sy = PNANOVDB_DEREF(src).y;
2029     float sz = PNANOVDB_DEREF(src).z;
2030     dst.x = sx * pnanovdb_map_get_invmatf(buf, map, 0) + sy * pnanovdb_map_get_invmatf(buf, map, 1) + sz * pnanovdb_map_get_invmatf(buf, map, 2);
2031     dst.y = sx * pnanovdb_map_get_invmatf(buf, map, 3) + sy * pnanovdb_map_get_invmatf(buf, map, 4) + sz * pnanovdb_map_get_invmatf(buf, map, 5);
2032     dst.z = sx * pnanovdb_map_get_invmatf(buf, map, 6) + sy * pnanovdb_map_get_invmatf(buf, map, 7) + sz * pnanovdb_map_get_invmatf(buf, map, 8);
2033     return dst;
2034 }
2035 
pnanovdb_grid_world_to_indexf(pnanovdb_buf_t buf,pnanovdb_grid_handle_t grid,PNANOVDB_IN (pnanovdb_vec3_t)src)2036 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_grid_world_to_indexf(pnanovdb_buf_t buf, pnanovdb_grid_handle_t grid, PNANOVDB_IN(pnanovdb_vec3_t) src)
2037 {
2038     pnanovdb_map_handle_t map = pnanovdb_grid_get_map(buf, grid);
2039     return pnanovdb_map_apply_inverse(buf, map, src);
2040 }
2041 
pnanovdb_grid_index_to_worldf(pnanovdb_buf_t buf,pnanovdb_grid_handle_t grid,PNANOVDB_IN (pnanovdb_vec3_t)src)2042 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_grid_index_to_worldf(pnanovdb_buf_t buf, pnanovdb_grid_handle_t grid, PNANOVDB_IN(pnanovdb_vec3_t) src)
2043 {
2044     pnanovdb_map_handle_t map = pnanovdb_grid_get_map(buf, grid);
2045     return pnanovdb_map_apply(buf, map, src);
2046 }
2047 
pnanovdb_grid_world_to_index_dirf(pnanovdb_buf_t buf,pnanovdb_grid_handle_t grid,PNANOVDB_IN (pnanovdb_vec3_t)src)2048 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_grid_world_to_index_dirf(pnanovdb_buf_t buf, pnanovdb_grid_handle_t grid, PNANOVDB_IN(pnanovdb_vec3_t) src)
2049 {
2050     pnanovdb_map_handle_t map = pnanovdb_grid_get_map(buf, grid);
2051     return pnanovdb_map_apply_inverse_jacobi(buf, map, src);
2052 }
2053 
pnanovdb_grid_index_to_world_dirf(pnanovdb_buf_t buf,pnanovdb_grid_handle_t grid,PNANOVDB_IN (pnanovdb_vec3_t)src)2054 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_grid_index_to_world_dirf(pnanovdb_buf_t buf, pnanovdb_grid_handle_t grid, PNANOVDB_IN(pnanovdb_vec3_t) src)
2055 {
2056     pnanovdb_map_handle_t map = pnanovdb_grid_get_map(buf, grid);
2057     return pnanovdb_map_apply_jacobi(buf, map, src);
2058 }
2059 
2060 // ------------------------------------------------ DitherLUT -----------------------------------------------------------
2061 
2062 // This table was generated with
2063 /**************
2064 
2065 static constexpr inline uint32
2066 SYSwang_inthash(uint32 key)
2067 {
2068     // From http://www.concentric.net/~Ttwang/tech/inthash.htm
2069     key += ~(key << 16);
2070     key ^=  (key >> 5);
2071     key +=  (key << 3);
2072     key ^=  (key >> 13);
2073     key += ~(key << 9);
2074     key ^=  (key >> 17);
2075     return key;
2076 }
2077 
2078 static void
2079 ut_initDitherR(float *pattern, float offset,
2080     int x, int y, int z, int res, int goalres)
2081 {
2082     // These offsets are designed to maximize the difference between
2083     // dither values in nearby voxels within a given 2x2x2 cell, without
2084     // producing axis-aligned artifacts.  The are organized in row-major
2085     // order.
2086     static const float  theDitherOffset[] = {0,4,6,2,5,1,3,7};
2087     static const float  theScale = 0.125F;
2088     int         key = (((z << res) + y) << res) + x;
2089 
2090     if (res == goalres)
2091     {
2092     pattern[key] = offset;
2093     return;
2094     }
2095 
2096     // Randomly flip (on each axis) the dithering patterns used by the
2097     // subcells.  This key is xor'd with the subcell index below before
2098     // looking up in the dither offset list.
2099     key = SYSwang_inthash(key) & 7;
2100 
2101     x <<= 1;
2102     y <<= 1;
2103     z <<= 1;
2104 
2105     offset *= theScale;
2106     for (int i = 0; i < 8; i++)
2107     ut_initDitherR(pattern, offset+theDitherOffset[i ^ key]*theScale,
2108         x+(i&1), y+((i&2)>>1), z+((i&4)>>2), res+1, goalres);
2109 }
2110 
2111 // This is a compact algorithm that accomplishes essentially the same thing
2112 // as ut_initDither() above.  We should eventually switch to use this and
2113 // clean the dead code.
2114 static fpreal32 *
2115 ut_initDitherRecursive(int goalres)
2116 {
2117     const int nfloat = 1 << (goalres*3);
2118     float   *pattern = new float[nfloat];
2119     ut_initDitherR(pattern, 1.0F, 0, 0, 0, 0, goalres);
2120 
2121     // This has built an even spacing from 1/nfloat to 1.0.
2122     // however, our dither pattern should be 1/(nfloat+1) to nfloat/(nfloat+1)
2123     // So we do a correction here.  Note that the earlier calculations are
2124     // done with powers of 2 so are exact, so it does make sense to delay
2125     // the renormalization to this pass.
2126     float correctionterm = nfloat / (nfloat+1.0F);
2127     for (int i = 0; i < nfloat; i++)
2128         pattern[i] *= correctionterm;
2129     return pattern;
2130 }
2131 
2132     theDitherMatrix = ut_initDitherRecursive(3);
2133 
2134     for (int i = 0; i < 512/8; i ++)
2135     {
2136         for (int j = 0; j < 8; j ++)
2137             std::cout << theDitherMatrix[i*8+j] << "f, ";
2138         std::cout << std::endl;
2139     }
2140 
2141  **************/
2142 
2143 PNANOVDB_STATIC_CONST float pnanovdb_dither_lut[512] =
2144 {
2145     0.14425f, 0.643275f, 0.830409f, 0.331384f, 0.105263f, 0.604289f, 0.167641f, 0.666667f,
2146     0.892788f, 0.393762f, 0.0818713f, 0.580897f, 0.853801f, 0.354776f, 0.916179f, 0.417154f,
2147     0.612086f, 0.11306f, 0.79922f, 0.300195f, 0.510721f, 0.0116959f, 0.947368f, 0.448343f,
2148     0.362573f, 0.861598f, 0.0506823f, 0.549708f, 0.261209f, 0.760234f, 0.19883f, 0.697856f,
2149     0.140351f, 0.639376f, 0.576998f, 0.0779727f, 0.522417f, 0.0233918f, 0.460039f, 0.959064f,
2150     0.888889f, 0.389864f, 0.327485f, 0.826511f, 0.272904f, 0.77193f, 0.709552f, 0.210526f,
2151     0.483431f, 0.982456f, 0.296296f, 0.795322f, 0.116959f, 0.615984f, 0.0545809f, 0.553606f,
2152     0.732943f, 0.233918f, 0.545809f, 0.0467836f, 0.865497f, 0.366472f, 0.803119f, 0.304094f,
2153     0.518519f, 0.0194932f, 0.45614f, 0.955166f, 0.729045f, 0.230019f, 0.54191f, 0.042885f,
2154     0.269006f, 0.768031f, 0.705653f, 0.206628f, 0.479532f, 0.978558f, 0.292398f, 0.791423f,
2155     0.237817f, 0.736842f, 0.424951f, 0.923977f, 0.136452f, 0.635478f, 0.323587f, 0.822612f,
2156     0.986355f, 0.487329f, 0.674464f, 0.175439f, 0.88499f, 0.385965f, 0.573099f, 0.0740741f,
2157     0.51462f, 0.0155945f, 0.202729f, 0.701754f, 0.148148f, 0.647174f, 0.834308f, 0.335283f,
2158     0.265107f, 0.764133f, 0.951267f, 0.452242f, 0.896686f, 0.397661f, 0.08577f, 0.584795f,
2159     0.8577f, 0.358674f, 0.920078f, 0.421053f, 0.740741f, 0.241715f, 0.678363f, 0.179337f,
2160     0.109162f, 0.608187f, 0.17154f, 0.670565f, 0.491228f, 0.990253f, 0.42885f, 0.927875f,
2161     0.0662768f, 0.565302f, 0.62768f, 0.128655f, 0.183236f, 0.682261f, 0.744639f, 0.245614f,
2162     0.814815f, 0.315789f, 0.378168f, 0.877193f, 0.931774f, 0.432749f, 0.495127f, 0.994152f,
2163     0.0350877f, 0.534113f, 0.97076f, 0.471735f, 0.214425f, 0.71345f, 0.526316f, 0.0272904f,
2164     0.783626f, 0.2846f, 0.222222f, 0.721248f, 0.962963f, 0.463938f, 0.276803f, 0.775828f,
2165     0.966862f, 0.467836f, 0.405458f, 0.904483f, 0.0701754f, 0.569201f, 0.881092f, 0.382066f,
2166     0.218324f, 0.717349f, 0.654971f, 0.155945f, 0.818713f, 0.319688f, 0.132554f, 0.631579f,
2167     0.0623782f, 0.561404f, 0.748538f, 0.249513f, 0.912281f, 0.413255f, 0.974659f, 0.475634f,
2168     0.810916f, 0.311891f, 0.499025f, 0.998051f, 0.163743f, 0.662768f, 0.226121f, 0.725146f,
2169     0.690058f, 0.191033f, 0.00389864f, 0.502924f, 0.557505f, 0.0584795f, 0.120858f, 0.619883f,
2170     0.440546f, 0.939571f, 0.752437f, 0.253411f, 0.307992f, 0.807018f, 0.869396f, 0.37037f,
2171     0.658869f, 0.159844f, 0.346979f, 0.846004f, 0.588694f, 0.0896686f, 0.152047f, 0.651072f,
2172     0.409357f, 0.908382f, 0.596491f, 0.0974659f, 0.339181f, 0.838207f, 0.900585f, 0.401559f,
2173     0.34308f, 0.842105f, 0.779727f, 0.280702f, 0.693957f, 0.194932f, 0.25731f, 0.756335f,
2174     0.592593f, 0.0935673f, 0.0311891f, 0.530214f, 0.444444f, 0.94347f, 0.506823f, 0.00779727f,
2175     0.68616f, 0.187135f, 0.124756f, 0.623782f, 0.288499f, 0.787524f, 0.350877f, 0.849903f,
2176     0.436647f, 0.935673f, 0.873294f, 0.374269f, 0.538012f, 0.0389864f, 0.60039f, 0.101365f,
2177     0.57115f, 0.0721248f, 0.758285f, 0.259259f, 0.719298f, 0.220273f, 0.532164f, 0.0331384f,
2178     0.321637f, 0.820663f, 0.00974659f, 0.508772f, 0.469786f, 0.968811f, 0.282651f, 0.781676f,
2179     0.539961f, 0.0409357f, 0.727096f, 0.22807f, 0.500975f, 0.00194932f, 0.563353f, 0.0643275f,
2180     0.290448f, 0.789474f, 0.477583f, 0.976608f, 0.251462f, 0.750487f, 0.31384f, 0.812865f,
2181     0.94152f, 0.442495f, 0.879142f, 0.380117f, 0.37232f, 0.871345f, 0.309942f, 0.808967f,
2182     0.192982f, 0.692008f, 0.130604f, 0.62963f, 0.621832f, 0.122807f, 0.559454f, 0.0604289f,
2183     0.660819f, 0.161793f, 0.723197f, 0.224172f, 0.403509f, 0.902534f, 0.840156f, 0.341131f,
2184     0.411306f, 0.910331f, 0.473684f, 0.97271f, 0.653021f, 0.153996f, 0.0916179f, 0.590643f,
2185     0.196881f, 0.695906f, 0.384016f, 0.883041f, 0.0955166f, 0.594542f, 0.157895f, 0.65692f,
2186     0.945419f, 0.446394f, 0.633528f, 0.134503f, 0.844055f, 0.345029f, 0.906433f, 0.407407f,
2187     0.165692f, 0.664717f, 0.103314f, 0.602339f, 0.126706f, 0.625731f, 0.189084f, 0.688109f,
2188     0.91423f, 0.415205f, 0.851852f, 0.352827f, 0.875244f, 0.376218f, 0.937622f, 0.438596f,
2189     0.317739f, 0.816764f, 0.255361f, 0.754386f, 0.996101f, 0.497076f, 0.933723f, 0.434698f,
2190     0.567251f, 0.0682261f, 0.504873f, 0.00584795f, 0.247563f, 0.746589f, 0.185185f, 0.684211f,
2191     0.037037f, 0.536062f, 0.0994152f, 0.598441f, 0.777778f, 0.278752f, 0.465887f, 0.964912f,
2192     0.785575f, 0.28655f, 0.847953f, 0.348928f, 0.0292398f, 0.528265f, 0.7154f, 0.216374f,
2193     0.39961f, 0.898636f, 0.961014f, 0.461988f, 0.0487329f, 0.547758f, 0.111111f, 0.610136f,
2194     0.649123f, 0.150097f, 0.212476f, 0.711501f, 0.797271f, 0.298246f, 0.859649f, 0.360624f,
2195     0.118908f, 0.617934f, 0.0565302f, 0.555556f, 0.329435f, 0.82846f, 0.516569f, 0.0175439f,
2196     0.867446f, 0.368421f, 0.805068f, 0.306043f, 0.578947f, 0.079922f, 0.267057f, 0.766082f,
2197     0.270955f, 0.76998f, 0.707602f, 0.208577f, 0.668616f, 0.169591f, 0.606238f, 0.107212f,
2198     0.520468f, 0.0214425f, 0.45809f, 0.957115f, 0.419103f, 0.918129f, 0.356725f, 0.855751f,
2199     0.988304f, 0.489279f, 0.426901f, 0.925926f, 0.450292f, 0.949318f, 0.512671f, 0.0136452f,
2200     0.239766f, 0.738791f, 0.676413f, 0.177388f, 0.699805f, 0.20078f, 0.263158f, 0.762183f,
2201     0.773879f, 0.274854f, 0.337232f, 0.836257f, 0.672515f, 0.173489f, 0.734893f, 0.235867f,
2202     0.0253411f, 0.524366f, 0.586745f, 0.0877193f, 0.423002f, 0.922027f, 0.48538f, 0.984405f,
2203     0.74269f, 0.243665f, 0.680312f, 0.181287f, 0.953216f, 0.454191f, 0.1423f, 0.641326f,
2204     0.493177f, 0.992203f, 0.430799f, 0.929825f, 0.204678f, 0.703704f, 0.890838f, 0.391813f,
2205     0.894737f, 0.395712f, 0.0838207f, 0.582846f, 0.0448343f, 0.54386f, 0.231969f, 0.730994f,
2206     0.146199f, 0.645224f, 0.832359f, 0.333333f, 0.793372f, 0.294347f, 0.980507f, 0.481481f,
2207     0.364522f, 0.863548f, 0.80117f, 0.302144f, 0.824561f, 0.325536f, 0.138402f, 0.637427f,
2208     0.614035f, 0.11501f, 0.0526316f, 0.551657f, 0.0760234f, 0.575049f, 0.88694f, 0.387914f,
2209 };
2210 
pnanovdb_dither_lookup(pnanovdb_bool_t enabled,int offset)2211 PNANOVDB_FORCE_INLINE float pnanovdb_dither_lookup(pnanovdb_bool_t enabled, int offset)
2212 {
2213     return enabled ? pnanovdb_dither_lut[offset & 511] : 0.5f;
2214 }
2215 
2216 // ------------------------------------------------ HDDA -----------------------------------------------------------
2217 
2218 #ifdef PNANOVDB_HDDA
2219 
2220 // Comment out to disable this explicit round-off check
2221 #define PNANOVDB_ENFORCE_FORWARD_STEPPING
2222 
2223 #define PNANOVDB_HDDA_FLOAT_MAX 1e38f
2224 
2225 struct pnanovdb_hdda_t
2226 {
2227     pnanovdb_int32_t dim;
2228     float tmin;
2229     float tmax;
2230     pnanovdb_coord_t voxel;
2231     pnanovdb_coord_t step;
2232     pnanovdb_vec3_t delta;
2233     pnanovdb_vec3_t next;
2234 };
PNANOVDB_STRUCT_TYPEDEF(pnanovdb_hdda_t)2235 PNANOVDB_STRUCT_TYPEDEF(pnanovdb_hdda_t)
2236 
2237 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_hdda_pos_to_ijk(PNANOVDB_IN(pnanovdb_vec3_t) pos)
2238 {
2239     pnanovdb_coord_t voxel;
2240     voxel.x = pnanovdb_float_to_int32(pnanovdb_floor(PNANOVDB_DEREF(pos).x));
2241     voxel.y = pnanovdb_float_to_int32(pnanovdb_floor(PNANOVDB_DEREF(pos).y));
2242     voxel.z = pnanovdb_float_to_int32(pnanovdb_floor(PNANOVDB_DEREF(pos).z));
2243     return voxel;
2244 }
2245 
pnanovdb_hdda_pos_to_voxel(PNANOVDB_IN (pnanovdb_vec3_t)pos,int dim)2246 PNANOVDB_FORCE_INLINE pnanovdb_coord_t pnanovdb_hdda_pos_to_voxel(PNANOVDB_IN(pnanovdb_vec3_t) pos, int dim)
2247 {
2248     pnanovdb_coord_t voxel;
2249     voxel.x = pnanovdb_float_to_int32(pnanovdb_floor(PNANOVDB_DEREF(pos).x)) & (~(dim - 1));
2250     voxel.y = pnanovdb_float_to_int32(pnanovdb_floor(PNANOVDB_DEREF(pos).y)) & (~(dim - 1));
2251     voxel.z = pnanovdb_float_to_int32(pnanovdb_floor(PNANOVDB_DEREF(pos).z)) & (~(dim - 1));
2252     return voxel;
2253 }
2254 
pnanovdb_hdda_ray_start(PNANOVDB_IN (pnanovdb_vec3_t)origin,float tmin,PNANOVDB_IN (pnanovdb_vec3_t)direction)2255 PNANOVDB_FORCE_INLINE pnanovdb_vec3_t pnanovdb_hdda_ray_start(PNANOVDB_IN(pnanovdb_vec3_t) origin, float tmin, PNANOVDB_IN(pnanovdb_vec3_t) direction)
2256 {
2257     pnanovdb_vec3_t pos = pnanovdb_vec3_add(
2258         pnanovdb_vec3_mul(PNANOVDB_DEREF(direction), pnanovdb_vec3_uniform(tmin)),
2259         PNANOVDB_DEREF(origin)
2260     );
2261     return pos;
2262 }
2263 
pnanovdb_hdda_init(PNANOVDB_INOUT (pnanovdb_hdda_t)hdda,PNANOVDB_IN (pnanovdb_vec3_t)origin,float tmin,PNANOVDB_IN (pnanovdb_vec3_t)direction,float tmax,int dim)2264 PNANOVDB_FORCE_INLINE void pnanovdb_hdda_init(PNANOVDB_INOUT(pnanovdb_hdda_t) hdda, PNANOVDB_IN(pnanovdb_vec3_t) origin, float tmin, PNANOVDB_IN(pnanovdb_vec3_t) direction, float tmax, int dim)
2265 {
2266     PNANOVDB_DEREF(hdda).dim = dim;
2267     PNANOVDB_DEREF(hdda).tmin = tmin;
2268     PNANOVDB_DEREF(hdda).tmax = tmax;
2269 
2270     pnanovdb_vec3_t pos = pnanovdb_hdda_ray_start(origin, tmin, direction);
2271     pnanovdb_vec3_t dir_inv = pnanovdb_vec3_div(pnanovdb_vec3_uniform(1.f), PNANOVDB_DEREF(direction));
2272 
2273     PNANOVDB_DEREF(hdda).voxel = pnanovdb_hdda_pos_to_voxel(PNANOVDB_REF(pos), dim);
2274 
2275     // x
2276     if (PNANOVDB_DEREF(direction).x == 0.f)
2277     {
2278         PNANOVDB_DEREF(hdda).next.x = PNANOVDB_HDDA_FLOAT_MAX;
2279         PNANOVDB_DEREF(hdda).step.x = 0;
2280         PNANOVDB_DEREF(hdda).delta.x = 0.f;
2281     }
2282     else if (dir_inv.x > 0.f)
2283     {
2284         PNANOVDB_DEREF(hdda).step.x = 1;
2285         PNANOVDB_DEREF(hdda).next.x = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.x + dim - pos.x) * dir_inv.x;
2286         PNANOVDB_DEREF(hdda).delta.x = dir_inv.x;
2287     }
2288     else
2289     {
2290         PNANOVDB_DEREF(hdda).step.x = -1;
2291         PNANOVDB_DEREF(hdda).next.x = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.x - pos.x) * dir_inv.x;
2292         PNANOVDB_DEREF(hdda).delta.x = -dir_inv.x;
2293     }
2294 
2295     // y
2296     if (PNANOVDB_DEREF(direction).y == 0.f)
2297     {
2298         PNANOVDB_DEREF(hdda).next.y = PNANOVDB_HDDA_FLOAT_MAX;
2299         PNANOVDB_DEREF(hdda).step.y = 0;
2300         PNANOVDB_DEREF(hdda).delta.y = 0.f;
2301     }
2302     else if (dir_inv.y > 0.f)
2303     {
2304         PNANOVDB_DEREF(hdda).step.y = 1;
2305         PNANOVDB_DEREF(hdda).next.y = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.y + dim - pos.y) * dir_inv.y;
2306         PNANOVDB_DEREF(hdda).delta.y = dir_inv.y;
2307     }
2308     else
2309     {
2310         PNANOVDB_DEREF(hdda).step.y = -1;
2311         PNANOVDB_DEREF(hdda).next.y = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.y - pos.y) * dir_inv.y;
2312         PNANOVDB_DEREF(hdda).delta.y = -dir_inv.y;
2313     }
2314 
2315     // z
2316     if (PNANOVDB_DEREF(direction).z == 0.f)
2317     {
2318         PNANOVDB_DEREF(hdda).next.z = PNANOVDB_HDDA_FLOAT_MAX;
2319         PNANOVDB_DEREF(hdda).step.z = 0;
2320         PNANOVDB_DEREF(hdda).delta.z = 0.f;
2321     }
2322     else if (dir_inv.z > 0.f)
2323     {
2324         PNANOVDB_DEREF(hdda).step.z = 1;
2325         PNANOVDB_DEREF(hdda).next.z = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.z + dim - pos.z) * dir_inv.z;
2326         PNANOVDB_DEREF(hdda).delta.z = dir_inv.z;
2327     }
2328     else
2329     {
2330         PNANOVDB_DEREF(hdda).step.z = -1;
2331         PNANOVDB_DEREF(hdda).next.z = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.z - pos.z) * dir_inv.z;
2332         PNANOVDB_DEREF(hdda).delta.z = -dir_inv.z;
2333     }
2334 }
2335 
pnanovdb_hdda_update(PNANOVDB_INOUT (pnanovdb_hdda_t)hdda,PNANOVDB_IN (pnanovdb_vec3_t)origin,PNANOVDB_IN (pnanovdb_vec3_t)direction,int dim)2336 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_hdda_update(PNANOVDB_INOUT(pnanovdb_hdda_t) hdda, PNANOVDB_IN(pnanovdb_vec3_t) origin, PNANOVDB_IN(pnanovdb_vec3_t) direction, int dim)
2337 {
2338     if (PNANOVDB_DEREF(hdda).dim == dim)
2339     {
2340         return PNANOVDB_FALSE;
2341     }
2342     PNANOVDB_DEREF(hdda).dim = dim;
2343 
2344     pnanovdb_vec3_t pos = pnanovdb_vec3_add(
2345         pnanovdb_vec3_mul(PNANOVDB_DEREF(direction), pnanovdb_vec3_uniform(PNANOVDB_DEREF(hdda).tmin)),
2346         PNANOVDB_DEREF(origin)
2347     );
2348     pnanovdb_vec3_t dir_inv = pnanovdb_vec3_div(pnanovdb_vec3_uniform(1.f), PNANOVDB_DEREF(direction));
2349 
2350     PNANOVDB_DEREF(hdda).voxel = pnanovdb_hdda_pos_to_voxel(PNANOVDB_REF(pos), dim);
2351 
2352     if (PNANOVDB_DEREF(hdda).step.x != 0)
2353     {
2354         PNANOVDB_DEREF(hdda).next.x = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.x - pos.x) * dir_inv.x;
2355         if (PNANOVDB_DEREF(hdda).step.x > 0)
2356         {
2357             PNANOVDB_DEREF(hdda).next.x += dim * dir_inv.x;
2358         }
2359     }
2360     if (PNANOVDB_DEREF(hdda).step.y != 0)
2361     {
2362         PNANOVDB_DEREF(hdda).next.y = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.y - pos.y) * dir_inv.y;
2363         if (PNANOVDB_DEREF(hdda).step.y > 0)
2364         {
2365             PNANOVDB_DEREF(hdda).next.y += dim * dir_inv.y;
2366         }
2367     }
2368     if (PNANOVDB_DEREF(hdda).step.z != 0)
2369     {
2370         PNANOVDB_DEREF(hdda).next.z = PNANOVDB_DEREF(hdda).tmin + (PNANOVDB_DEREF(hdda).voxel.z - pos.z) * dir_inv.z;
2371         if (PNANOVDB_DEREF(hdda).step.z > 0)
2372         {
2373             PNANOVDB_DEREF(hdda).next.z += dim * dir_inv.z;
2374         }
2375     }
2376 
2377     return PNANOVDB_TRUE;
2378 }
2379 
pnanovdb_hdda_step(PNANOVDB_INOUT (pnanovdb_hdda_t)hdda)2380 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_hdda_step(PNANOVDB_INOUT(pnanovdb_hdda_t) hdda)
2381 {
2382     pnanovdb_bool_t ret;
2383     if (PNANOVDB_DEREF(hdda).next.x < PNANOVDB_DEREF(hdda).next.y && PNANOVDB_DEREF(hdda).next.x < PNANOVDB_DEREF(hdda).next.z)
2384     {
2385 #ifdef PNANOVDB_ENFORCE_FORWARD_STEPPING
2386         if (PNANOVDB_DEREF(hdda).next.x <= PNANOVDB_DEREF(hdda).tmin)
2387         {
2388             PNANOVDB_DEREF(hdda).next.x += PNANOVDB_DEREF(hdda).tmin - 0.999999f * PNANOVDB_DEREF(hdda).next.x + 1.0e-6f;
2389         }
2390 #endif
2391         PNANOVDB_DEREF(hdda).tmin = PNANOVDB_DEREF(hdda).next.x;
2392         PNANOVDB_DEREF(hdda).next.x += PNANOVDB_DEREF(hdda).dim * PNANOVDB_DEREF(hdda).delta.x;
2393         PNANOVDB_DEREF(hdda).voxel.x += PNANOVDB_DEREF(hdda).dim * PNANOVDB_DEREF(hdda).step.x;
2394         ret = PNANOVDB_DEREF(hdda).tmin <= PNANOVDB_DEREF(hdda).tmax;
2395     }
2396     else if (PNANOVDB_DEREF(hdda).next.y < PNANOVDB_DEREF(hdda).next.z)
2397     {
2398 #ifdef PNANOVDB_ENFORCE_FORWARD_STEPPING
2399         if (PNANOVDB_DEREF(hdda).next.y <= PNANOVDB_DEREF(hdda).tmin)
2400         {
2401             PNANOVDB_DEREF(hdda).next.y += PNANOVDB_DEREF(hdda).tmin - 0.999999f * PNANOVDB_DEREF(hdda).next.y + 1.0e-6f;
2402         }
2403 #endif
2404         PNANOVDB_DEREF(hdda).tmin = PNANOVDB_DEREF(hdda).next.y;
2405         PNANOVDB_DEREF(hdda).next.y += PNANOVDB_DEREF(hdda).dim * PNANOVDB_DEREF(hdda).delta.y;
2406         PNANOVDB_DEREF(hdda).voxel.y += PNANOVDB_DEREF(hdda).dim * PNANOVDB_DEREF(hdda).step.y;
2407         ret = PNANOVDB_DEREF(hdda).tmin <= PNANOVDB_DEREF(hdda).tmax;
2408     }
2409     else
2410     {
2411 #ifdef PNANOVDB_ENFORCE_FORWARD_STEPPING
2412         if (PNANOVDB_DEREF(hdda).next.z <= PNANOVDB_DEREF(hdda).tmin)
2413         {
2414             PNANOVDB_DEREF(hdda).next.z += PNANOVDB_DEREF(hdda).tmin - 0.999999f * PNANOVDB_DEREF(hdda).next.z + 1.0e-6f;
2415         }
2416 #endif
2417         PNANOVDB_DEREF(hdda).tmin = PNANOVDB_DEREF(hdda).next.z;
2418         PNANOVDB_DEREF(hdda).next.z += PNANOVDB_DEREF(hdda).dim * PNANOVDB_DEREF(hdda).delta.z;
2419         PNANOVDB_DEREF(hdda).voxel.z += PNANOVDB_DEREF(hdda).dim * PNANOVDB_DEREF(hdda).step.z;
2420         ret = PNANOVDB_DEREF(hdda).tmin <= PNANOVDB_DEREF(hdda).tmax;
2421     }
2422     return ret;
2423 }
2424 
pnanovdb_hdda_ray_clip(PNANOVDB_IN (pnanovdb_vec3_t)bbox_min,PNANOVDB_IN (pnanovdb_vec3_t)bbox_max,PNANOVDB_IN (pnanovdb_vec3_t)origin,PNANOVDB_INOUT (float)tmin,PNANOVDB_IN (pnanovdb_vec3_t)direction,PNANOVDB_INOUT (float)tmax)2425 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_hdda_ray_clip(
2426     PNANOVDB_IN(pnanovdb_vec3_t) bbox_min,
2427     PNANOVDB_IN(pnanovdb_vec3_t) bbox_max,
2428     PNANOVDB_IN(pnanovdb_vec3_t) origin, PNANOVDB_INOUT(float) tmin,
2429     PNANOVDB_IN(pnanovdb_vec3_t) direction, PNANOVDB_INOUT(float) tmax
2430 )
2431 {
2432     pnanovdb_vec3_t dir_inv = pnanovdb_vec3_div(pnanovdb_vec3_uniform(1.f), PNANOVDB_DEREF(direction));
2433     pnanovdb_vec3_t t0 = pnanovdb_vec3_mul(pnanovdb_vec3_sub(PNANOVDB_DEREF(bbox_min), PNANOVDB_DEREF(origin)), dir_inv);
2434     pnanovdb_vec3_t t1 = pnanovdb_vec3_mul(pnanovdb_vec3_sub(PNANOVDB_DEREF(bbox_max), PNANOVDB_DEREF(origin)), dir_inv);
2435     pnanovdb_vec3_t tmin3 = pnanovdb_vec3_min(t0, t1);
2436     pnanovdb_vec3_t tmax3 = pnanovdb_vec3_max(t0, t1);
2437     float tnear = pnanovdb_max(tmin3.x, pnanovdb_max(tmin3.y, tmin3.z));
2438     float tfar = pnanovdb_min(tmax3.x, pnanovdb_min(tmax3.y, tmax3.z));
2439     pnanovdb_bool_t hit = tnear <= tfar;
2440     PNANOVDB_DEREF(tmin) = pnanovdb_max(PNANOVDB_DEREF(tmin), tnear);
2441     PNANOVDB_DEREF(tmax) = pnanovdb_min(PNANOVDB_DEREF(tmax), tfar);
2442     return hit;
2443 }
2444 
pnanovdb_hdda_zero_crossing(pnanovdb_grid_type_t grid_type,pnanovdb_buf_t buf,PNANOVDB_INOUT (pnanovdb_readaccessor_t)acc,PNANOVDB_IN (pnanovdb_vec3_t)origin,float tmin,PNANOVDB_IN (pnanovdb_vec3_t)direction,float tmax,PNANOVDB_INOUT (float)thit,PNANOVDB_INOUT (float)v)2445 PNANOVDB_FORCE_INLINE pnanovdb_bool_t pnanovdb_hdda_zero_crossing(
2446     pnanovdb_grid_type_t grid_type,
2447     pnanovdb_buf_t buf,
2448     PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc,
2449     PNANOVDB_IN(pnanovdb_vec3_t) origin, float tmin,
2450     PNANOVDB_IN(pnanovdb_vec3_t) direction, float tmax,
2451     PNANOVDB_INOUT(float) thit,
2452     PNANOVDB_INOUT(float) v
2453 )
2454 {
2455     pnanovdb_coord_t bbox_min = pnanovdb_root_get_bbox_min(buf, PNANOVDB_DEREF(acc).root);
2456     pnanovdb_coord_t bbox_max = pnanovdb_root_get_bbox_max(buf, PNANOVDB_DEREF(acc).root);
2457     pnanovdb_vec3_t bbox_minf = pnanovdb_coord_to_vec3(bbox_min);
2458     pnanovdb_vec3_t bbox_maxf = pnanovdb_coord_to_vec3(pnanovdb_coord_add(bbox_max, pnanovdb_coord_uniform(1)));
2459 
2460     pnanovdb_bool_t hit = pnanovdb_hdda_ray_clip(PNANOVDB_REF(bbox_minf), PNANOVDB_REF(bbox_maxf), origin, PNANOVDB_REF(tmin), direction, PNANOVDB_REF(tmax));
2461     if (!hit || tmax > 1.0e20f)
2462     {
2463         return PNANOVDB_FALSE;
2464     }
2465 
2466     pnanovdb_vec3_t pos = pnanovdb_hdda_ray_start(origin, tmin, direction);
2467     pnanovdb_coord_t ijk = pnanovdb_hdda_pos_to_ijk(PNANOVDB_REF(pos));
2468 
2469     pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, PNANOVDB_REF(ijk));
2470     float v0 = pnanovdb_read_float(buf, address);
2471 
2472     pnanovdb_int32_t dim = pnanovdb_uint32_as_int32(pnanovdb_readaccessor_get_dim(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, PNANOVDB_REF(ijk)));
2473     pnanovdb_hdda_t hdda;
2474     pnanovdb_hdda_init(PNANOVDB_REF(hdda), origin, tmin, direction, tmax, dim);
2475     while (pnanovdb_hdda_step(PNANOVDB_REF(hdda)))
2476     {
2477         pnanovdb_vec3_t pos_start = pnanovdb_hdda_ray_start(origin, hdda.tmin + 1.0001f, direction);
2478         ijk = pnanovdb_hdda_pos_to_ijk(PNANOVDB_REF(pos_start));
2479         dim = pnanovdb_uint32_as_int32(pnanovdb_readaccessor_get_dim(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, PNANOVDB_REF(ijk)));
2480         pnanovdb_hdda_update(PNANOVDB_REF(hdda), origin, direction, dim);
2481         if (hdda.dim > 1 || !pnanovdb_readaccessor_is_active(grid_type, buf, acc, PNANOVDB_REF(ijk)))
2482         {
2483             continue;
2484         }
2485         while (pnanovdb_hdda_step(PNANOVDB_REF(hdda)) && pnanovdb_readaccessor_is_active(grid_type, buf, acc, PNANOVDB_REF(hdda.voxel)))
2486         {
2487             ijk = hdda.voxel;
2488             pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, PNANOVDB_REF(ijk));
2489             PNANOVDB_DEREF(v) = pnanovdb_read_float(buf, address);
2490             if (PNANOVDB_DEREF(v) * v0 < 0.f)
2491             {
2492                 PNANOVDB_DEREF(thit) = hdda.tmin;
2493                 return PNANOVDB_TRUE;
2494             }
2495         }
2496     }
2497     return PNANOVDB_FALSE;
2498 }
2499 
2500 #endif
2501 
2502 #endif // end of NANOVDB_PNANOVDB_H_HAS_BEEN_INCLUDED
2503