OpenVDB 13.2.0
Loading...
Searching...
No Matches
NanoVDB.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 \file nanovdb/NanoVDB.h
6
7 \author Ken Museth
8
9 \date January 8, 2020
10
11 \brief Implements a light-weight self-contained VDB data-structure in a
12 single file! In other words, this is a significantly watered-down
13 version of the OpenVDB implementation, with few dependencies - so
14 a one-stop-shop for a minimalistic VDB data structure that run on
15 most platforms!
16
17 \note It is important to note that NanoVDB (by design) is a read-only
18 sparse GPU (and CPU) friendly data structure intended for applications
19 like rendering and collision detection. As such it obviously lacks
20 a lot of the functionality and features of OpenVDB grids. NanoVDB
21 is essentially a compact linearized (or serialized) representation of
22 an OpenVDB tree with getValue methods only. For best performance use
23 the ReadAccessor::getValue method as opposed to the Tree::getValue
24 method. Note that since a ReadAccessor caches previous access patterns
25 it is by design not thread-safe, so use one instantiation per thread
26 (it is very light-weight). Also, it is not safe to copy accessors between
27 the GPU and CPU! In fact, client code should only interface
28 with the API of the Grid class (all other nodes of the NanoVDB data
29 structure can safely be ignored by most client codes)!
30
31
32 \warning NanoVDB grids can only be constructed via tools like createNanoGrid
33 or the GridBuilder. This explains why none of the grid nodes defined below
34 have public constructors or destructors.
35
36 \details Please see the following paper for more details on the data structure:
37 K. Museth, “VDB: High-Resolution Sparse Volumes with Dynamic Topology”,
38 ACM Transactions on Graphics 32(3), 2013, which can be found here:
39 http://www.museth.org/Ken/Publications_files/Museth_TOG13.pdf
40
41 NanoVDB was first published there: https://dl.acm.org/doi/fullHtml/10.1145/3450623.3464653
42
43
44 Overview: This file implements the following fundamental class that when combined
45 forms the backbone of the VDB tree data structure:
46
47 Coord- a signed integer coordinate
48 Vec3 - a 3D vector
49 Vec4 - a 4D vector
50 BBox - a bounding box
51 Mask - a bitmask essential to the non-root tree nodes
52 Map - an affine coordinate transformation
53 Grid - contains a Tree and a map for world<->index transformations. Use
54 this class as the main API with client code!
55 Tree - contains a RootNode and getValue methods that should only be used for debugging
56 RootNode - the top-level node of the VDB data structure
57 InternalNode - the internal nodes of the VDB data structure
58 LeafNode - the lowest level tree nodes that encode voxel values and state
59 ReadAccessor - implements accelerated random access operations
60
61 Semantics: A VDB data structure encodes values and (binary) states associated with
62 signed integer coordinates. Values encoded at the leaf node level are
63 denoted voxel values, and values associated with other tree nodes are referred
64 to as tile values, which by design cover a larger coordinate index domain.
65
66
67 Memory layout:
68
69 It's important to emphasize that all the grid data (defined below) are explicitly 32 byte
70 aligned, which implies that any memory buffer that contains a NanoVDB grid must also be at
71 32 byte aligned. That is, the memory address of the beginning of a buffer (see ascii diagram below)
72 must be divisible by 32, i.e. uintptr_t(&buffer)%32 == 0! If this is not the case, the C++ standard
73 says the behaviour is undefined! Normally this is not a concerns on GPUs, because they use 256 byte
74 aligned allocations, but the same cannot be said about the CPU.
75
76 GridData is always at the very beginning of the buffer immediately followed by TreeData!
77 The remaining nodes and blind-data are allowed to be scattered throughout the buffer,
78 though in practice they are arranged as:
79
80 GridData: 672 bytes (e.g. magic, checksum, major, flags, index, count, size, name, map, world bbox, voxel size, class, type, offset, count)
81
82 TreeData: 64 bytes (node counts and byte offsets)
83
84 ... optional padding ...
85
86 RootData: size depends on ValueType (index bbox, voxel count, tile count, min/max/avg/standard deviation)
87
88 Array of: RootData::Tile
89
90 ... optional padding ...
91
92 Array of: Upper InternalNodes of size 32^3: bbox, two bit masks, 32768 tile values, and min/max/avg/standard deviation values
93
94 ... optional padding ...
95
96 Array of: Lower InternalNodes of size 16^3: bbox, two bit masks, 4096 tile values, and min/max/avg/standard deviation values
97
98 ... optional padding ...
99
100 Array of: LeafNodes of size 8^3: bbox, bit masks, 512 voxel values, and min/max/avg/standard deviation values
101
102 ... optional padding ...
103
104 Array of: GridBlindMetaData (288 bytes). The offset and count are defined in GridData::mBlindMetadataOffset and GridData::mBlindMetadataCount
105
106 ... optional padding ...
107
108 Array of: blind data
109
110 Notation: "]---[" implies it has optional padding, and "][" implies zero padding
111
112 [GridData(672B)][TreeData(64B)]---[RootData][N x Root::Tile]---[InternalData<5>]---[InternalData<4>]---[LeafData<3>]---[BLINDMETA...]---[BLIND0]---[BLIND1]---etc.
113 ^ ^ ^ ^ ^ ^ ^
114 | | | | | | GridBlindMetaData*
115 +-- Start of 32B aligned buffer | | | | +-- Node0::DataType* leafData
116 GridType::DataType* gridData | | | |
117 | | | +-- Node1::DataType* lowerData
118 RootType::DataType* rootData --+ | |
119 | +-- Node2::DataType* upperData
120 |
121 +-- RootType::DataType::Tile* tile
122
123*/
124
125#ifndef NANOVDB_NANOVDB_H_HAS_BEEN_INCLUDED
126#define NANOVDB_NANOVDB_H_HAS_BEEN_INCLUDED
127
128// The following two header files are the only mandatory dependencies
129#include <nanovdb/util/Util.h>// for __hostdev__ and lots of other utility functions
130#include <nanovdb/math/Math.h>// for Coord, BBox, Vec3, Vec4 etc
131
132// Do not change this value! 32 byte alignment is fixed in NanoVDB
133#define NANOVDB_DATA_ALIGNMENT 32
134
135// NANOVDB_MAGIC_NUMB previously used for both grids and files (starting with v32.6.0)
136// NANOVDB_MAGIC_GRID currently used exclusively for grids (serialized to a single buffer)
137// NANOVDB_MAGIC_FILE currently used exclusively for files
138// | : 0 in 30 corresponds to 0 in NanoVDB0
139#define NANOVDB_MAGIC_NUMB 0x304244566f6e614eUL // "NanoVDB0" in hex - little endian (uint64_t)
140#define NANOVDB_MAGIC_GRID 0x314244566f6e614eUL // "NanoVDB1" in hex - little endian (uint64_t)
141#define NANOVDB_MAGIC_FILE 0x324244566f6e614eUL // "NanoVDB2" in hex - little endian (uint64_t)
142#define NANOVDB_MAGIC_MASK 0x00FFFFFFFFFFFFFFUL // use this mask to remove the number
143
144#define NANOVDB_USE_NEW_MAGIC_NUMBERS// enables use of the new magic numbers described above
145
146#define NANOVDB_MAJOR_VERSION_NUMBER 32 // reflects changes to the ABI and hence also the file format
147#define NANOVDB_MINOR_VERSION_NUMBER 10 // reflects changes to the API but not ABI
148#define NANOVDB_PATCH_VERSION_NUMBER 0 // reflects changes that do not affect the ABI or API
149
150#define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
151
152// This replaces a Coord key at the root level with a single uint64_t
153#define NANOVDB_USE_SINGLE_ROOT_KEY
154
155// This replaces three levels of Coord keys in the ReadAccessor with one Coord
156//#define NANOVDB_USE_SINGLE_ACCESSOR_KEY
157
158// Use this to switch between std::ofstream or FILE implementations
159//#define NANOVDB_USE_IOSTREAMS
160
161// Define NANOVDB_USE_OLD_ACCESSOR before including this header to temporarily
162// restore legacy ReadAccessor behavior where value lookups fall back to root
163// after a leaf-cache miss.
164
165// Comment out to use (slower) branched version of LeafData<FpN,...>::getValue
166#define NANOVDB_FPN_BRANCHLESS
167
168#if !defined(NANOVDB_ALIGN)
169#define NANOVDB_ALIGN(n) alignas(n)
170#endif // !defined(NANOVDB_ALIGN)
171
172namespace nanovdb {// =================================================================
173
174// --------------------------> Build types <------------------------------------
175
176/// @brief Dummy type for a voxel whose value equals an offset into an external value array
178
179/// @brief Dummy type for a voxel whose value equals an offset into an external value array of active values
181
182/// @brief Dummy type for a voxel whose value equals its binary active state
183class ValueMask{};
184
185/// @brief Type containing raw 16 bits for half precision floating point values (IEEE 754 Half)
186class Half
187{
188 public:
189 uint16_t raw;
190};
191
192/// @brief Dummy type for a 4bit quantization of float point values
193class Fp4{};
194
195/// @brief Dummy type for a 8bit quantization of float point values
196class Fp8{};
197
198/// @brief Dummy type for a 16bit quantization of float point values
199class Fp16{};
200
201/// @brief Dummy type for a variable bit quantization of floating point values
202class FpN{};
203
204/// @brief Dummy type for indexing points into voxels
205class Point{};
206
207// --------------------------> GridType <------------------------------------
208
209/// @brief return the number of characters (including null termination) required to convert enum type to a string
210///
211/// @note This curious implementation, which subtracts End from StrLen, avoids duplicate values in the enum!
212template <class EnumT>
213__hostdev__ inline constexpr uint32_t strlen(){return (uint32_t)EnumT::StrLen - (uint32_t)EnumT::End;}
214
215/// @brief List of types that are currently supported by NanoVDB
216///
217/// @note To expand on this list do:
218/// 1) Add the new type between Unknown and End in the enum below
219/// 2) Add the new type to OpenToNanoVDB::processGrid that maps OpenVDB types to GridType
220/// 3) Verify that the ConvertTrait in NanoToOpenVDB.h works correctly with the new type
221/// 4) Add the new type to toGridType (defined below) that maps NanoVDB types to GridType
222/// 5) Add the new type to toStr (defined below)
223enum class GridType : uint32_t { Unknown = 0, // unknown value type - should rarely be used
224 Float = 1, // single precision floating point value
225 Double = 2, // double precision floating point value
226 Int16 = 3, // half precision signed integer value
227 Int32 = 4, // single precision signed integer value
228 Int64 = 5, // double precision signed integer value
229 Vec3f = 6, // single precision floating 3D vector
230 Vec3d = 7, // double precision floating 3D vector
231 Mask = 8, // no value, just the active state
232 Half = 9, // half precision floating point value (IEEE 754 Half)
233 UInt32 = 10, // single precision unsigned integer value
234 Boolean = 11, // boolean value, encoded in bit array
235 RGBA8 = 12, // RGBA packed into 32bit word in reverse-order, i.e. R is lowest byte.
236 Fp4 = 13, // 4bit quantization of floating point value
237 Fp8 = 14, // 8bit quantization of floating point value
238 Fp16 = 15, // 16bit quantization of floating point value
239 FpN = 16, // variable bit quantization of floating point value
240 Vec4f = 17, // single precision floating 4D vector
241 Vec4d = 18, // double precision floating 4D vector
242 Index = 19, // index into an external array of active and inactive values
243 OnIndex = 20, // index into an external array of active values
244 //IndexMask = 21, // retired ValueIndexMask - available for future use
245 //OnIndexMask = 22, // retired ValueOnIndexMask - available for future use
246 PointIndex = 23, // voxels encode indices to co-located points
247 Vec3u8 = 24, // 8bit quantization of floating point 3D vector (only as blind data)
248 Vec3u16 = 25, // 16bit quantization of floating point 3D vector (only as blind data)
249 UInt8 = 26, // 8 bit unsigned integer values (eg 0 -> 255 gray scale)
250 End = 27,// total number of types in this enum (excluding StrLen since it's not a type)
251 StrLen = End + 11};// this entry is used to determine the minimum size of c-string
252
253/// @brief Maps a GridType to a c-string
254/// @param dst destination string of size 12 or larger
255/// @param gridType GridType enum to be mapped to a string
256/// @return Retuns a c-string used to describe a GridType
257__hostdev__ inline char* toStr(char *dst, GridType gridType)
258{
259 switch (gridType){
260 case GridType::Unknown: return util::strcpy(dst, "Unknown");
261 case GridType::Float: return util::strcpy(dst, "float");
262 case GridType::Double: return util::strcpy(dst, "double");
263 case GridType::Int16: return util::strcpy(dst, "int16");
264 case GridType::Int32: return util::strcpy(dst, "int32");
265 case GridType::Int64: return util::strcpy(dst, "int64");
266 case GridType::Vec3f: return util::strcpy(dst, "Vec3f");
267 case GridType::Vec3d: return util::strcpy(dst, "Vec3d");
268 case GridType::Mask: return util::strcpy(dst, "Mask");
269 case GridType::Half: return util::strcpy(dst, "Half");
270 case GridType::UInt32: return util::strcpy(dst, "uint32");
271 case GridType::Boolean: return util::strcpy(dst, "bool");
272 case GridType::RGBA8: return util::strcpy(dst, "RGBA8");
273 case GridType::Fp4: return util::strcpy(dst, "Float4");
274 case GridType::Fp8: return util::strcpy(dst, "Float8");
275 case GridType::Fp16: return util::strcpy(dst, "Float16");
276 case GridType::FpN: return util::strcpy(dst, "FloatN");
277 case GridType::Vec4f: return util::strcpy(dst, "Vec4f");
278 case GridType::Vec4d: return util::strcpy(dst, "Vec4d");
279 case GridType::Index: return util::strcpy(dst, "Index");
280 case GridType::OnIndex: return util::strcpy(dst, "OnIndex");
281 case GridType::PointIndex: return util::strcpy(dst, "PointIndex");// StrLen = 10 + 1 + End
282 case GridType::Vec3u8: return util::strcpy(dst, "Vec3u8");
283 case GridType::Vec3u16: return util::strcpy(dst, "Vec3u16");
284 case GridType::UInt8: return util::strcpy(dst, "uint8");
285 default: return util::strcpy(dst, "End");
286 }
287}
288
289// --------------------------> GridClass <------------------------------------
290
291/// @brief Classes (superset of OpenVDB) that are currently supported by NanoVDB
292enum class GridClass : uint32_t { Unknown = 0,
293 LevelSet = 1, // narrow band level set, e.g. SDF
294 FogVolume = 2, // fog volume, e.g. density
295 Staggered = 3, // staggered MAC grid, e.g. velocity
296 PointIndex = 4, // point index grid
297 PointData = 5, // point data grid
298 Topology = 6, // grid with active states only (no values)
299 VoxelVolume = 7, // volume of geometric cubes, e.g. colors cubes in Minecraft
300 IndexGrid = 8, // grid whose values are offsets, e.g. into an external array
301 TensorGrid = 9, // Index grid for indexing learnable tensor features
302 VoxelBVH = 10, // grid where each voxel points to list of primitive ids
303 End = 11,// total number of types in this enum (excluding StrLen since it's not a type)
304 StrLen = End + 7};// this entry is used to determine the minimum size of c-string
305
306
307/// @brief Retuns a c-string used to describe a GridClass
308/// @param dst destination string of size 7 or larger
309/// @param gridClass GridClass enum to be converted to a string
310__hostdev__ inline char* toStr(char *dst, GridClass gridClass)
311{
312 switch (gridClass){
313 case GridClass::Unknown: return util::strcpy(dst, "?");
314 case GridClass::LevelSet: return util::strcpy(dst, "SDF");
315 case GridClass::FogVolume: return util::strcpy(dst, "FOG");
316 case GridClass::Staggered: return util::strcpy(dst, "MAC");
317 case GridClass::PointIndex: return util::strcpy(dst, "PNTIDX");// StrLen = 6 + 1 + End
318 case GridClass::PointData: return util::strcpy(dst, "PNTDAT");
319 case GridClass::Topology: return util::strcpy(dst, "TOPO");
320 case GridClass::VoxelVolume: return util::strcpy(dst, "VOX");
321 case GridClass::IndexGrid: return util::strcpy(dst, "INDEX");
322 case GridClass::TensorGrid: return util::strcpy(dst, "TENSOR");
323 case GridClass::VoxelBVH: return util::strcpy(dst, "VOXBVH");
324 default: return util::strcpy(dst, "END");
325 }
326}
327
328// --------------------------> GridFlags <------------------------------------
329
330/// @brief Grid flags which indicate what extra information is present in the grid buffer.
331enum class GridFlags : uint32_t {
332 HasLongGridName = 1 << 0, // grid name is longer than 256 characters
333 HasBBox = 1 << 1, // nodes contain bounding-boxes of active values
334 HasMinMax = 1 << 2, // nodes contain min/max of active values
335 HasAverage = 1 << 3, // nodes contain averages of active values
336 HasStdDeviation = 1 << 4, // nodes contain standard deviations of active values
337 IsBreadthFirst = 1 << 5, // nodes are typically arranged breadth-first in memory
338 End = 1 << 6, // use End - 1 as a mask for the 5 lower bit flags
339 StrLen = End + 23,// this entry is used to determine the minimum size of c-string
340};
341
342/// @brief Retuns a c-string used to describe a GridFlags
343/// @param dst destination string of size 23 or larger
344/// @param gridFlags GridFlags enum to be converted to a string
345__hostdev__ inline const char* toStr(char *dst, GridFlags gridFlags)
346{
347 switch (gridFlags){
348 case GridFlags::HasLongGridName: return util::strcpy(dst, "has long grid name");
349 case GridFlags::HasBBox: return util::strcpy(dst, "has bbox");
350 case GridFlags::HasMinMax: return util::strcpy(dst, "has min/max");
351 case GridFlags::HasAverage: return util::strcpy(dst, "has average");
352 case GridFlags::HasStdDeviation: return util::strcpy(dst, "has standard deviation");// StrLen = 22 + 1 + End
353 case GridFlags::IsBreadthFirst: return util::strcpy(dst, "is breadth-first");
354 default: return util::strcpy(dst, "end");
355 }
356}
357
358// --------------------------> MagicType <------------------------------------
359
360/// @brief Enums used to identify magic numbers recognized by NanoVDB
361enum class MagicType : uint32_t { Unknown = 0,// first 64 bits are neither of the cases below
362 OpenVDB = 1,// first 32 bits = 0x56444220UL
363 NanoVDB = 2,// first 64 bits = NANOVDB_MAGIC_NUMB
364 NanoGrid = 3,// first 64 bits = NANOVDB_MAGIC_GRID
365 NanoFile = 4,// first 64 bits = NANOVDB_MAGIC_FILE
366 End = 5,
367 StrLen = End + 14};// this entry is used to determine the minimum size of c-string
368
369/// @brief maps 64 bits of magic number to enum
370__hostdev__ inline MagicType toMagic(uint64_t magic)
371{
372 switch (magic){
376 default: return (magic & ~uint32_t(0)) == 0x56444220UL ? MagicType::OpenVDB : MagicType::Unknown;
377 }
378}
379
380/// @brief print 64-bit magic number to string
381/// @param dst destination string of size 25 or larger
382/// @param magic 64 bit magic number to be printed
383/// @return return destination string @c dst
384__hostdev__ inline char* toStr(char *dst, MagicType magic)
385{
386 switch (magic){
387 case MagicType::Unknown: return util::strcpy(dst, "unknown");
388 case MagicType::NanoVDB: return util::strcpy(dst, "nanovdb");
389 case MagicType::NanoGrid: return util::strcpy(dst, "nanovdb::Grid");// StrLen = 13 + 1 + End
390 case MagicType::NanoFile: return util::strcpy(dst, "nanovdb::File");
391 case MagicType::OpenVDB: return util::strcpy(dst, "openvdb");
392 default: return util::strcpy(dst, "end");
393 }
394}
395
396// --------------------------> PointType enums <------------------------------------
397
398// Define the type used when the points are encoded as blind data in the output grid
399enum class PointType : uint32_t { Disable = 0,// no point information e.g. when BuildT != Point
400 PointID = 1,// linear index of type uint32_t to points
401 World64 = 2,// Vec3d in world space
402 World32 = 3,// Vec3f in world space
403 Grid64 = 4,// Vec3d in grid space
404 Grid32 = 5,// Vec3f in grid space
405 Voxel32 = 6,// Vec3f in voxel space
406 Voxel16 = 7,// Vec3u16 in voxel space
407 Voxel8 = 8,// Vec3u8 in voxel space
408 Default = 9,// output matches input, i.e. Vec3d or Vec3f in world space
409 End =10 };
410
411// --------------------------> GridBlindData enums <------------------------------------
412
413/// @brief Blind-data Classes that are currently supported by NanoVDB
414enum class GridBlindDataClass : uint32_t { Unknown = 0,
415 IndexArray = 1,// indices typically used for mapping into other arrays
416 AttributeArray = 2,// attributes typically associated with points
417 GridName = 3,// grid names of length longer than 256 characters
418 ChannelArray = 4,// channel of values typically used by index grids
419 End = 5 };
420
421/// @brief Blind-data Semantics that are currently understood by NanoVDB
422enum class GridBlindDataSemantic : uint32_t { Unknown = 0,
423 PointPosition = 1, // 3D coordinates in an unknown space
424 PointColor = 2, // color associated with point
425 PointNormal = 3,// normal associated with point
426 PointRadius = 4,// radius of point
427 PointVelocity = 5,// velocity associated with point
428 PointId = 6,// integer ID of point
429 WorldCoords = 7, // 3D coordinates in world space, e.g. (0.056, 0.8, 1,8)
430 GridCoords = 8, // 3D coordinates in grid space, e.g. (1.2, 4.0, 5.7), aka index-space
431 VoxelCoords = 9, // 3D coordinates in voxel space, e.g. (0.2, 0.0, 0.7)
432 LevelSet = 10, // narrow band level set, e.g. SDF
433 FogVolume = 11, // fog volume, e.g. density
434 Staggered = 12, // staggered MAC grid, e.g. velocity
435 PointOpacity = 13, // opacity associated with point
436 PointQuat = 14, // quaternion rotation, wxyz convention
437 PointScale = 15, // vec3 scale
438 PointSH0 = 16, // spherical harmonics, DC component
439 PointSHN = 17, // spherical haromnics, AC components
440 LineId = 18, // integer ID of line
441 TriangleId = 19, // integer ID of triangle
442 GaussianId = 20, // integer ID of Gaussian
443 Range = 21, // begin/end pair of indices
444 VoxelBVH = 22, // voxelbvh 64-bit voxel value
445 End = 23 };
446
447/// @brief Maps from GridBlindDataSemantic to GridClass
448/// @note Useful when converting an IndexGrid with blind data of type T into a Grid<T>
449/// @param semantics GridBlindDataSemantic
450/// @param defaultClass Default return type used for no match
451/// @return GridClass
480
481/// @brief Maps from GridClass to GridBlindDataSemantic.
482/// @note Useful when converting a Grid<T> into an IndexGrid with blind data of type T.
483/// @param gridClass GridClass
484/// @param defaultSemantic Default return type used for no match
485/// @return GridBlindDataSemantic
488{
489 switch (gridClass){
500 default:
501 return defaultSemantic;
502 }
503}
504
505// --------------------------> BuildTraits <------------------------------------
506
507/// @brief Define static boolean tests for template build types
508template<typename T>
510{
511 // check if T is an index type
515 // check if T is a compressed float type with fixed bit precision
517 // check if T is a compressed float type with fixed or variable bit precision
519 // check if T is a POD float type, i.e float or double
521 // check if T is a template specialization of LeafData<T>, i.e. has T mValues[512]
523}; // BuildTraits
524
525// --------------------------> BuildToValueMap <------------------------------------
526
527/// @brief Maps one type (e.g. the build types above) to other (actual) types
528template<typename T>
530{
531 using Type = T;
532 using type = T;
533};
534
535template<>
537{
538 using Type = uint64_t;
539 using type = uint64_t;
540};
541
542template<>
544{
545 using Type = uint64_t;
546 using type = uint64_t;
547};
548
549template<>
551{
552 using Type = bool;
553 using type = bool;
554};
555
556template<>
558{
559 using Type = float;
560 using type = float;
561};
562
563template<>
565{
566 using Type = float;
567 using type = float;
568};
569
570template<>
572{
573 using Type = float;
574 using type = float;
575};
576
577template<>
579{
580 using Type = float;
581 using type = float;
582};
583
584template<>
586{
587 using Type = uint64_t;
588 using type = uint64_t;
589};
590
591template<typename T>
593
594// --------------------------> utility functions related to alignment <------------------------------------
595
596/// @brief return true if the specified pointer is 32 byte aligned
597__hostdev__ inline static bool isAligned(const void* p){return uint64_t(p) % NANOVDB_DATA_ALIGNMENT == 0;}
598
599/// @brief return the smallest number of bytes that when added to the specified pointer results in a 32 byte aligned pointer.
600__hostdev__ inline static uint64_t alignmentPadding(const void* p)
601{
604}
605
606/// @brief offset the specified pointer so it is 32 byte aligned. Works with both const and non-const pointers.
607template <typename T>
608__hostdev__ inline static T* alignPtr(T* p){return util::PtrAdd<T>(p, alignmentPadding(p));}
609
610// --------------------------> isFloatingPoint(GridType) <------------------------------------
611
612/// @brief return true if the GridType maps to a floating point type
614{
615 return gridType == GridType::Float ||
616 gridType == GridType::Double ||
617 gridType == GridType::Half ||
618 gridType == GridType::Fp4 ||
619 gridType == GridType::Fp8 ||
620 gridType == GridType::Fp16 ||
621 gridType == GridType::FpN;
622}
623
624// --------------------------> isFloatingPointVector(GridType) <------------------------------------
625
626/// @brief return true if the GridType maps to a floating point vec3.
628{
629 return gridType == GridType::Vec3f ||
630 gridType == GridType::Vec3d ||
631 gridType == GridType::Vec4f ||
632 gridType == GridType::Vec4d;
633}
634
635// --------------------------> isInteger(GridType) <------------------------------------
636
637/// @brief Return true if the GridType maps to a POD integer type.
638/// @details These types are used to associate a voxel with a POD integer type
639__hostdev__ inline bool isInteger(GridType gridType)
640{
641 return gridType == GridType::Int16 ||
642 gridType == GridType::Int32 ||
643 gridType == GridType::Int64 ||
644 gridType == GridType::UInt32||
645 gridType == GridType::UInt8;
646}
647
648// --------------------------> isIndex(GridType) <------------------------------------
649
650/// @brief Return true if the GridType maps to a special index type (not a POD integer type).
651/// @details These types are used to index from a voxel into an external array of values, e.g. sidecar or blind data.
652__hostdev__ inline bool isIndex(GridType gridType)
653{
654 return gridType == GridType::Index ||// index both active and inactive values
655 gridType == GridType::OnIndex;// index active values only
656}
657
658// --------------------------> isValue(GridType, GridClass) <------------------------------------
659
660/// @brief return true if the combination of GridType and GridClass is valid.
661__hostdev__ inline bool isValid(GridType gridType, GridClass gridClass)
662{
663 if (gridClass == GridClass::LevelSet || gridClass == GridClass::FogVolume) {
664 return isFloatingPoint(gridType) || gridType == GridType::Half;
665 } else if (gridClass == GridClass::Staggered) {
666 return isFloatingPointVector(gridType);
667 } else if (gridClass == GridClass::PointIndex || gridClass == GridClass::PointData) {
668 return gridType == GridType::PointIndex || gridType == GridType::UInt32;
669 } else if (gridClass == GridClass::Topology) {
670 return gridType == GridType::Mask;
671 } else if (gridClass == GridClass::IndexGrid) {
672 return isIndex(gridType);
673 } else if (gridClass == GridClass::VoxelVolume) {
674 return gridType == GridType::RGBA8 || gridType == GridType::Float ||
675 gridType == GridType::Double || gridType == GridType::Vec3f ||
676 gridType == GridType::Vec3d || gridType == GridType::UInt32 ||
677 gridType == GridType::UInt8 || gridType == GridType::Half;
678 }
679 return gridClass < GridClass::End && gridType < GridType::End; // any valid combination
680}
681
682// --------------------------> validation of blind data meta data <------------------------------------
683
684/// @brief return true if the combination of GridBlindDataClass, GridBlindDataSemantic and GridType is valid.
685__hostdev__ inline bool isValid(const GridBlindDataClass& blindClass,
686 const GridBlindDataSemantic& blindSemantics,
687 const GridType& blindType)
688{
689 bool test = false;
690 switch (blindClass) {
692 test = (blindSemantics == GridBlindDataSemantic::Unknown ||
693 blindSemantics == GridBlindDataSemantic::PointId) &&
694 isInteger(blindType);
695 break;
697 if (blindSemantics == GridBlindDataSemantic::PointPosition ||
698 blindSemantics == GridBlindDataSemantic::WorldCoords) {
699 test = blindType == GridType::Vec3f || blindType == GridType::Vec3d;
700 } else if (blindSemantics == GridBlindDataSemantic::GridCoords) {
701 test = blindType == GridType::Vec3f;
702 } else if (blindSemantics == GridBlindDataSemantic::VoxelCoords) {
703 test = blindType == GridType::Vec3f || blindType == GridType::Vec3u8 || blindType == GridType::Vec3u16;
704 } else {
705 test = blindSemantics != GridBlindDataSemantic::PointId;
706 }
707 break;
709 test = blindSemantics == GridBlindDataSemantic::Unknown && blindType == GridType::Unknown;
710 break;
711 default: // captures blindClass == Unknown and ChannelArray
712 test = blindClass < GridBlindDataClass::End &&
713 blindSemantics < GridBlindDataSemantic::End &&
714 blindType < GridType::End; // any valid combination
715 break;
716 }
717 //if (!test) printf("Invalid combination: GridBlindDataClass=%u, GridBlindDataSemantic=%u, GridType=%u\n",(uint32_t)blindClass, (uint32_t)blindSemantics, (uint32_t)blindType);
718 return test;
719}
720
721// ----------------------------> Version class <-------------------------------------
722
723/// @brief Bit-compacted representation of all three version numbers
724///
725/// @details major is the top 11 bits, minor is the 11 middle bits and patch is the lower 10 bits
727{
728 uint32_t mData; // 11 + 11 + 10 bit packing of major + minor + patch
729public:
730 static constexpr uint32_t End = 0, StrLen = 8;// for strlen<Version>()
731 /// @brief Default constructor
733 : mData(uint32_t(NANOVDB_MAJOR_VERSION_NUMBER) << 21 |
734 uint32_t(NANOVDB_MINOR_VERSION_NUMBER) << 10 |
736 {
737 }
738 /// @brief Constructor from a raw uint32_t data representation
739 __hostdev__ Version(uint32_t data) : mData(data) {}
740 /// @brief Constructor from major.minor.patch version numbers
741 __hostdev__ Version(uint32_t major, uint32_t minor, uint32_t patch)
742 : mData(major << 21 | minor << 10 | patch)
743 {
744 NANOVDB_ASSERT(major < (1u << 11)); // max value of major is 2047
745 NANOVDB_ASSERT(minor < (1u << 11)); // max value of minor is 2047
746 NANOVDB_ASSERT(patch < (1u << 10)); // max value of patch is 1023
747 }
748 __hostdev__ bool operator==(const Version& rhs) const { return mData == rhs.mData; }
749 __hostdev__ bool operator<( const Version& rhs) const { return mData < rhs.mData; }
750 __hostdev__ bool operator<=(const Version& rhs) const { return mData <= rhs.mData; }
751 __hostdev__ bool operator>( const Version& rhs) const { return mData > rhs.mData; }
752 __hostdev__ bool operator>=(const Version& rhs) const { return mData >= rhs.mData; }
753 __hostdev__ uint32_t id() const { return mData; }
754 __hostdev__ uint32_t getMajor() const { return (mData >> 21) & ((1u << 11) - 1); }
755 __hostdev__ uint32_t getMinor() const { return (mData >> 10) & ((1u << 11) - 1); }
756 __hostdev__ uint32_t getPatch() const { return mData & ((1u << 10) - 1); }
757 __hostdev__ bool isCompatible() const { return this->getMajor() == uint32_t(NANOVDB_MAJOR_VERSION_NUMBER); }
758 /// @brief Returns the difference between major version of this instance and NANOVDB_MAJOR_VERSION_NUMBER
759 /// @return return 0 if the major version equals NANOVDB_MAJOR_VERSION_NUMBER, else a negative age if this
760 /// instance has a smaller major verion (is older), and a positive age if it is newer, i.e. larger.
761 __hostdev__ int age() const {return int(this->getMajor()) - int(NANOVDB_MAJOR_VERSION_NUMBER);}
762}; // Version
763
764/// @brief print the verion number to a c-string
765/// @param dst destination string of size 8 or more
766/// @param v version to be printed
767/// @return returns destination string @c dst
768__hostdev__ inline char* toStr(char *dst, const Version &v)
769{
770 return util::sprint(dst, v.getMajor(), ".",v.getMinor(), ".",v.getPatch());
771}
772
773// ----------------------------> TensorTraits <--------------------------------------
774
775template<typename T, int Rank = (util::is_specialization<T, math::Vec3>::value || util::is_specialization<T, math::Vec4>::value || util::is_same<T, math::Rgba8>::value) ? 1 : 0>
777
778template<typename T>
779struct TensorTraits<T, 0>
780{
781 static const int Rank = 0; // i.e. scalar
782 static const bool IsScalar = true;
783 static const bool IsVector = false;
784 static const int Size = 1;
785 using ElementType = T;
786 static T scalar(const T& s) { return s; }
787};
788
789template<typename T>
790struct TensorTraits<T, 1>
791{
792 static const int Rank = 1; // i.e. vector
793 static const bool IsScalar = false;
794 static const bool IsVector = true;
795 static const int Size = T::SIZE;
796 using ElementType = typename T::ValueType;
797 static ElementType scalar(const T& v) { return v.length(); }
798};
799
800// ----------------------------> FloatTraits <--------------------------------------
801
802template<typename T, int = sizeof(typename TensorTraits<T>::ElementType)>
804{
805 using FloatType = float;
806};
807
808template<typename T>
809struct FloatTraits<T, 8>
810{
811 using FloatType = double;
812};
813
814template<>
815struct FloatTraits<bool, 1>
816{
817 using FloatType = bool;
818};
819
820template<>
821struct FloatTraits<ValueIndex, 1> // size of empty class in C++ is 1 byte and not 0 byte
822{
823 using FloatType = uint64_t;
824};
825
826template<>
827struct FloatTraits<ValueOnIndex, 1> // size of empty class in C++ is 1 byte and not 0 byte
828{
829 using FloatType = uint64_t;
830};
831
832template<>
833struct FloatTraits<ValueMask, 1> // size of empty class in C++ is 1 byte and not 0 byte
834{
835 using FloatType = bool;
836};
837
838template<>
839struct FloatTraits<Point, 1> // size of empty class in C++ is 1 byte and not 0 byte
840{
841 using FloatType = double;
842};
843
844// ----------------------------> mapping BuildType -> GridType <--------------------------------------
845
846/// @brief Maps from a templated build type to a GridType enum
847template<typename BuildT>
849{
850 if constexpr(util::is_same<BuildT, float>::value) { // resolved at compile-time
851 return GridType::Float;
852 } else if constexpr(util::is_same<BuildT, double>::value) {
853 return GridType::Double;
854 } else if constexpr(util::is_same<BuildT, int16_t>::value) {
855 return GridType::Int16;
856 } else if constexpr(util::is_same<BuildT, int32_t>::value) {
857 return GridType::Int32;
858 } else if constexpr(util::is_same<BuildT, int64_t>::value) {
859 return GridType::Int64;
860 } else if constexpr(util::is_same<BuildT, Vec3f>::value) {
861 return GridType::Vec3f;
862 } else if constexpr(util::is_same<BuildT, Vec3d>::value) {
863 return GridType::Vec3d;
864 } else if constexpr(util::is_same<BuildT, uint32_t>::value) {
865 return GridType::UInt32;
866 } else if constexpr(util::is_same<BuildT, ValueMask>::value) {
867 return GridType::Mask;
868 } else if constexpr(util::is_same<BuildT, Half>::value) {
869 return GridType::Half;
870 } else if constexpr(util::is_same<BuildT, ValueIndex>::value) {
871 return GridType::Index;
872 } else if constexpr(util::is_same<BuildT, ValueOnIndex>::value) {
873 return GridType::OnIndex;
874 } else if constexpr(util::is_same<BuildT, bool>::value) {
875 return GridType::Boolean;
876 } else if constexpr(util::is_same<BuildT, math::Rgba8>::value) {
877 return GridType::RGBA8;
878 } else if constexpr(util::is_same<BuildT, Fp4>::value) {
879 return GridType::Fp4;
880 } else if constexpr(util::is_same<BuildT, Fp8>::value) {
881 return GridType::Fp8;
882 } else if constexpr(util::is_same<BuildT, Fp16>::value) {
883 return GridType::Fp16;
884 } else if constexpr(util::is_same<BuildT, FpN>::value) {
885 return GridType::FpN;
886 } else if constexpr(util::is_same<BuildT, Vec4f>::value) {
887 return GridType::Vec4f;
888 } else if constexpr(util::is_same<BuildT, Vec4d>::value) {
889 return GridType::Vec4d;
890 } else if constexpr(util::is_same<BuildT, Point>::value) {
892 } else if constexpr(util::is_same<BuildT, Vec3u8>::value) {
893 return GridType::Vec3u8;
894 } else if constexpr(util::is_same<BuildT, Vec3u16>::value) {
895 return GridType::Vec3u16;
896 } else if constexpr(util::is_same<BuildT, uint8_t>::value) {
897 return GridType::UInt8;
898 }
899 return GridType::Unknown;
900}// toGridType
901
902template<typename BuildT>
903[[deprecated("Use toGridType<T>() instead.")]]
905
906// ----------------------------> mapping BuildType -> GridClass <--------------------------------------
907
908/// @brief Maps from a templated build type to a GridClass enum
909template<typename BuildT>
911{
913 return GridClass::Topology;
914 } else if constexpr(BuildTraits<BuildT>::is_index) {
916 } else if constexpr(util::is_same<BuildT, math::Rgba8>::value) {
918 } else if constexpr(util::is_same<BuildT, Point>::value) {
920 }
921 return defaultClass;
922}
923
924template<typename BuildT>
925[[deprecated("Use toGridClass<T>() instead.")]]
930
931// ----------------------------> BitFlags <--------------------------------------
932
933template<int N>
934struct BitArray;
935template<>
936struct BitArray<8>
937{
938 uint8_t mFlags{0};
939};
940template<>
941struct BitArray<16>
942{
943 uint16_t mFlags{0};
944};
945template<>
946struct BitArray<32>
947{
948 uint32_t mFlags{0};
949};
950template<>
951struct BitArray<64>
952{
953 uint64_t mFlags{0};
954};
955
956template<int N>
957class BitFlags : public BitArray<N>
958{
959protected:
960 using BitArray<N>::mFlags;
961
962public:
963 using Type = decltype(mFlags);
965 BitFlags(Type mask) : BitArray<N>{mask} {}
966 BitFlags(std::initializer_list<uint8_t> list)
967 {
968 for (auto bit : list) mFlags |= static_cast<Type>(1 << bit);
969 }
970 template<typename MaskT>
971 BitFlags(std::initializer_list<MaskT> list)
972 {
973 for (auto mask : list) mFlags |= static_cast<Type>(mask);
974 }
975 __hostdev__ Type data() const { return mFlags; }
976 __hostdev__ Type& data() { return mFlags; }
977 __hostdev__ void initBit(std::initializer_list<uint8_t> list)
978 {
979 mFlags = 0u;
980 for (auto bit : list) mFlags |= static_cast<Type>(1 << bit);
981 }
982 template<typename MaskT>
983 __hostdev__ void initMask(std::initializer_list<MaskT> list)
984 {
985 mFlags = 0u;
986 for (auto mask : list) mFlags |= static_cast<Type>(mask);
987 }
988 __hostdev__ Type getFlags() const { return mFlags & (static_cast<Type>(GridFlags::End) - 1u); } // mask out everything except relevant bits
989
990 __hostdev__ void setOn() { mFlags = ~Type(0u); }
991 __hostdev__ void setOff() { mFlags = Type(0u); }
992
993 __hostdev__ void setBitOn(uint8_t bit) { mFlags |= static_cast<Type>(1 << bit); }
994 __hostdev__ void setBitOff(uint8_t bit) { mFlags &= ~static_cast<Type>(1 << bit); }
995
996 __hostdev__ void setBitOn(std::initializer_list<uint8_t> list)
997 {
998 for (auto bit : list) mFlags |= static_cast<Type>(1 << bit);
999 }
1000 __hostdev__ void setBitOff(std::initializer_list<uint8_t> list)
1001 {
1002 for (auto bit : list) mFlags &= ~static_cast<Type>(1 << bit);
1003 }
1004
1005 template<typename MaskT>
1006 __hostdev__ void setMaskOn(MaskT mask) { mFlags |= static_cast<Type>(mask); }
1007 template<typename MaskT>
1008 __hostdev__ void setMaskOff(MaskT mask) { mFlags &= ~static_cast<Type>(mask); }
1009
1010 template<typename MaskT>
1011 __hostdev__ void setMaskOn(std::initializer_list<MaskT> list)
1012 {
1013 for (auto mask : list) mFlags |= static_cast<Type>(mask);
1014 }
1015 template<typename MaskT>
1016 __hostdev__ void setMaskOff(std::initializer_list<MaskT> list)
1017 {
1018 for (auto mask : list) mFlags &= ~static_cast<Type>(mask);
1019 }
1020
1021 __hostdev__ void setBit(uint8_t bit, bool on) { on ? this->setBitOn(bit) : this->setBitOff(bit); }
1022 template<typename MaskT>
1023 __hostdev__ void setMask(MaskT mask, bool on) { on ? this->setMaskOn(mask) : this->setMaskOff(mask); }
1024
1025 __hostdev__ bool isOn() const { return mFlags == ~Type(0u); }
1026 __hostdev__ bool isOff() const { return mFlags == Type(0u); }
1027 __hostdev__ bool isBitOn(uint8_t bit) const { return 0 != (mFlags & static_cast<Type>(1 << bit)); }
1028 __hostdev__ bool isBitOff(uint8_t bit) const { return 0 == (mFlags & static_cast<Type>(1 << bit)); }
1029 template<typename MaskT>
1030 __hostdev__ bool isMaskOn(MaskT mask) const { return 0 != (mFlags & static_cast<Type>(mask)); }
1031 template<typename MaskT>
1032 __hostdev__ bool isMaskOff(MaskT mask) const { return 0 == (mFlags & static_cast<Type>(mask)); }
1033 /// @brief return true if any of the masks in the list are on
1034 template<typename MaskT>
1035 __hostdev__ bool isMaskOn(std::initializer_list<MaskT> list) const
1036 {
1037 for (auto mask : list) {
1038 if (0 != (mFlags & static_cast<Type>(mask))) return true;
1039 }
1040 return false;
1041 }
1042 /// @brief return true if any of the masks in the list are off
1043 template<typename MaskT>
1044 __hostdev__ bool isMaskOff(std::initializer_list<MaskT> list) const
1045 {
1046 for (auto mask : list) {
1047 if (0 == (mFlags & static_cast<Type>(mask))) return true;
1048 }
1049 return false;
1050 }
1051 /// @brief required for backwards compatibility
1053 {
1054 mFlags = n;
1055 return *this;
1056 }
1057}; // BitFlags<N>
1058
1059// ----------------------------> Mask <--------------------------------------
1060
1061/// @brief Bit-mask to encode active states and facilitate sequential iterators
1062/// and a fast codec for I/O compression.
1063template<uint32_t LOG2DIM>
1064class Mask
1065{
1066public:
1067 static constexpr uint32_t SIZE = 1U << (3 * LOG2DIM); // Number of bits in mask
1068 static constexpr uint32_t WORD_COUNT = SIZE >> 6; // Number of 64 bit words
1069
1070 /// @brief Return the memory footprint in bytes of this Mask
1071 __hostdev__ static size_t memUsage() { return sizeof(Mask); }
1072
1073 /// @brief Return the number of bits available in this Mask
1074 __hostdev__ static uint32_t bitCount() { return SIZE; }
1075
1076 /// @brief Return the number of machine words used by this Mask
1077 __hostdev__ static uint32_t wordCount() { return WORD_COUNT; }
1078
1079 /// @brief Return the total number of set bits in this Mask
1080 __hostdev__ uint32_t countOn() const
1081 {
1082 uint32_t sum = 0;
1083 for (const uint64_t *w = mWords, *q = w + WORD_COUNT; w != q; ++w)
1084 sum += util::countOn(*w);
1085 return sum;
1086 }
1087
1088 /// @brief Return the number of lower set bits in mask up to but excluding the i'th bit
1089 inline __hostdev__ uint32_t countOn(uint32_t i) const
1090 {
1091 uint32_t n = i >> 6, sum = util::countOn(mWords[n] & ((uint64_t(1) << (i & 63u)) - 1u));
1092 for (const uint64_t* w = mWords; n--; ++w)
1093 sum += util::countOn(*w);
1094 return sum;
1095 }
1096
1097 template<bool On>
1099 {
1100 public:
1102 : mPos(Mask::SIZE)
1103 , mParent(nullptr)
1104 {
1105 }
1106 __hostdev__ Iterator(uint32_t pos, const Mask* parent)
1107 : mPos(pos)
1108 , mParent(parent)
1109 {
1110 }
1111 Iterator& operator=(const Iterator&) = default;
1112 __hostdev__ uint32_t operator*() const { return mPos; }
1113 __hostdev__ uint32_t pos() const { return mPos; }
1114 __hostdev__ operator bool() const { return mPos != Mask::SIZE; }
1116 {
1117 mPos = mParent->findNext<On>(mPos + 1);
1118 return *this;
1119 }
1121 {
1122 auto tmp = *this;
1123 ++(*this);
1124 return tmp;
1125 }
1126
1127 private:
1128 uint32_t mPos;
1129 const Mask* mParent;
1130 }; // Member class Iterator
1131
1133 {
1134 public:
1136 : mPos(pos)
1137 {
1138 }
1140 __hostdev__ uint32_t operator*() const { return mPos; }
1141 __hostdev__ uint32_t pos() const { return mPos; }
1142 __hostdev__ operator bool() const { return mPos != Mask::SIZE; }
1144 {
1145 ++mPos;
1146 return *this;
1147 }
1149 {
1150 auto tmp = *this;
1151 ++mPos;
1152 return tmp;
1153 }
1154
1155 private:
1156 uint32_t mPos;
1157 }; // Member class DenseIterator
1158
1161
1162 __hostdev__ OnIterator beginOn() const { return OnIterator(this->findFirst<true>(), this); }
1163
1165
1167
1168 /// @brief Initialize all bits to zero.
1170 {
1171 for (uint32_t i = 0; i < WORD_COUNT; ++i)
1172 mWords[i] = 0;
1173 }
1175 {
1176 const uint64_t v = on ? ~uint64_t(0) : uint64_t(0);
1177 for (uint32_t i = 0; i < WORD_COUNT; ++i)
1178 mWords[i] = v;
1179 }
1180
1181 /// @brief Copy constructor
1182 Mask(const Mask&) = default;
1183
1184 /// @brief Return a pointer to the list of words of the bit mask
1185 __hostdev__ uint64_t* words() { return mWords; }
1186 __hostdev__ const uint64_t* words() const { return mWords; }
1187
1188 template<typename WordT>
1189 __hostdev__ WordT getWord(uint32_t n) const
1190 {
1192 NANOVDB_ASSERT(n*8*sizeof(WordT) < WORD_COUNT);
1193 return reinterpret_cast<WordT*>(mWords)[n];
1194 }
1195 template<typename WordT>
1196 __hostdev__ void setWord(WordT w, uint32_t n)
1197 {
1199 NANOVDB_ASSERT(n*8*sizeof(WordT) < WORD_COUNT);
1200 reinterpret_cast<WordT*>(mWords)[n] = w;
1201 }
1202
1203 /// @brief Assignment operator that works with openvdb::util::NodeMask
1204 template<typename MaskT = Mask>
1206 {
1207 static_assert(sizeof(Mask) == sizeof(MaskT), "Mismatching sizeof");
1208 static_assert(WORD_COUNT == MaskT::WORD_COUNT, "Mismatching word count");
1209 static_assert(LOG2DIM == MaskT::LOG2DIM, "Mismatching LOG2DIM");
1210 auto* src = reinterpret_cast<const uint64_t*>(&other);
1211 for (uint64_t *dst = mWords, *end = dst + WORD_COUNT; dst != end; ++dst)
1212 *dst = *src++;
1213 return *this;
1214 }
1215
1216 //__hostdev__ Mask& operator=(const Mask& other){return *util::memcpy(this, &other);}
1217 Mask& operator=(const Mask&) = default;
1218
1219 __hostdev__ bool operator==(const Mask& other) const
1220 {
1221 for (uint32_t i = 0; i < WORD_COUNT; ++i) {
1222 if (mWords[i] != other.mWords[i])
1223 return false;
1224 }
1225 return true;
1226 }
1227
1228 __hostdev__ bool operator!=(const Mask& other) const { return !((*this) == other); }
1229
1230 /// @brief Return true if the given bit is set.
1231 __hostdev__ bool isOn(uint32_t n) const { return 0 != (mWords[n >> 6] & (uint64_t(1) << (n & 63))); }
1232
1233 /// @brief Return true if the given bit is NOT set.
1234 __hostdev__ bool isOff(uint32_t n) const { return 0 == (mWords[n >> 6] & (uint64_t(1) << (n & 63))); }
1235
1236 /// @brief Return true if all the bits are set in this Mask.
1237 __hostdev__ bool isOn() const
1238 {
1239 for (uint32_t i = 0; i < WORD_COUNT; ++i)
1240 if (mWords[i] != ~uint64_t(0))
1241 return false;
1242 return true;
1243 }
1244
1245 /// @brief Return true if none of the bits are set in this Mask.
1246 __hostdev__ bool isOff() const
1247 {
1248 for (uint32_t i = 0; i < WORD_COUNT; ++i)
1249 if (mWords[i] != uint64_t(0))
1250 return false;
1251 return true;
1252 }
1253
1254 /// @brief Set the specified bit on.
1255 __hostdev__ void setOn(uint32_t n) { mWords[n >> 6] |= uint64_t(1) << (n & 63); }
1256 /// @brief Set the specified bit off.
1257 __hostdev__ void setOff(uint32_t n) { mWords[n >> 6] &= ~(uint64_t(1) << (n & 63)); }
1258
1259 __hostdev__ inline void setOnAtomic(uint32_t n)
1260 {
1261 util::atomicOr(mWords + (n >> 6), uint64_t(1) << (n & 63));
1262 }
1263 __hostdev__ inline void setOffAtomic(uint32_t n)
1264 {
1265 util::atomicAnd(mWords + (n >> 6), ~(uint64_t(1) << (n & 63)));
1266 }
1267 __hostdev__ inline void setAtomic(uint32_t n, bool on)
1268 {
1269 on ? this->setOnAtomic(n) : this->setOffAtomic(n);
1270 }
1271#if defined(__CUDACC__)
1272// TODO: setWordAtomic is currently disabled. Before re-enabling, audit for
1273// possible migration to __hostdev__ using util::atomicOr/util::atomicAnd.
1274/*
1275 template<typename WordT>
1276 __device__ inline void setWordAtomic(WordT w, uint32_t n)
1277 {
1278 static_assert(util::is_same<WordT, uint8_t, uint16_t, uint32_t, uint64_t>::value);
1279 NANOVDB_ASSERT(n*8*sizeof(WordT) < WORD_COUNT);
1280 if constexpr(util::is_same<WordT,uint8_t>::value) {
1281 mask <<= x;
1282 } else if constexpr(util::is_same<WordT,uint16_t>::value) {
1283 unsigned int mask = w;
1284 if (n >> 1) mask <<= 16;
1285 atomicOr(reinterpret_cast<unsigned int*>(this) + n, mask);
1286 } else if constexpr(util::is_same<WordT,uint32_t>::value) {
1287 atomicOr(reinterpret_cast<unsigned int*>(this) + n, w);
1288 } else {
1289 atomicOr(reinterpret_cast<unsigned long long int*>(this) + n, w);
1290 }
1291 }
1292*/
1293#endif
1294 /// @brief Set the specified bit on or off.
1295 __hostdev__ void set(uint32_t n, bool on)
1296 {
1297#if 1 // switch between branchless
1298 auto& word = mWords[n >> 6];
1299 n &= 63;
1300 word &= ~(uint64_t(1) << n);
1301 word |= uint64_t(on) << n;
1302#else
1303 on ? this->setOn(n) : this->setOff(n);
1304#endif
1305 }
1306
1307 /// @brief Set all bits on
1309 {
1310 for (uint32_t i = 0; i < WORD_COUNT; ++i)mWords[i] = ~uint64_t(0);
1311 }
1312
1313 /// @brief Set all bits off
1315 {
1316 for (uint32_t i = 0; i < WORD_COUNT; ++i) mWords[i] = uint64_t(0);
1317 }
1318
1319 /// @brief Set all bits off
1320 __hostdev__ void set(bool on)
1321 {
1322 const uint64_t v = on ? ~uint64_t(0) : uint64_t(0);
1323 for (uint32_t i = 0; i < WORD_COUNT; ++i) mWords[i] = v;
1324 }
1325 /// brief Toggle the state of all bits in the mask
1327 {
1328 uint32_t n = WORD_COUNT;
1329 for (auto* w = mWords; n--; ++w) *w = ~*w;
1330 }
1331 __hostdev__ void toggle(uint32_t n) { mWords[n >> 6] ^= uint64_t(1) << (n & 63); }
1332
1333 /// @brief Bitwise intersection
1335 {
1336 uint64_t* w1 = mWords;
1337 const uint64_t* w2 = other.mWords;
1338 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 &= *w2;
1339 return *this;
1340 }
1341 /// @brief Bitwise union
1343 {
1344 uint64_t* w1 = mWords;
1345 const uint64_t* w2 = other.mWords;
1346 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 |= *w2;
1347 return *this;
1348 }
1349 /// @brief Bitwise difference
1351 {
1352 uint64_t* w1 = mWords;
1353 const uint64_t* w2 = other.mWords;
1354 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 &= ~*w2;
1355 return *this;
1356 }
1357 /// @brief Bitwise XOR
1359 {
1360 uint64_t* w1 = mWords;
1361 const uint64_t* w2 = other.mWords;
1362 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 ^= *w2;
1363 return *this;
1364 }
1365
1367 template<bool ON>
1368 __hostdev__ uint32_t findFirst() const
1369 {
1370 uint32_t n = 0u;
1371 const uint64_t* w = mWords;
1372 for (; n < WORD_COUNT && !(ON ? *w : ~*w); ++w, ++n);
1373 return n < WORD_COUNT ? (n << 6) + util::findLowestOn(ON ? *w : ~*w) : SIZE;
1374 }
1375
1377 template<bool ON>
1378 __hostdev__ uint32_t findNext(uint32_t start) const
1379 {
1380 uint32_t n = start >> 6; // initiate
1381 if (n >= WORD_COUNT) return SIZE; // check for out of bounds
1382 uint32_t m = start & 63u;
1383 uint64_t b = ON ? mWords[n] : ~mWords[n];
1384 if (b & (uint64_t(1u) << m)) return start; // simple case: start is on/off
1385 b &= ~uint64_t(0u) << m; // mask out lower bits
1386 while (!b && ++n < WORD_COUNT) b = ON ? mWords[n] : ~mWords[n]; // find next non-zero word
1387 return b ? (n << 6) + util::findLowestOn(b) : SIZE; // catch last word=0
1388 }
1389
1391 template<bool ON>
1392 __hostdev__ uint32_t findPrev(uint32_t start) const
1393 {
1394 uint32_t n = start >> 6; // initiate
1395 if (n >= WORD_COUNT) return SIZE; // check for out of bounds
1396 uint32_t m = start & 63u;
1397 uint64_t b = ON ? mWords[n] : ~mWords[n];
1398 if (b & (uint64_t(1u) << m)) return start; // simple case: start is on/off
1399 b &= (uint64_t(1u) << m) - 1u; // mask out higher bits
1400 while (!b && n) b = ON ? mWords[--n] : ~mWords[--n]; // find previous non-zero word
1401 return b ? (n << 6) + util::findHighestOn(b) : SIZE; // catch first word=0
1402 }
1403
1404private:
1405 uint64_t mWords[WORD_COUNT];
1406}; // Mask class
1407
1408// ----------------------------> Map <--------------------------------------
1409
1410/// @brief Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation
1411struct Map
1412{ // 264B (not 32B aligned!)
1413 float mMatF[9]; // 9*4B <- 3x3 matrix
1414 float mInvMatF[9]; // 9*4B <- 3x3 matrix
1415 float mVecF[3]; // 3*4B <- translation
1416 float mTaperF; // 4B, placeholder for taper value
1417 double mMatD[9]; // 9*8B <- 3x3 matrix
1418 double mInvMatD[9]; // 9*8B <- 3x3 matrix
1419 double mVecD[3]; // 3*8B <- translation
1420 double mTaperD; // 8B, placeholder for taper value
1421
1422 /// @brief Default constructor for the identity map
1423 __hostdev__ constexpr Map()
1424 : mMatF{ 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}
1425 , mInvMatF{1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}
1426 , mVecF{0.0f, 0.0f, 0.0f}
1427 , mTaperF{1.0f}
1428 , mMatD{ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}
1429 , mInvMatD{1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}
1430 , mVecD{0.0, 0.0, 0.0}
1431 , mTaperD{1.0}
1432 {
1433 }
1434 __hostdev__ constexpr Map(double s, const Vec3d& t = Vec3d(0.0, 0.0, 0.0))
1435 : mMatF{float(s), 0.0f, 0.0f, 0.0f, float(s), 0.0f, 0.0f, 0.0f, float(s)}
1436 , mInvMatF{1.0f / float(s), 0.0f, 0.0f, 0.0f, 1.0f / float(s), 0.0f, 0.0f, 0.0f, 1.0f / float(s)}
1437 , mVecF{float(t[0]), float(t[1]), float(t[2])}
1438 , mTaperF{1.0f}
1439 , mMatD{s, 0.0, 0.0, 0.0, s, 0.0, 0.0, 0.0, s}
1440 , mInvMatD{1.0 / s, 0.0, 0.0, 0.0, 1.0 / s, 0.0, 0.0, 0.0, 1.0 / s}
1441 , mVecD{t[0], t[1], t[2]}
1442 , mTaperD{1.0}
1443 {
1444 }
1445
1446 /// @brief Initialize the member data from 3x3 or 4x4 matrices
1447 /// @note This is not _hostdev__ since then MatT=openvdb::Mat4d will produce warnings
1448 template<typename MatT, typename Vec3T>
1449 void set(const MatT& mat, const MatT& invMat, const Vec3T& translate, double taper = 1.0);
1450
1451 /// @brief Initialize the member data from 4x4 matrices
1452 /// @note The last (4th) row of invMat is actually ignored.
1453 /// This is not _hostdev__ since then Mat4T=openvdb::Mat4d will produce warnings
1454 template<typename Mat4T>
1455 void set(const Mat4T& mat, const Mat4T& invMat, double taper = 1.0) { this->set(mat, invMat, mat[3], taper); }
1456
1457 template<typename Vec3T>
1458 void set(double scale, const Vec3T& translation, double taper = 1.0);
1459
1460 /// @brief Apply the forward affine transformation to a vector using 64bit floating point arithmetics.
1461 /// @note Typically this operation is used for the scale, rotation and translation of index -> world mapping
1462 /// @tparam Vec3T Template type of the 3D vector to be mapped
1463 /// @param ijk 3D vector to be mapped - typically floating point index coordinates
1464 /// @return Forward mapping for affine transformation, i.e. (mat x ijk) + translation
1465 template<typename Vec3T>
1466 __hostdev__ constexpr Vec3T applyMap(const Vec3T& ijk) const { return math::matMult(mMatD, mVecD, ijk); }
1467
1468 /// @brief Apply the forward affine transformation to a vector using 32bit floating point arithmetics.
1469 /// @note Typically this operation is used for the scale, rotation and translation of index -> world mapping
1470 /// @tparam Vec3T Template type of the 3D vector to be mapped
1471 /// @param ijk 3D vector to be mapped - typically floating point index coordinates
1472 /// @return Forward mapping for affine transformation, i.e. (mat x ijk) + translation
1473 template<typename Vec3T>
1474 __hostdev__ constexpr Vec3T applyMapF(const Vec3T& ijk) const { return math::matMult(mMatF, mVecF, ijk); }
1475
1476 /// @brief Apply the linear forward 3x3 transformation to an input 3d vector using 64bit floating point arithmetics,
1477 /// e.g. scale and rotation WITHOUT translation.
1478 /// @note Typically this operation is used for scale and rotation from index -> world mapping
1479 /// @tparam Vec3T Template type of the 3D vector to be mapped
1480 /// @param ijk 3D vector to be mapped - typically floating point index coordinates
1481 /// @return linear forward 3x3 mapping of the input vector
1482 template<typename Vec3T>
1483 __hostdev__ constexpr Vec3T applyJacobian(const Vec3T& ijk) const { return math::matMult(mMatD, ijk); }
1484
1485 /// @brief Apply the linear forward 3x3 transformation to an input 3d vector using 32bit floating point arithmetics,
1486 /// e.g. scale and rotation WITHOUT translation.
1487 /// @note Typically this operation is used for scale and rotation from index -> world mapping
1488 /// @tparam Vec3T Template type of the 3D vector to be mapped
1489 /// @param ijk 3D vector to be mapped - typically floating point index coordinates
1490 /// @return linear forward 3x3 mapping of the input vector
1491 template<typename Vec3T>
1492 __hostdev__ constexpr Vec3T applyJacobianF(const Vec3T& ijk) const { return math::matMult(mMatF, ijk); }
1493
1494 /// @brief Apply the inverse affine mapping to a vector using 64bit floating point arithmetics.
1495 /// @note Typically this operation is used for the world -> index mapping
1496 /// @tparam Vec3T Template type of the 3D vector to be mapped
1497 /// @param xyz 3D vector to be mapped - typically floating point world coordinates
1498 /// @return Inverse affine mapping of the input @c xyz i.e. (xyz - translation) x mat^-1
1499 template<typename Vec3T>
1500 __hostdev__ constexpr Vec3T applyInverseMap(const Vec3T& xyz) const
1501 {
1502 return math::matMult(mInvMatD, Vec3T(xyz[0] - mVecD[0], xyz[1] - mVecD[1], xyz[2] - mVecD[2]));
1503 }
1504
1505 /// @brief Apply the inverse affine mapping to a vector using 32bit floating point arithmetics.
1506 /// @note Typically this operation is used for the world -> index mapping
1507 /// @tparam Vec3T Template type of the 3D vector to be mapped
1508 /// @param xyz 3D vector to be mapped - typically floating point world coordinates
1509 /// @return Inverse affine mapping of the input @c xyz i.e. (xyz - translation) x mat^-1
1510 template<typename Vec3T>
1511 __hostdev__ constexpr Vec3T applyInverseMapF(const Vec3T& xyz) const
1512 {
1513 return math::matMult(mInvMatF, Vec3T(xyz[0] - mVecF[0], xyz[1] - mVecF[1], xyz[2] - mVecF[2]));
1514 }
1515
1516 /// @brief Apply the linear inverse 3x3 transformation to an input 3d vector using 64bit floating point arithmetics,
1517 /// e.g. inverse scale and inverse rotation WITHOUT translation.
1518 /// @note Typically this operation is used for scale and rotation from world -> index mapping
1519 /// @tparam Vec3T Template type of the 3D vector to be mapped
1520 /// @param xyz 3D vector to be mapped - typically floating point index coordinates
1521 /// @return linear inverse 3x3 mapping of the input vector i.e. xyz x mat^-1
1522 template<typename Vec3T>
1523 __hostdev__ constexpr Vec3T applyInverseJacobian(const Vec3T& xyz) const { return math::matMult(mInvMatD, xyz); }
1524
1525 /// @brief Apply the linear inverse 3x3 transformation to an input 3d vector using 32bit floating point arithmetics,
1526 /// e.g. inverse scale and inverse rotation WITHOUT translation.
1527 /// @note Typically this operation is used for scale and rotation from world -> index mapping
1528 /// @tparam Vec3T Template type of the 3D vector to be mapped
1529 /// @param xyz 3D vector to be mapped - typically floating point index coordinates
1530 /// @return linear inverse 3x3 mapping of the input vector i.e. xyz x mat^-1
1531 template<typename Vec3T>
1532 __hostdev__ constexpr Vec3T applyInverseJacobianF(const Vec3T& xyz) const { return math::matMult(mInvMatF, xyz); }
1533
1534 /// @brief Apply the transposed inverse 3x3 transformation to an input 3d vector using 64bit floating point arithmetics,
1535 /// e.g. inverse scale and inverse rotation WITHOUT translation.
1536 /// @note Typically this operation is used for scale and rotation from world -> index mapping
1537 /// @tparam Vec3T Template type of the 3D vector to be mapped
1538 /// @param xyz 3D vector to be mapped - typically floating point index coordinates
1539 /// @return linear inverse 3x3 mapping of the input vector i.e. xyz x mat^-1
1540 template<typename Vec3T>
1541 __hostdev__ constexpr Vec3T applyIJT(const Vec3T& xyz) const { return math::matMultT(mInvMatD, xyz); }
1542 template<typename Vec3T>
1543 __hostdev__ constexpr Vec3T applyIJTF(const Vec3T& xyz) const { return math::matMultT(mInvMatF, xyz); }
1544
1545 /// @brief Return a voxels size in each coordinate direction, measured at the origin
1546 __hostdev__ constexpr Vec3d getVoxelSize() const { return this->applyMap(Vec3d(1)) - this->applyMap(Vec3d(0)); }
1547}; // Map
1548
1549template<typename MatT, typename Vec3T>
1550inline void Map::set(const MatT& mat, const MatT& invMat, const Vec3T& translate, double taper)
1551{
1552 float * mf = mMatF, *vf = mVecF, *mif = mInvMatF;
1553 double *md = mMatD, *vd = mVecD, *mid = mInvMatD;
1554 mTaperF = static_cast<float>(taper);
1555 mTaperD = taper;
1556 for (int i = 0; i < 3; ++i) {
1557 *vd++ = translate[i]; //translation
1558 *vf++ = static_cast<float>(translate[i]); //translation
1559 for (int j = 0; j < 3; ++j) {
1560 *md++ = mat[j][i]; //transposed
1561 *mid++ = invMat[j][i];
1562 *mf++ = static_cast<float>(mat[j][i]); //transposed
1563 *mif++ = static_cast<float>(invMat[j][i]);
1564 }
1565 }
1566}
1567
1568template<typename Vec3T>
1569inline void Map::set(double dx, const Vec3T& trans, double taper)
1570{
1571 NANOVDB_ASSERT(dx > 0.0);
1572 const double mat[3][3] = { {dx, 0.0, 0.0}, // row 0
1573 {0.0, dx, 0.0}, // row 1
1574 {0.0, 0.0, dx} }; // row 2
1575 const double idx = 1.0 / dx;
1576 const double invMat[3][3] = { {idx, 0.0, 0.0}, // row 0
1577 {0.0, idx, 0.0}, // row 1
1578 {0.0, 0.0, idx} }; // row 2
1579 this->set(mat, invMat, trans, taper);
1580}
1581
1582// ----------------------------> GridBlindMetaData <--------------------------------------
1583
1584struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) GridBlindMetaData
1585{ // 288 bytes
1586 static const int MaxNameSize = 256; // due to NULL termination the maximum length is one less!
1587 int64_t mDataOffset; // byte offset to the blind data, relative to GridBlindMetaData::this.
1588 uint64_t mValueCount; // number of blind values, e.g. point count
1589 uint32_t mValueSize;// byte size of each value, e.g. 4 if mDataType=Float and 1 if mDataType=Unknown since that amounts to char
1590 GridBlindDataSemantic mSemantic; // semantic meaning of the data.
1593 char mName[MaxNameSize]; // note this includes the NULL termination
1594 // no padding required for 32 byte alignment
1595
1596 /// @brief Empty constructor
1607
1608 GridBlindMetaData(int64_t dataOffset, uint64_t valueCount, uint32_t valueSize, GridBlindDataSemantic semantic, GridBlindDataClass dataClass, GridType dataType)
1609 : mDataOffset(dataOffset)
1610 , mValueCount(valueCount)
1611 , mValueSize(valueSize)
1612 , mSemantic(semantic)
1613 , mDataClass(dataClass)
1614 , mDataType(dataType)
1615 {
1617 }
1618
1619 /// @brief Copy constructor that resets mDataOffset and zeros out mName
1621 : mDataOffset(util::PtrDiff(util::PtrAdd(&other, other.mDataOffset), this))
1622 , mValueCount(other.mValueCount)
1623 , mValueSize(other.mValueSize)
1624 , mSemantic(other.mSemantic)
1625 , mDataClass(other.mDataClass)
1626 , mDataType(other.mDataType)
1627 {
1629 }
1630
1631 /// @brief Copy assignment operator that resets mDataOffset and copies mName
1632 /// @param rhs right-hand instance to copy
1633 /// @return reference to itself
1635 {
1638 mValueSize = rhs. mValueSize;
1639 mSemantic = rhs.mSemantic;
1640 mDataClass = rhs.mDataClass;
1641 mDataType = rhs.mDataType;
1643 return *this;
1644 }
1645
1647 {
1649 }
1650
1651 /// @brief Sets the name string
1652 /// @param name c-string source name
1653 /// @return returns false if @c name has too many characters
1654 __hostdev__ bool setName(const char* name){return util::strncpy(mName, name, MaxNameSize)[MaxNameSize-1] == '\0';}
1655
1656 /// @brief returns a const void point to the blind data
1657 /// @note assumes that setBlinddData was called
1658 __hostdev__ const void* blindData() const
1659 {
1661 return util::PtrAdd(this, mDataOffset);
1662 }
1663
1664 /// @brief Get a const pointer to the blind data represented by this meta data
1665 /// @tparam BlindDataT Expected value type of the blind data.
1666 /// @return Returns NULL if mGridType!=toGridType<BlindDataT>(), else a const point of type BlindDataT.
1667 /// @note Use mDataType=Unknown if BlindDataT is a custom data type unknown to NanoVDB.
1668 template<typename BlindDataT>
1669 __hostdev__ const BlindDataT* getBlindData() const
1670 {
1672 }
1673
1674 /// @brief return true if this meta data has a valid combination of semantic, class and value tags.
1675 /// @note this does not check if the mDataOffset has been set! It is intended to catch invalid combinations
1676 /// of semantic, class and value tags.
1678 {
1679 auto check = [&]()->bool{
1680 switch (mDataType){
1681 //case GridType::Unknown: return mValueSize==1u;// i.e. we encode data as mValueCount chars
1682 case GridType::Float: return mValueSize==4u;
1683 case GridType::Double: return mValueSize==8u;
1684 case GridType::Int16: return mValueSize==2u;
1685 case GridType::Int32: return mValueSize==4u;
1686 case GridType::Int64: return mValueSize==8u;
1687 case GridType::Vec3f: return mValueSize==12u;
1688 case GridType::Vec3d: return mValueSize==24u;
1689 case GridType::Half: return mValueSize==2u;
1690 case GridType::RGBA8: return mValueSize==4u;
1691 case GridType::Fp8: return mValueSize==1u;
1692 case GridType::Fp16: return mValueSize==2u;
1693 case GridType::Vec4f: return mValueSize==16u;
1694 case GridType::Vec4d: return mValueSize==32u;
1695 case GridType::Vec3u8: return mValueSize==3u;
1696 case GridType::Vec3u16: return mValueSize==6u;
1697 default: return true;}// all other combinations are valid
1698 };
1699 //if (!check()) {
1700 // char str[20];
1701 // printf("Inconsistent blind data properties: size=%u, GridType=\"%s\"\n",(uint32_t)mValueSize, toStr(str, mDataType) );
1702 //}
1703 return nanovdb::isValid(mDataClass, mSemantic, mDataType) && check();
1704 }
1705
1706 /// @brief return size in bytes of the blind data represented by this blind meta data
1707 /// @note This size includes possible padding for 32 byte alignment. The actual amount
1708 /// of bind data is mValueCount * mValueSize
1713}; // GridBlindMetaData
1714
1715// ----------------------------> NodeTrait <--------------------------------------
1716
1717/// @brief Struct to derive node type from its level in a given
1718/// grid, tree or root while preserving constness
1719template<typename GridOrTreeOrRootT, int LEVEL>
1721
1722// Partial template specialization of above Node struct
1723template<typename GridOrTreeOrRootT>
1724struct NodeTrait<GridOrTreeOrRootT, 0>
1725{
1726 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1727 using Type = typename GridOrTreeOrRootT::LeafNodeType;
1728 using type = typename GridOrTreeOrRootT::LeafNodeType;
1729};
1730template<typename GridOrTreeOrRootT>
1731struct NodeTrait<const GridOrTreeOrRootT, 0>
1732{
1733 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1734 using Type = const typename GridOrTreeOrRootT::LeafNodeType;
1735 using type = const typename GridOrTreeOrRootT::LeafNodeType;
1736};
1737
1738template<typename GridOrTreeOrRootT>
1739struct NodeTrait<GridOrTreeOrRootT, 1>
1740{
1741 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1742 using Type = typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType;
1743 using type = typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType;
1744};
1745template<typename GridOrTreeOrRootT>
1746struct NodeTrait<const GridOrTreeOrRootT, 1>
1747{
1748 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1749 using Type = const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType;
1750 using type = const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType;
1751};
1752template<typename GridOrTreeOrRootT>
1753struct NodeTrait<GridOrTreeOrRootT, 2>
1754{
1755 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1756 using Type = typename GridOrTreeOrRootT::RootNodeType::ChildNodeType;
1757 using type = typename GridOrTreeOrRootT::RootNodeType::ChildNodeType;
1758};
1759template<typename GridOrTreeOrRootT>
1760struct NodeTrait<const GridOrTreeOrRootT, 2>
1761{
1762 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1763 using Type = const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType;
1764 using type = const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType;
1765};
1766template<typename GridOrTreeOrRootT>
1767struct NodeTrait<GridOrTreeOrRootT, 3>
1768{
1769 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1770 using Type = typename GridOrTreeOrRootT::RootNodeType;
1771 using type = typename GridOrTreeOrRootT::RootNodeType;
1772};
1773
1774template<typename GridOrTreeOrRootT>
1775struct NodeTrait<const GridOrTreeOrRootT, 3>
1776{
1777 static_assert(GridOrTreeOrRootT::RootNodeType::LEVEL == 3, "Tree depth is not supported");
1778 using Type = const typename GridOrTreeOrRootT::RootNodeType;
1779 using type = const typename GridOrTreeOrRootT::RootNodeType;
1780};
1781
1782template<typename GridOrTreeOrRootT, int LEVEL>
1784
1785// ------------> Froward decelerations of accelerated random access methods <---------------
1786
1787template<typename BuildT>
1788struct GetValue;
1789template<typename BuildT>
1790struct SetValue;
1791template<typename BuildT>
1792struct SetVoxel;
1793template<typename BuildT>
1794struct GetState;
1795template<typename BuildT>
1796struct GetDim;
1797template<typename BuildT>
1798struct GetLeaf;
1799template<typename BuildT>
1800struct ProbeValue;
1801template<typename BuildT>
1802struct GetNodeInfo;
1803
1804/// @brief Result of a fused ReadAccessor::getDimAndActive traversal: the
1805/// getDim(ijk, ray) step size and the policy-dependent active state of @a ijk.
1806///
1807/// The low 31 bits store @c dim and bit 31 stores @c active, saving one live
1808/// return register versus {uint32_t, bool}. The default FloatTree's upper-node
1809/// maximum is 4096. The constructor supports `return {dim, active}`; dim() and
1810/// active() decode the packed value.
1812{
1813 uint32_t packed{0u};
1814
1816 __hostdev__ DimAndActive(uint32_t d, bool a)
1817 : packed((d & 0x7FFFFFFFu) | (uint32_t(a) << 31))
1818 {
1819 NANOVDB_ASSERT(d < (uint32_t(1) << 31)); // dim must fit in 31 bits (bit 31 = active)
1820 }
1821
1822 __hostdev__ uint32_t dim() const { return packed & 0x7FFFFFFFu; }
1823 __hostdev__ bool active() const { return (packed >> 31) != 0u; }
1824};
1825
1826/// @brief Policy that exactly matches separate getDim and isActive calls. A
1827/// skip flag still controls @c dim but cannot stop the active-state descent:
1828/// GridStats flags value range versus render delta, not activeness. This costs
1829/// a full descent through skipped InternalNodes; use it when @c active is read
1830/// unconditionally, such as by HDDA iterators observing upper-level activeness.
1831struct ActiveExact {};
1832
1833/// @brief Policy that preserves getDim's skip-flag fast path. If an
1834/// InternalNode short-circuits, @c active is unspecified and must be gated on
1835/// @c dim. Otherwise the leaf-level active read is fused into the descent. Use
1836/// for logic such as `if (hdda.dim() > 1 || !active) continue;`, where the
1837/// short-circuit ensures @c active is read only after a leaf-level descent.
1839
1840// ----------------------------> CheckMode <----------------------------------
1841
1842/// @brief List of different modes for computing for a checksum
1843enum class CheckMode : uint32_t { Disable = 0, // no computation
1845 Half = 1,
1846 Partial = 1, // fast but approximate
1847 Default = 1, // defaults to Partial
1848 Full = 2, // slow but accurate
1849 End = 3, // marks the end of the enum list
1850 StrLen = 9 + End};
1851
1852/// @brief Prints CheckMode enum to a c-string
1853/// @param dst Destination c-string
1854/// @param mode CheckMode enum to be converted to string
1855/// @return destinations string @c dst
1856__hostdev__ inline char* toStr(char *dst, CheckMode mode)
1857{
1858 switch (mode){
1859 case CheckMode::Half: return util::strcpy(dst, "half");
1860 case CheckMode::Full: return util::strcpy(dst, "full");
1861 default: return util::strcpy(dst, "disabled");// StrLen = 8 + 1 + End
1862 }
1863}
1864
1865// ----------------------------> Checksum <----------------------------------
1866
1867/// @brief Class that encapsulates two CRC32 checksums, one for the Grid, Tree and Root node meta data
1868/// and one for the remaining grid nodes.
1870{
1871 /// Three types of checksums:
1872 /// 1) Empty: all 64 bits are on (used to signify a disabled or undefined checksum)
1873 /// 2) Half: Upper 32 bits are on and not all of lower 32 bits are on (lower 32 bits checksum head of grid)
1874 /// 3) Full: Not all of the 64 bits are one (lower 32 bits checksum head of grid and upper 32 bits checksum tail of grid)
1875 union { uint32_t mCRC32[2]; uint64_t mCRC64; };// mCRC32[0] is checksum of Grid, Tree and Root, and mCRC32[1] is checksum of nodes
1876
1877public:
1878
1879 static constexpr uint32_t EMPTY32 = ~uint32_t{0};
1880 static constexpr uint64_t EMPTY64 = ~uint64_t(0);
1881
1882 /// @brief default constructor initiates checksum to EMPTY
1884
1885 /// @brief Constructor that allows the two 32bit checksums to be initiated explicitly
1886 /// @param head Initial 32bit CRC checksum of grid, tree and root data
1887 /// @param tail Initial 32bit CRC checksum of all the nodes and blind data
1888 __hostdev__ Checksum(uint32_t head, uint32_t tail) : mCRC32{head, tail} {}
1889
1890 /// @brief
1891 /// @param checksum
1892 /// @param mode
1897
1898 /// @brief return the 64 bit checksum of this instance
1899 [[deprecated("Use Checksum::data instead.")]]
1900 __hostdev__ uint64_t checksum() const { return mCRC64; }
1901 [[deprecated("Use Checksum::head and Ckecksum::tail instead.")]]
1902 __hostdev__ uint32_t& checksum(int i) {NANOVDB_ASSERT(i==0 || i==1); return mCRC32[i]; }
1903 [[deprecated("Use Checksum::head and Ckecksum::tail instead.")]]
1904 __hostdev__ uint32_t checksum(int i) const {NANOVDB_ASSERT(i==0 || i==1); return mCRC32[i]; }
1905
1906 __hostdev__ uint64_t full() const { return mCRC64; }
1907 __hostdev__ uint64_t& full() { return mCRC64; }
1908 __hostdev__ uint32_t head() const { return mCRC32[0]; }
1909 __hostdev__ uint32_t& head() { return mCRC32[0]; }
1910 __hostdev__ uint32_t tail() const { return mCRC32[1]; }
1911 __hostdev__ uint32_t& tail() { return mCRC32[1]; }
1912
1913 /// @brief return true if the 64 bit checksum is partial, i.e. of head only
1914 [[deprecated("Use Checksum::isHalf instead.")]]
1915 __hostdev__ bool isPartial() const { return mCRC32[0] != EMPTY32 && mCRC32[1] == EMPTY32; }
1916 __hostdev__ bool isHalf() const { return mCRC32[0] != EMPTY32 && mCRC32[1] == EMPTY32; }
1917
1918 /// @brief return true if the 64 bit checksum is fill, i.e. of both had and nodes
1919 __hostdev__ bool isFull() const { return mCRC64 != EMPTY64 && mCRC32[1] != EMPTY32; }
1920
1921 /// @brief return true if the 64 bit checksum is disables (unset)
1922 __hostdev__ bool isEmpty() const { return mCRC64 == EMPTY64; }
1923
1925
1926 /// @brief return the mode of the 64 bit checksum
1932
1933 /// @brief return true if the checksums are identical
1934 /// @param rhs other Checksum
1935 __hostdev__ bool operator==(const Checksum &rhs) const {return mCRC64 == rhs.mCRC64;}
1936
1937 /// @brief return true if the checksums are not identical
1938 /// @param rhs other Checksum
1939 __hostdev__ bool operator!=(const Checksum &rhs) const {return mCRC64 != rhs.mCRC64;}
1940};// Checksum
1941
1942/// @brief Maps 64 bit checksum to CheckMode enum
1943/// @param checksum 64 bit checksum with two CRC32 codes
1944/// @return CheckMode enum
1945__hostdev__ inline CheckMode toCheckMode(const Checksum &checksum){return checksum.mode();}
1946
1947// ----------------------------> Grid <--------------------------------------
1948
1949/*
1950 The following class and comment is for internal use only
1951
1952 Memory layout:
1953
1954 Grid -> 39 x double (world bbox and affine transformation)
1955 Tree -> Root 3 x ValueType + int32_t + N x Tiles (background,min,max,tileCount + tileCount x Tiles)
1956
1957 N2 upper InternalNodes each with 2 bit masks, N2 tiles, and min/max values
1958
1959 N1 lower InternalNodes each with 2 bit masks, N1 tiles, and min/max values
1960
1961 N0 LeafNodes each with a bit mask, N0 ValueTypes and min/max
1962
1963 Example layout: ("---" implies it has a custom offset, "..." implies zero or more)
1964 [GridData][TreeData]---[RootData][ROOT TILES...]---[InternalData<5>]---[InternalData<4>]---[LeafData<3>]---[BLINDMETA...]---[BLIND0]---[BLIND1]---etc.
1965*/
1966
1967/// @brief Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
1968///
1969/// @note The transform is assumed to be affine (so linear) and have uniform scale! So frustum transforms
1970/// and non-uniform scaling are not supported (primarily because they complicate ray-tracing in index space)
1971///
1972/// @note No client code should (or can) interface with this struct so it can safely be ignored!
1973struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) GridData
1974{ // sizeof(GridData) = 672B
1975 static const int MaxNameSize = 256; // due to NULL termination the maximum length is one less
1976 uint64_t mMagic; // 8B (0) magic to validate it is valid grid data.
1977 Checksum mChecksum; // 8B (8). Checksum of grid buffer.
1978 Version mVersion; // 4B (16) major, minor, and patch version numbers
1979 BitFlags<32> mFlags; // 4B (20). flags for grid.
1980 uint32_t mGridIndex; // 4B (24). Index of this grid in the buffer
1981 uint32_t mGridCount; // 4B (28). Total number of grids in the buffer
1982 uint64_t mGridSize; // 8B (32). byte count of this entire grid occupied in the buffer.
1983 char mGridName[MaxNameSize]; // 256B (40)
1984 Map mMap; // 264B (296). affine transformation between index and world space in both single and double precision
1985 Vec3dBBox mWorldBBox; // 48B (560). floating-point AABB of active values in WORLD SPACE (2 x 3 doubles)
1986 Vec3d mVoxelSize; // 24B (608). size of a voxel in world units
1987 GridClass mGridClass; // 4B (632).
1988 GridType mGridType; // 4B (636).
1989 int64_t mBlindMetadataOffset; // 8B (640). offset to beginning of GridBlindMetaData structures that follow this grid.
1990 uint32_t mBlindMetadataCount; // 4B (648). count of GridBlindMetaData structures that follow this grid.
1991 uint32_t mData0; // 4B (652) unused
1992 uint64_t mData1; // 8B (656) is use for the total number of values indexed by an IndexGrid
1993 uint64_t mData2; // 8B (664) padding to 32 B alignment
1994 /// @brief Use this method to initiate most member data
1995 GridData& operator=(const GridData&) = default;
1996 //__hostdev__ GridData& operator=(const GridData& other){return *util::memcpy(this, &other);}
1997 __hostdev__ void init(std::initializer_list<GridFlags> list = {GridFlags::IsBreadthFirst},
1998 uint64_t gridSize = 0u,
1999 const Map& map = Map(),
2000 GridType gridType = GridType::Unknown,
2001 GridClass gridClass = GridClass::Unknown)
2002 {
2003#ifdef NANOVDB_USE_NEW_MAGIC_NUMBERS
2004 mMagic = NANOVDB_MAGIC_GRID;
2005#else
2006 mMagic = NANOVDB_MAGIC_NUMB;
2007#endif
2008 mChecksum.disable();// all 64 bits ON means checksum is disabled
2009 mVersion = Version();
2010 mFlags.initMask(list);
2011 mGridIndex = 0u;
2012 mGridCount = 1u;
2013 mGridSize = gridSize;
2014 mGridName[0] = '\0';
2015 mMap = map;
2016 mWorldBBox = Vec3dBBox();// invalid bbox
2017 mVoxelSize = map.getVoxelSize();
2018 mGridClass = gridClass;
2019 mGridType = gridType;
2020 mBlindMetadataOffset = mGridSize; // i.e. no blind data
2021 mBlindMetadataCount = 0u; // i.e. no blind data
2022 mData0 = 0u; // zero padding
2023 mData1 = 0u; // only used for index and point grids
2024#ifdef NANOVDB_USE_NEW_MAGIC_NUMBERS
2025 mData2 = 0u;// unused
2026#else
2027 mData2 = NANOVDB_MAGIC_GRID; // since version 32.6.0 (will change in the future)
2028#endif
2029 }
2030 /// @brief return true if the magic number and the version are both valid
2031 __hostdev__ bool isValid() const {
2032 // Before v32.6.0: toMagic(mMagic) = MagicType::NanoVDB and mData2 was undefined
2033 // For v32.6.0: toMagic(mMagic) = MagicType::NanoVDB and toMagic(mData2) = MagicType::NanoGrid
2034 // After v32.7.X: toMagic(mMagic) = MagicType::NanoGrid and mData2 will again be undefined
2035 const MagicType magic = toMagic(mMagic);
2036 if (magic == MagicType::NanoGrid || toMagic(mData2) == MagicType::NanoGrid) return true;
2037 bool test = magic == MagicType::NanoVDB;// could be GridData or io::FileHeader
2038 if (test) test = mVersion.isCompatible();
2039 if (test) test = mGridCount > 0u && mGridIndex < mGridCount;
2040 if (test) test = mGridClass < GridClass::End && mGridType < GridType::End;
2041 return test;
2042 }
2043 // Set and unset various bit flags
2044 __hostdev__ void setMinMaxOn(bool on = true) { mFlags.setMask(GridFlags::HasMinMax, on); }
2045 __hostdev__ void setBBoxOn(bool on = true) { mFlags.setMask(GridFlags::HasBBox, on); }
2047 __hostdev__ void setAverageOn(bool on = true) { mFlags.setMask(GridFlags::HasAverage, on); }
2049 __hostdev__ bool setGridName(const char* src)
2050 {
2051 const bool success = (util::strncpy(mGridName, src, MaxNameSize)[MaxNameSize-1] == '\0');
2052 if (!success) mGridName[MaxNameSize-1] = '\0';
2053 return success; // returns true if input grid name is NOT longer than MaxNameSize characters
2054 }
2055 // Affine transformations based on double precision
2056 template<typename Vec3T>
2057 __hostdev__ Vec3T applyMap(const Vec3T& xyz) const { return mMap.applyMap(xyz); } // Pos: index -> world
2058 template<typename Vec3T>
2059 __hostdev__ Vec3T applyInverseMap(const Vec3T& xyz) const { return mMap.applyInverseMap(xyz); } // Pos: world -> index
2060 template<typename Vec3T>
2061 __hostdev__ Vec3T applyJacobian(const Vec3T& xyz) const { return mMap.applyJacobian(xyz); } // Dir: index -> world
2062 template<typename Vec3T>
2063 __hostdev__ Vec3T applyInverseJacobian(const Vec3T& xyz) const { return mMap.applyInverseJacobian(xyz); } // Dir: world -> index
2064 template<typename Vec3T>
2065 __hostdev__ Vec3T applyIJT(const Vec3T& xyz) const { return mMap.applyIJT(xyz); }
2066 // Affine transformations based on single precision
2067 template<typename Vec3T>
2068 __hostdev__ Vec3T applyMapF(const Vec3T& xyz) const { return mMap.applyMapF(xyz); } // Pos: index -> world
2069 template<typename Vec3T>
2070 __hostdev__ Vec3T applyInverseMapF(const Vec3T& xyz) const { return mMap.applyInverseMapF(xyz); } // Pos: world -> index
2071 template<typename Vec3T>
2072 __hostdev__ Vec3T applyJacobianF(const Vec3T& xyz) const { return mMap.applyJacobianF(xyz); } // Dir: index -> world
2073 template<typename Vec3T>
2074 __hostdev__ Vec3T applyInverseJacobianF(const Vec3T& xyz) const { return mMap.applyInverseJacobianF(xyz); } // Dir: world -> index
2075 template<typename Vec3T>
2076 __hostdev__ Vec3T applyIJTF(const Vec3T& xyz) const { return mMap.applyIJTF(xyz); }
2077
2078 // @brief Return a non-const void pointer to the tree
2079 __hostdev__ void* treePtr() { return this + 1; }// TreeData is always right after GridData
2080
2081 // @brief Return a const void pointer to the tree
2082 __hostdev__ const void* treePtr() const { return this + 1; }// TreeData is always right after GridData
2083
2084 /// @brief Return a non-const void pointer to the first node at @c LEVEL
2085 /// @tparam LEVEL Level of the node. LEVEL 0 means leaf node and LEVEL 3 means root node
2086 template <uint32_t LEVEL>
2087 __hostdev__ const void* nodePtr() const
2088 {
2089 static_assert(LEVEL >= 0 && LEVEL <= 3, "invalid LEVEL template parameter");
2090 const void *treeData = this + 1;// TreeData is always right after GridData
2091 const uint64_t nodeOffset = *util::PtrAdd<uint64_t>(treeData, 8*LEVEL);// skip LEVEL uint64_t
2092 return nodeOffset ? util::PtrAdd(treeData, nodeOffset) : nullptr;
2093 }
2094
2095 /// @brief Return a non-const void pointer to the first node at @c LEVEL
2096 /// @tparam LEVEL of the node. LEVEL 0 means leaf node and LEVEL 3 means root node
2097 /// @warning If not nodes exist at @c LEVEL NULL is returned
2098 template <uint32_t LEVEL>
2100 {
2101 static_assert(LEVEL >= 0 && LEVEL <= 3, "invalid LEVEL template parameter");
2102 void *treeData = this + 1;// TreeData is always right after GridData
2103 const uint64_t nodeOffset = *util::PtrAdd<uint64_t>(treeData, 8*LEVEL);// skip LEVEL uint64_t
2104 return nodeOffset ? util::PtrAdd(treeData, nodeOffset) : nullptr;
2105 }
2106
2107 /// @brief Return number of nodes at @c LEVEL
2108 /// @tparam Level of the node. LEVEL 0 means leaf node and LEVEL 2 means upper node
2109 template <uint32_t LEVEL>
2110 __hostdev__ uint32_t nodeCount() const
2111 {
2112 static_assert(LEVEL >= 0 && LEVEL < 3, "invalid LEVEL template parameter");
2113 return *util::PtrAdd<uint32_t>(this + 1, 4*(8 + LEVEL));// TreeData is always right after GridData
2114 }
2115
2116 /// @brief Returns a const reference to the blindMetaData at the specified linear offset.
2117 ///
2118 /// @warning The linear offset is assumed to be in the valid range
2124
2125 __hostdev__ const char* gridName() const
2126 {
2127 if (mFlags.isMaskOn(GridFlags::HasLongGridName)) {// search for first blind meta data that contains a name
2129 for (uint32_t i = 0; i < mBlindMetadataCount; ++i) {
2130 const auto* metaData = this->blindMetaData(i);// EXTREMELY important to be a pointer
2131 if (metaData->mDataClass == GridBlindDataClass::GridName) {
2132 NANOVDB_ASSERT(metaData->mDataType == GridType::Unknown);
2133 return metaData->template getBlindData<const char>();
2134 }
2135 }
2136 NANOVDB_ASSERT(false); // should never hit this!
2137 }
2138 return mGridName;
2139 }
2140
2141 /// @brief Return memory usage in bytes for this class only.
2142 __hostdev__ static uint64_t memUsage() { return sizeof(GridData); }
2143
2144 /// @brief return AABB of active values in world space
2145 __hostdev__ const Vec3dBBox& worldBBox() const { return mWorldBBox; }
2146
2147 /// @brief return AABB of active values in index space
2148 __hostdev__ const CoordBBox& indexBBox() const {return *(const CoordBBox*)(this->nodePtr<3>());}
2149
2150 /// @brief return the root table has size
2152 {
2153 const void *root = this->nodePtr<3>();
2154 return root ? *util::PtrAdd<uint32_t>(root, sizeof(CoordBBox)) : 0u;
2155 }
2156
2157 /// @brief test if the grid is empty, e.i the root table has size 0
2158 /// @return true if this grid contains not data whatsoever
2159 __hostdev__ bool isEmpty() const {return this->rootTableSize() == 0u;}
2160
2161 /// @brief return true if RootData follows TreeData in memory without any extra padding
2162 /// @details TreeData is always following right after GridData, but the same might not be true for RootData
2163 __hostdev__ bool isRootConnected() const { return *(const uint64_t*)((const char*)(this + 1) + 24) == 64u;}
2164}; // GridData
2165
2166// Forward declaration of accelerated random access class
2167template<typename BuildT, int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1>
2169
2170template<typename BuildT>
2172
2173/// @brief Highest level of the data structure. Contains a tree and a world->index
2174/// transform (that currently only supports uniform scaling and translation).
2175///
2176/// @note This the API of this class to interface with client code
2177template<typename TreeT>
2178class Grid : public GridData
2179{
2180public:
2181 using TreeType = TreeT;
2182 using RootType = typename TreeT::RootType;
2184 using UpperNodeType = typename RootNodeType::ChildNodeType;
2185 using LowerNodeType = typename UpperNodeType::ChildNodeType;
2186 using LeafNodeType = typename RootType::LeafNodeType;
2188 using ValueType = typename TreeT::ValueType;
2189 using BuildType = typename TreeT::BuildType; // in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
2190 using CoordType = typename TreeT::CoordType;
2192
2193 /// @brief Disallow constructions, copy and assignment
2194 ///
2195 /// @note Only a Serializer, defined elsewhere, can instantiate this class
2196 Grid(const Grid&) = delete;
2197 Grid& operator=(const Grid&) = delete;
2198 ~Grid() = delete;
2199
2201
2202 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
2203
2204 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
2205
2206 /// @brief Return memory usage in bytes for this class only.
2207 //__hostdev__ static uint64_t memUsage() { return sizeof(GridData); }
2208
2209 /// @brief Return the memory footprint of the entire grid, i.e. including all nodes and blind data
2210 __hostdev__ uint64_t gridSize() const { return DataType::mGridSize; }
2211
2212 /// @brief Return index of this grid in the buffer
2213 __hostdev__ uint32_t gridIndex() const { return DataType::mGridIndex; }
2214
2215 /// @brief Return total number of grids in the buffer
2216 __hostdev__ uint32_t gridCount() const { return DataType::mGridCount; }
2217
2218 /// @brief @brief Return the total number of values indexed by this IndexGrid
2219 ///
2220 /// @note This method is only defined for IndexGrid = NanoGrid<ValueIndex || ValueOnIndex >
2221 template<typename T = BuildType>
2222 __hostdev__ typename util::enable_if<BuildTraits<T>::is_index, const uint64_t&>::type
2223 valueCount() const { return DataType::mData1; }
2224
2225 /// @brief @brief Return the total number of points indexed by this PointGrid
2226 ///
2227 /// @note This method is only defined for PointGrid = NanoGrid<Point>
2228 template<typename T = BuildType>
2229 __hostdev__ typename util::enable_if<util::is_same<T, Point>::value, const uint64_t&>::type
2230 pointCount() const { return DataType::mData1; }
2231
2232 /// @brief Return a const reference to the tree
2233 __hostdev__ const TreeT& tree() const { return *reinterpret_cast<const TreeT*>(this->treePtr()); }
2234
2235 /// @brief Return a non-const reference to the tree
2236 __hostdev__ TreeT& tree() { return *reinterpret_cast<TreeT*>(this->treePtr()); }
2237
2238 /// @brief Return a new instance of a ReadAccessor used to access values in this grid
2239 __hostdev__ AccessorType getAccessor() const { return AccessorType(this->tree().root()); }
2240
2241 /// @brief Return a const reference to the size of a voxel in world units
2243
2244 /// @brief Return a const reference to the Map for this grid
2245 __hostdev__ const Map& map() const { return DataType::mMap; }
2246
2247 /// @brief world to index space transformation
2248 template<typename Vec3T>
2249 __hostdev__ Vec3T worldToIndex(const Vec3T& xyz) const { return this->applyInverseMap(xyz); }
2250
2251 /// @brief index to world space transformation
2252 template<typename Vec3T>
2253 __hostdev__ Vec3T indexToWorld(const Vec3T& xyz) const { return this->applyMap(xyz); }
2254
2255 /// @brief transformation from index space direction to world space direction
2256 /// @warning assumes dir to be normalized
2257 template<typename Vec3T>
2258 __hostdev__ Vec3T indexToWorldDir(const Vec3T& dir) const { return this->applyJacobian(dir); }
2259
2260 /// @brief transformation from world space direction to index space direction
2261 /// @warning assumes dir to be normalized
2262 template<typename Vec3T>
2263 __hostdev__ Vec3T worldToIndexDir(const Vec3T& dir) const { return this->applyInverseJacobian(dir); }
2264
2265 /// @brief transform the gradient from index space to world space.
2266 /// @details Applies the inverse jacobian transform map.
2267 template<typename Vec3T>
2268 __hostdev__ Vec3T indexToWorldGrad(const Vec3T& grad) const { return this->applyIJT(grad); }
2269
2270 /// @brief world to index space transformation
2271 template<typename Vec3T>
2272 __hostdev__ Vec3T worldToIndexF(const Vec3T& xyz) const { return this->applyInverseMapF(xyz); }
2273
2274 /// @brief index to world space transformation
2275 template<typename Vec3T>
2276 __hostdev__ Vec3T indexToWorldF(const Vec3T& xyz) const { return this->applyMapF(xyz); }
2277
2278 /// @brief transformation from index space direction to world space direction
2279 /// @warning assumes dir to be normalized
2280 template<typename Vec3T>
2281 __hostdev__ Vec3T indexToWorldDirF(const Vec3T& dir) const { return this->applyJacobianF(dir); }
2282
2283 /// @brief transformation from world space direction to index space direction
2284 /// @warning assumes dir to be normalized
2285 template<typename Vec3T>
2286 __hostdev__ Vec3T worldToIndexDirF(const Vec3T& dir) const { return this->applyInverseJacobianF(dir); }
2287
2288 /// @brief Transforms the gradient from index space to world space.
2289 /// @details Applies the inverse jacobian transform map.
2290 template<typename Vec3T>
2291 __hostdev__ Vec3T indexToWorldGradF(const Vec3T& grad) const { return DataType::applyIJTF(grad); }
2292
2293 /// @brief Computes a AABB of active values in world space
2294 //__hostdev__ const Vec3dBBox& worldBBox() const { return DataType::mWorldBBox; }
2295
2296 /// @brief Computes a AABB of active values in index space
2297 ///
2298 /// @note This method is returning a floating point bounding box and not a CoordBBox. This makes
2299 /// it more useful for clipping rays.
2300 //__hostdev__ const BBox<CoordType>& indexBBox() const { return this->tree().bbox(); }
2301
2302 /// @brief Return the total number of active voxels in this tree.
2303 __hostdev__ uint64_t activeVoxelCount() const { return this->tree().activeVoxelCount(); }
2304
2305 /// @brief Methods related to the classification of this grid
2306 __hostdev__ bool isValid() const { return DataType::isValid(); }
2319 __hostdev__ bool hasBBox() const { return DataType::mFlags.isMaskOn(GridFlags::HasBBox); }
2324
2325 /// @brief return true if the specified node type is laid out breadth-first in memory and has a fixed size.
2326 /// This allows for sequential access to the nodes.
2327 template<typename NodeT>
2328 __hostdev__ bool isSequential() const { return NodeT::FIXED_SIZE && this->isBreadthFirst(); }
2329
2330 /// @brief return true if the specified node level is laid out breadth-first in memory and has a fixed size.
2331 /// This allows for sequential access to the nodes.
2332 template<int LEVEL>
2334
2335 /// @brief return true if nodes at all levels can safely be accessed with simple linear offsets
2336 __hostdev__ bool isSequential() const { return UpperNodeType::FIXED_SIZE && LowerNodeType::FIXED_SIZE && LeafNodeType::FIXED_SIZE && this->isBreadthFirst(); }
2337
2338 /// @brief Return a c-string with the name of this grid
2339 __hostdev__ const char* gridName() const { return DataType::gridName(); }
2340
2341 /// @brief Return a c-string with the name of this grid, truncated to 255 characters
2342 __hostdev__ const char* shortGridName() const { return DataType::mGridName; }
2343
2344 /// @brief Return checksum of the grid buffer.
2346
2347 /// @brief Return true if this grid is empty, i.e. contains no values or nodes.
2348 //__hostdev__ bool isEmpty() const { return this->tree().isEmpty(); }
2349
2350 /// @brief Return the count of blind-data encoded in this grid
2352
2353 /// @brief Return the index of the first blind data with specified name if found, otherwise -1.
2354 __hostdev__ int findBlindData(const char* name) const;
2355
2356 /// @brief Return the index of the first blind data with specified semantic if found, otherwise -1.
2358
2359 /// @brief Returns a const pointer to the blindData at the specified linear offset.
2360 ///
2361 /// @warning Pointer might be NULL and the linear offset is assumed to be in the valid range
2362 // this method is deprecated !!!!
2363 [[deprecated("Use Grid::getBlindData<T>() instead.")]]
2364 __hostdev__ const void* blindData(uint32_t n) const
2365 {
2366 printf("\nnanovdb::Grid::blindData is unsafe and hence deprecated! Please use nanovdb::Grid::getBlindData instead.\n\n");
2368 return this->blindMetaData(n).blindData();
2369 }
2370
2371 template <typename BlindDataT>
2372 __hostdev__ const BlindDataT* getBlindData(uint32_t n) const
2373 {
2374 if (n >= DataType::mBlindMetadataCount) return nullptr;// index is out of bounds
2375 return this->blindMetaData(n).template getBlindData<BlindDataT>();// NULL if mismatching BlindDataT
2376 }
2377
2378 template <typename BlindDataT>
2379 __hostdev__ BlindDataT* getBlindData(uint32_t n)
2380 {
2381 if (n >= DataType::mBlindMetadataCount) return nullptr;// index is out of bounds
2382 return const_cast<BlindDataT*>(this->blindMetaData(n).template getBlindData<BlindDataT>());// NULL if mismatching BlindDataT
2383 }
2384
2386
2387private:
2388 static_assert(sizeof(GridData) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(GridData) is misaligned");
2389}; // Class Grid
2390
2391template<typename TreeT>
2393{
2394 for (uint32_t i = 0, n = this->blindDataCount(); i < n; ++i) {
2395 if (this->blindMetaData(i).mSemantic == semantic)
2396 return int(i);
2397 }
2398 return -1;
2399}
2400
2401template<typename TreeT>
2402__hostdev__ int Grid<TreeT>::findBlindData(const char* name) const
2403{
2404 auto test = [&](int n) {
2405 const char* str = this->blindMetaData(n).mName;
2406 for (int i = 0; i < GridBlindMetaData::MaxNameSize; ++i) {
2407 if (name[i] != str[i])
2408 return false;
2409 if (name[i] == '\0' && str[i] == '\0')
2410 return true;
2411 }
2412 return true; // all len characters matched
2413 };
2414 for (int i = 0, n = this->blindDataCount(); i < n; ++i)
2415 if (test(i))
2416 return i;
2417 return -1;
2418}
2419
2420// ----------------------------> Tree <--------------------------------------
2421
2422struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) TreeData
2423{ // sizeof(TreeData) == 64B
2424 int64_t mNodeOffset[4];// 32B, byte offset from this tree to first leaf, lower, upper and root node. If mNodeCount[N]=0 => mNodeOffset[N]==mNodeOffset[N+1]
2425 uint32_t mNodeCount[3]; // 12B, total number of nodes of type: leaf, lower internal, upper internal
2426 uint32_t mTileCount[3]; // 12B, total number of active tile values at the lower internal, upper internal and root node levels
2427 uint64_t mVoxelCount; // 8B, total number of active voxels in the root and all its child nodes.
2428 // No padding since it's always 32B aligned
2429 TreeData& operator=(const TreeData&) = default;
2430 __hostdev__ void setRoot(const void* root) {
2431 NANOVDB_ASSERT(root);
2432 mNodeOffset[3] = util::PtrDiff(root, this);
2433 }
2434
2435 /// @brief Get a non-const void pointer to the root node (never NULL)
2436 __hostdev__ void* getRoot() { return util::PtrAdd(this, mNodeOffset[3]); }
2437
2438 /// @brief Get a const void pointer to the root node (never NULL)
2439 __hostdev__ const void* getRoot() const { return util::PtrAdd(this, mNodeOffset[3]); }
2440
2441 template<typename NodeT>
2442 __hostdev__ void setFirstNode(const NodeT* node) {mNodeOffset[NodeT::LEVEL] = (node ? util::PtrDiff(node, this) : 0);}
2443
2444 /// @brief Return true if the root is empty, i.e. has not child nodes or constant tiles
2445 __hostdev__ bool isEmpty() const {return mNodeOffset[3] ? *util::PtrAdd<uint32_t>(this, mNodeOffset[3] + sizeof(CoordBBox)) == 0 : true;}
2446
2447 /// @brief Return the index bounding box of all the active values in this tree, i.e. in all nodes of the tree
2449
2450 /// @brief return true if RootData is layout out immediately after TreeData in memory
2451 __hostdev__ bool isRootNext() const {return mNodeOffset[3] ? mNodeOffset[3] == sizeof(TreeData) : false; }
2452};// TreeData
2453
2454// ----------------------------> GridTree <--------------------------------------
2455
2456/// @brief defines a tree type from a grid type while preserving constness
2457template<typename GridT>
2459{
2460 using Type = typename GridT::TreeType;
2461 using type = typename GridT::TreeType;
2462};
2463template<typename GridT>
2464struct GridTree<const GridT>
2465{
2466 using Type = const typename GridT::TreeType;
2467 using type = const typename GridT::TreeType;
2468};
2469
2470template<typename GridT>
2472
2473// ----------------------------> Tree <--------------------------------------
2474
2475/// @brief VDB Tree, which is a thin wrapper around a RootNode.
2476template<typename RootT>
2477class Tree : public TreeData
2478{
2479 static_assert(RootT::LEVEL == 3, "Tree depth is not supported");
2480 static_assert(RootT::ChildNodeType::LOG2DIM == 5, "Tree configuration is not supported");
2481 static_assert(RootT::ChildNodeType::ChildNodeType::LOG2DIM == 4, "Tree configuration is not supported");
2482 static_assert(RootT::LeafNodeType::LOG2DIM == 3, "Tree configuration is not supported");
2483
2484public:
2486 using RootType = RootT;
2487 using RootNodeType = RootT;
2488 using UpperNodeType = typename RootNodeType::ChildNodeType;
2489 using LowerNodeType = typename UpperNodeType::ChildNodeType;
2490 using LeafNodeType = typename RootType::LeafNodeType;
2491 using ValueType = typename RootT::ValueType;
2492 using BuildType = typename RootT::BuildType; // in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
2493 using CoordType = typename RootT::CoordType;
2495
2496 using Node3 = RootT;
2497 using Node2 = typename RootT::ChildNodeType;
2498 using Node1 = typename Node2::ChildNodeType;
2500
2501 /// @brief This class cannot be constructed or deleted
2502 Tree() = delete;
2503 Tree(const Tree&) = delete;
2504 Tree& operator=(const Tree&) = delete;
2505 ~Tree() = delete;
2506
2507 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
2508
2509 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
2510
2511 /// @brief return memory usage in bytes for the class
2512 __hostdev__ static uint64_t memUsage() { return sizeof(DataType); }
2513
2514 __hostdev__ RootT& root() {return *reinterpret_cast<RootT*>(DataType::getRoot());}
2515
2516 __hostdev__ const RootT& root() const {return *reinterpret_cast<const RootT*>(DataType::getRoot());}
2517
2519
2520 /// @brief Return the value of the given voxel (regardless of state or location in the tree.)
2521 __hostdev__ ValueType getValue(const CoordType& ijk) const { return this->root().getValue(ijk); }
2522 __hostdev__ ValueType getValue(int i, int j, int k) const { return this->root().getValue(CoordType(i, j, k)); }
2523
2524 /// @brief Return the active state of the given voxel (regardless of state or location in the tree.)
2525 __hostdev__ bool isActive(const CoordType& ijk) const { return this->root().isActive(ijk); }
2526
2527 /// @brief Return true if this tree is empty, i.e. contains no values or nodes
2528 //__hostdev__ bool isEmpty() const { return this->root().isEmpty(); }
2529
2530 /// @brief Combines the previous two methods in a single call
2531 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->root().probeValue(ijk, v); }
2532
2533 /// @brief Return a const reference to the background value.
2534 __hostdev__ const ValueType& background() const { return this->root().background(); }
2535
2536 /// @brief Sets the extrema values of all the active values in this tree, i.e. in all nodes of the tree
2537 __hostdev__ void extrema(ValueType& min, ValueType& max) const;
2538
2539 /// @brief Return a const reference to the index bounding box of all the active values in this tree, i.e. in all nodes of the tree
2540 //__hostdev__ const BBox<CoordType>& bbox() const { return this->root().bbox(); }
2541
2542 /// @brief Return the total number of active voxels in this tree.
2544
2545 /// @brief Return the total number of active tiles at the specified level of the tree.
2546 ///
2547 /// @details level = 1,2,3 corresponds to active tile count in lower internal nodes, upper
2548 /// internal nodes, and the root level. Note active values at the leaf level are
2549 /// referred to as active voxels (see activeVoxelCount defined above).
2550 __hostdev__ const uint32_t& activeTileCount(uint32_t level) const
2551 {
2552 NANOVDB_ASSERT(level > 0 && level <= 3); // 1, 2, or 3
2553 return DataType::mTileCount[level - 1];
2554 }
2555
2556 template<typename NodeT>
2557 __hostdev__ uint32_t nodeCount() const
2558 {
2559 static_assert(NodeT::LEVEL < 3, "Invalid NodeT");
2560 return DataType::mNodeCount[NodeT::LEVEL];
2561 }
2562
2563 __hostdev__ uint32_t nodeCount(int level) const
2564 {
2565 NANOVDB_ASSERT(level < 3);
2566 return DataType::mNodeCount[level];
2567 }
2568
2570 {
2572 }
2573
2574 /// @brief return a pointer to the first node of the specified type
2575 ///
2576 /// @warning Note it may return NULL if no nodes exist
2577 template<typename NodeT>
2579 {
2580 const int64_t nodeOffset = DataType::mNodeOffset[NodeT::LEVEL];
2581 return nodeOffset ? util::PtrAdd<NodeT>(this, nodeOffset) : nullptr;
2582 }
2583
2584 /// @brief return a const pointer to the first node of the specified type
2585 ///
2586 /// @warning Note it may return NULL if no nodes exist
2587 template<typename NodeT>
2588 __hostdev__ const NodeT* getFirstNode() const
2589 {
2590 const int64_t nodeOffset = DataType::mNodeOffset[NodeT::LEVEL];
2591 return nodeOffset ? util::PtrAdd<NodeT>(this, nodeOffset) : nullptr;
2592 }
2593
2594 /// @brief return a pointer to the first node at the specified level
2595 ///
2596 /// @warning Note it may return NULL if no nodes exist
2597 template<int LEVEL>
2602
2603 /// @brief return a const pointer to the first node of the specified level
2604 ///
2605 /// @warning Note it may return NULL if no nodes exist
2606 template<int LEVEL>
2608 {
2610 }
2611
2612 /// @brief Template specializations of getFirstNode
2616 __hostdev__ const typename NodeTrait<RootT, 1>::type* getFirstLower() const { return this->getFirstNode<1>(); }
2618 __hostdev__ const typename NodeTrait<RootT, 2>::type* getFirstUpper() const { return this->getFirstNode<2>(); }
2619
2620 template<typename OpT, typename... ArgsT>
2621 __hostdev__ auto get(const CoordType& ijk, ArgsT&&... args) const
2622 {
2623 return this->root().template get<OpT>(ijk, args...);
2624 }
2625
2626 template<typename OpT, typename... ArgsT>
2627 __hostdev__ auto set(const CoordType& ijk, ArgsT&&... args)
2628 {
2629 return this->root().template set<OpT>(ijk, args...);
2630 }
2631
2632private:
2633 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(TreeData) is misaligned");
2634
2635}; // Tree class
2636
2637template<typename RootT>
2639{
2640 min = this->root().minimum();
2641 max = this->root().maximum();
2642}
2643
2644// --------------------------> RootData <------------------------------------
2645
2646/// @brief Struct with all the member data of the RootNode (useful during serialization of an openvdb RootNode)
2647///
2648/// @note No client code should (or can) interface with this struct so it can safely be ignored!
2649template<typename ChildT>
2650struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) RootData
2651{
2652 using ValueT = typename ChildT::ValueType;
2653 using BuildT = typename ChildT::BuildType; // in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
2654 using CoordT = typename ChildT::CoordType;
2655 using StatsT = typename ChildT::FloatType;
2656 static constexpr bool FIXED_SIZE = false;
2657
2658 /// @brief Return a key based on the coordinates of a voxel
2659#ifdef NANOVDB_USE_SINGLE_ROOT_KEY
2660 using KeyT = uint64_t;
2661 template<typename CoordType>
2662 __hostdev__ static KeyT CoordToKey(const CoordType& ijk)
2663 {
2664 static_assert(sizeof(CoordT) == sizeof(CoordType), "Mismatching sizeof");
2665 static_assert(32 - ChildT::TOTAL <= 21, "Cannot use 64 bit root keys");
2666 return (KeyT(uint32_t(ijk[2]) >> ChildT::TOTAL)) | // z is the lower 21 bits
2667 (KeyT(uint32_t(ijk[1]) >> ChildT::TOTAL) << 21) | // y is the middle 21 bits
2668 (KeyT(uint32_t(ijk[0]) >> ChildT::TOTAL) << 42); // x is the upper 21 bits
2669 }
2671 {
2672 static constexpr uint64_t MASK = (1u << 21) - 1; // used to mask out 21 lower bits
2673 return CoordT(((key >> 42) & MASK) << ChildT::TOTAL, // x are the upper 21 bits
2674 ((key >> 21) & MASK) << ChildT::TOTAL, // y are the middle 21 bits
2675 ( key & MASK) << ChildT::TOTAL); // z are the lower 21 bits
2676 }
2677#else
2678 using KeyT = CoordT;
2679 __hostdev__ static KeyT CoordToKey(const CoordT& ijk) { return ijk & ~ChildT::MASK; }
2680 __hostdev__ static CoordT KeyToCoord(const KeyT& key) { return key; }
2681#endif
2682 math::BBox<CoordT> mBBox; // 24B. AABB of active values in index space.
2683 uint32_t mTableSize; // 4B. number of tiles and child pointers in the root node
2684
2685 ValueT mBackground; // background value, i.e. value of any unset voxel
2686 ValueT mMinimum; // typically 4B, minimum of all the active values
2687 ValueT mMaximum; // typically 4B, maximum of all the active values
2688 StatsT mAverage; // typically 4B, average of all the active values in this node and its child nodes
2689 StatsT mStdDevi; // typically 4B, standard deviation of all the active values in this node and its child nodes
2690
2691 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
2692 ///
2693 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
2694 __hostdev__ static constexpr uint32_t padding()
2695 {
2696 return sizeof(RootData) - (24 + 4 + 3 * sizeof(ValueT) + 2 * sizeof(StatsT));
2697 }
2698
2699 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) Tile
2700 {
2701 template<typename CoordType>
2702 __hostdev__ void setChild(const CoordType& k, const void* ptr, const RootData* data)
2703 {
2704 key = CoordToKey(k);
2705 state = false;
2706 child = util::PtrDiff(ptr, data);
2707 }
2708 template<typename CoordType, typename ValueType>
2709 __hostdev__ void setValue(const CoordType& k, bool s, const ValueType& v)
2710 {
2711 key = CoordToKey(k);
2712 state = s;
2713 value = v;
2714 child = 0;
2715 }
2716 __hostdev__ bool isChild() const { return child != 0; }
2717 __hostdev__ bool isValue() const { return child == 0; }
2718 __hostdev__ bool isActive() const { return child == 0 && state; }
2720 KeyT key; // NANOVDB_USE_SINGLE_ROOT_KEY ? 8B : 12B
2721 int64_t child; // 8B. signed byte offset from this node to the child node. 0 means it is a constant tile, so use value.
2722 uint32_t state; // 4B. state of tile value
2723 ValueT value; // value of tile (i.e. no child node)
2724 }; // Tile
2725
2726 /// @brief Returns a pointer to the tile at the specified linear offset.
2727 ///
2728 /// @warning The linear offset is assumed to be in the valid range
2729 __hostdev__ const Tile* tile(uint32_t n) const
2730 {
2732 return reinterpret_cast<const Tile*>(this + 1) + n;
2733 }
2734 __hostdev__ Tile* tile(uint32_t n)
2735 {
2737 return reinterpret_cast<Tile*>(this + 1) + n;
2738 }
2739
2740 template<typename DataT>
2742 {
2743 protected:
2747
2748 public:
2749 __hostdev__ TileIter() : mBegin(nullptr), mPos(nullptr), mEnd(nullptr) {}
2750 __hostdev__ TileIter(DataT* data, uint32_t pos = 0)
2751 : mBegin(reinterpret_cast<TileT*>(data + 1))// tiles reside right after the RootData
2752 , mPos(mBegin + pos)
2754 {
2756 NANOVDB_ASSERT(mBegin <= mPos);// pos > mTableSize is allowed
2757 NANOVDB_ASSERT(mBegin <= mEnd);// mTableSize = 0 is possible
2758 }
2759 __hostdev__ inline operator bool() const { return mPos < mEnd; }
2760 __hostdev__ inline auto pos() const {return mPos - mBegin; }
2762 {
2763 ++mPos;
2764 return *this;
2765 }
2767 {
2769 return *mPos;
2770 }
2772 {
2774 return mPos;
2775 }
2776 __hostdev__ inline DataT* data() const
2777 {
2779 return reinterpret_cast<DataT*>(mBegin) - 1;
2780 }
2781 __hostdev__ inline bool isChild() const
2782 {
2784 return mPos->child != 0;
2785 }
2786 __hostdev__ inline bool isValue() const
2787 {
2789 return mPos->child == 0;
2790 }
2791 __hostdev__ inline bool isValueOn() const
2792 {
2794 return mPos->child == 0 && mPos->state != 0;
2795 }
2796 __hostdev__ inline NodeT* child() const
2797 {
2798 NANOVDB_ASSERT(mPos < mEnd && mPos->child != 0);
2799 return util::PtrAdd<NodeT>(this->data(), mPos->child);// byte offset relative to RootData::this
2800 }
2801 __hostdev__ inline ValueT value() const
2802 {
2803 NANOVDB_ASSERT(mPos < mEnd && mPos->child == 0);
2804 return mPos->value;
2805 }
2806 };// TileIter
2807
2810
2813
2815 {
2816 const auto key = CoordToKey(ijk);
2817 TileIterator iter(this);
2818 for(; iter; ++iter) if (iter->key == key) break;
2819 return iter;
2820 }
2821
2823 {
2824 const auto key = CoordToKey(ijk);
2825 ConstTileIterator iter(this);
2826 for(; iter; ++iter) if (iter->key == key) break;
2827 return iter;
2828 }
2829
2830 __hostdev__ inline Tile* probeTile(const CoordT& ijk)
2831 {
2832 auto iter = this->probe(ijk);
2833 return iter ? iter.operator->() : nullptr;
2834 }
2835
2836 __hostdev__ inline const Tile* probeTile(const CoordT& ijk) const
2837 {
2838 return const_cast<RootData*>(this)->probeTile(ijk);
2839 }
2840
2841 __hostdev__ inline ChildT* probeChild(const CoordT& ijk)
2842 {
2843 auto iter = this->probe(ijk);
2844 return iter && iter.isChild() ? iter.child() : nullptr;
2845 }
2846
2847 __hostdev__ inline const ChildT* probeChild(const CoordT& ijk) const
2848 {
2849 return const_cast<RootData*>(this)->probeChild(ijk);
2850 }
2851
2852 /// @brief Returns a const reference to the child node in the specified tile.
2853 ///
2854 /// @warning A child node is assumed to exist in the specified tile
2856 {
2857 NANOVDB_ASSERT(tile->child);
2858 return util::PtrAdd<ChildT>(this, tile->child);
2859 }
2860 __hostdev__ const ChildT* getChild(const Tile* tile) const
2861 {
2862 NANOVDB_ASSERT(tile->child);
2863 return util::PtrAdd<ChildT>(this, tile->child);
2864 }
2865
2866 __hostdev__ const ValueT& getMin() const { return mMinimum; }
2867 __hostdev__ const ValueT& getMax() const { return mMaximum; }
2868 __hostdev__ const StatsT& average() const { return mAverage; }
2869 __hostdev__ const StatsT& stdDeviation() const { return mStdDevi; }
2870
2871 __hostdev__ void setMin(const ValueT& v) { mMinimum = v; }
2872 __hostdev__ void setMax(const ValueT& v) { mMaximum = v; }
2873 __hostdev__ void setAvg(const StatsT& v) { mAverage = v; }
2874 __hostdev__ void setDev(const StatsT& v) { mStdDevi = v; }
2875
2876 /// @brief This class cannot be constructed or deleted
2877 RootData() = delete;
2878 RootData(const RootData&) = delete;
2879 RootData& operator=(const RootData&) = delete;
2880 ~RootData() = delete;
2881}; // RootData
2882
2883// --------------------------> RootNode <------------------------------------
2884
2885/// @brief Top-most node of the VDB tree structure.
2886template<typename ChildT>
2887class RootNode : public RootData<ChildT>
2888{
2889public:
2891 using ChildNodeType = ChildT;
2892 using RootType = RootNode<ChildT>; // this allows RootNode to behave like a Tree
2894 using UpperNodeType = ChildT;
2895 using LowerNodeType = typename UpperNodeType::ChildNodeType;
2896 using LeafNodeType = typename ChildT::LeafNodeType;
2897 using ValueType = typename DataType::ValueT;
2898 using FloatType = typename DataType::StatsT;
2899 using BuildType = typename DataType::BuildT; // in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
2900
2901 using CoordType = typename ChildT::CoordType;
2904 using Tile = typename DataType::Tile;
2905 static constexpr bool FIXED_SIZE = DataType::FIXED_SIZE;
2906
2907 static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
2908
2909 template<typename RootT>
2911 {
2912 protected:
2915 typename DataType::template TileIter<DataT> mTileIter;
2918
2919 public:
2920 __hostdev__ operator bool() const { return bool(mTileIter); }
2921 __hostdev__ uint32_t pos() const { return uint32_t(mTileIter.pos()); }
2922 __hostdev__ TileT* tile() const { return mTileIter.operator->(); }
2923 __hostdev__ CoordType getOrigin() const {return mTileIter->origin();}
2924 __hostdev__ CoordType getCoord() const {return this->getOrigin();}
2925 }; // Member class BaseIter
2926
2927 template<typename RootT>
2928 class ChildIter : public BaseIter<RootT>
2929 {
2930 static_assert(util::is_same<typename util::remove_const<RootT>::type, RootNode>::value, "Invalid RootT");
2931 using BaseT = BaseIter<RootT>;
2932 using NodeT = typename util::match_const<ChildT, RootT>::type;
2933 using BaseT::mTileIter;
2934
2935 public:
2936 __hostdev__ ChildIter() : BaseT() {}
2937 __hostdev__ ChildIter(RootT* parent) : BaseT(parent->data())
2938 {
2939 while (mTileIter && mTileIter.isValue()) ++mTileIter;
2940 }
2941 __hostdev__ NodeT& operator*() const {return *mTileIter.child();}
2942 __hostdev__ NodeT* operator->() const {return mTileIter.child();}
2944 {
2945 ++mTileIter;
2946 while (mTileIter && mTileIter.isValue()) ++mTileIter;
2947 return *this;
2948 }
2950 {
2951 auto tmp = *this;
2952 this->operator++();
2953 return tmp;
2954 }
2955 }; // Member class ChildIter
2956
2959
2962
2963 template<typename RootT>
2964 class ValueIter : public BaseIter<RootT>
2965 {
2966 using BaseT = BaseIter<RootT>;
2967 using BaseT::mTileIter;
2968
2969 public:
2971 __hostdev__ ValueIter(RootT* parent) : BaseT(parent->data())
2972 {
2973 while (mTileIter && mTileIter.isChild()) ++mTileIter;
2974 }
2975 __hostdev__ ValueType operator*() const {return mTileIter.value();}
2976 __hostdev__ bool isActive() const {return mTileIter.isValueOn();}
2978 {
2979 ++mTileIter;
2980 while (mTileIter && mTileIter.isChild()) ++mTileIter;
2981 return *this;
2982 }
2984 {
2985 auto tmp = *this;
2986 this->operator++();
2987 return tmp;
2988 }
2989 }; // Member class ValueIter
2990
2993
2996
2997 template<typename RootT>
2998 class ValueOnIter : public BaseIter<RootT>
2999 {
3000 using BaseT = BaseIter<RootT>;
3001 using BaseT::mTileIter;
3002
3003 public:
3005 __hostdev__ ValueOnIter(RootT* parent) : BaseT(parent->data())
3006 {
3007 while (mTileIter && !mTileIter.isValueOn()) ++mTileIter;
3008 }
3009 __hostdev__ ValueType operator*() const {return mTileIter.value();}
3011 {
3012 ++mTileIter;
3013 while (mTileIter && !mTileIter.isValueOn()) ++mTileIter;
3014 return *this;
3015 }
3017 {
3018 auto tmp = *this;
3019 this->operator++();
3020 return tmp;
3021 }
3022 }; // Member class ValueOnIter
3023
3026
3029
3030 template<typename RootT>
3031 class DenseIter : public BaseIter<RootT>
3032 {
3033 using BaseT = BaseIter<RootT>;
3034 using NodeT = typename util::match_const<ChildT, RootT>::type;
3035 using BaseT::mTileIter;
3036
3037 public:
3039 __hostdev__ DenseIter(RootT* parent) : BaseT(parent->data()){}
3040 __hostdev__ NodeT* probeChild(ValueType& value) const
3041 {
3042 if (mTileIter.isChild()) return mTileIter.child();
3043 value = mTileIter.value();
3044 return nullptr;
3045 }
3046 __hostdev__ bool isValueOn() const{return mTileIter.isValueOn();}
3048 {
3049 ++mTileIter;
3050 return *this;
3051 }
3053 {
3054 auto tmp = *this;
3055 ++mTileIter;
3056 return tmp;
3057 }
3058 }; // Member class DenseIter
3059
3062
3066
3067 /// @brief This class cannot be constructed or deleted
3068 RootNode() = delete;
3069 RootNode(const RootNode&) = delete;
3070 RootNode& operator=(const RootNode&) = delete;
3071 ~RootNode() = delete;
3072
3074
3075 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
3076
3077 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
3078
3079 /// @brief Return a const reference to the index bounding box of all the active values in this tree, i.e. in all nodes of the tree
3080 __hostdev__ const BBoxType& bbox() const { return DataType::mBBox; }
3081
3082 /// @brief Return the total number of active voxels in the root and all its child nodes.
3083
3084 /// @brief Return a const reference to the background value, i.e. the value associated with
3085 /// any coordinate location that has not been set explicitly.
3087
3088 /// @brief Return the number of tiles encoded in this root node
3089 __hostdev__ const uint32_t& tileCount() const { return DataType::mTableSize; }
3090 __hostdev__ const uint32_t& getTableSize() const { return DataType::mTableSize; }
3091
3092 /// @brief Return a const reference to the minimum active value encoded in this root node and any of its child nodes
3094
3095 /// @brief Return a const reference to the maximum active value encoded in this root node and any of its child nodes
3097
3098 /// @brief Return a const reference to the average of all the active values encoded in this root node and any of its child nodes
3100
3101 /// @brief Return the variance of all the active values encoded in this root node and any of its child nodes
3103
3104 /// @brief Return a const reference to the standard deviation of all the active values encoded in this root node and any of its child nodes
3106
3107 /// @brief Return the expected memory footprint in bytes with the specified number of tiles
3108 __hostdev__ static uint64_t memUsage(uint32_t tableSize) { return sizeof(RootNode) + tableSize * sizeof(Tile); }
3109
3110 /// @brief Return the actual memory footprint of this root node
3111 __hostdev__ uint64_t memUsage() const { return sizeof(RootNode) + DataType::mTableSize * sizeof(Tile); }
3112
3113 /// @brief Return true if this RootNode is empty, i.e. contains no values or nodes
3114 __hostdev__ bool isEmpty() const { return DataType::mTableSize == uint32_t(0); }
3115
3116 /// @brief Return the value of the given voxel
3117 __hostdev__ ValueType getValue(const CoordType& ijk) const { return this->template get<GetValue<BuildType>>(ijk); }
3118 __hostdev__ ValueType getValue(int i, int j, int k) const { return this->template get<GetValue<BuildType>>(CoordType(i, j, k)); }
3119 __hostdev__ bool isActive(const CoordType& ijk) const { return this->template get<GetState<BuildType>>(ijk); }
3120 /// @brief return the state and updates the value of the specified voxel
3121 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->template get<ProbeValue<BuildType>>(ijk, v); }
3122 __hostdev__ const LeafNodeType* probeLeaf(const CoordType& ijk) const { return this->template get<GetLeaf<BuildType>>(ijk); }
3123
3124 template<typename OpT, typename... ArgsT>
3125 __hostdev__ typename OpT::Type get(const CoordType& ijk, ArgsT&&... args) const
3126 {
3127 if (const Tile* tile = this->probeTile(ijk)) {
3128 if constexpr(OpT::LEVEL < LEVEL) if (tile->isChild()) return this->getChild(tile)->template get<OpT>(ijk, args...);
3129 return OpT::get(*tile, args...);
3130 }
3131 return OpT::get(*this, args...);
3132 }
3133
3134 template<typename OpT, typename... ArgsT>
3135 __hostdev__ void set(const CoordType& ijk, ArgsT&&... args)
3136 {
3137 if (Tile* tile = DataType::probeTile(ijk)) {
3138 if constexpr(OpT::LEVEL < LEVEL) if (tile->isChild()) return this->getChild(tile)->template set<OpT>(ijk, args...);
3139 return OpT::set(*tile, args...);
3140 }
3141 return OpT::set(*this, args...);
3142 }
3143
3144private:
3145 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(RootData) is misaligned");
3146 static_assert(sizeof(typename DataType::Tile) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(RootData::Tile) is misaligned");
3147
3148 template<typename, int, int, int>
3149 friend class ReadAccessor;
3150
3151 template<typename>
3152 friend class Tree;
3153
3154 template<typename RayT, typename AccT>
3155 __hostdev__ uint32_t getDimAndCache(const CoordType& ijk, const RayT& ray, const AccT& acc) const
3156 {
3157 if (const Tile* tile = this->probeTile(ijk)) {
3158 if (tile->isChild()) {
3159 const auto* child = this->getChild(tile);
3160 acc.insert(ijk, child);
3161 return child->getDimAndCache(ijk, ray, acc);
3162 }
3163 return 1 << ChildT::TOTAL; //tile value
3164 }
3165 return ChildNodeType::dim(); // background
3166 }
3167
3168 /// @brief Returns dim and active state in one traversal, sharing cache and
3169 /// terminal tile/mask reads. Root has no skip flag, so @c Policy affects
3170 /// only the child descent; see ActiveExact and ActiveOnLeafOnly.
3171 template<typename Policy = ActiveExact, typename RayT, typename AccT>
3172 __hostdev__ DimAndActive getDimAndActiveAndCache(const CoordType& ijk, const RayT& ray, const AccT& acc) const
3173 {
3174 if (const Tile* tile = this->probeTile(ijk)) {
3175 if (tile->isChild()) {
3176 const auto* child = this->getChild(tile);
3177 acc.insert(ijk, child);
3178 return child->template getDimAndActiveAndCache<Policy>(ijk, ray, acc);
3179 }
3180 return {uint32_t(1) << ChildT::TOTAL, tile->state > 0u}; // tile value
3181 }
3182 return {ChildNodeType::dim(), false}; // background is never active
3183 }
3184
3185 template<typename OpT, typename AccT, typename... ArgsT>
3186 __hostdev__ typename OpT::Type getAndCache(const CoordType& ijk, const AccT& acc, ArgsT&&... args) const
3187 {
3188 if (const Tile* tile = this->probeTile(ijk)) {
3189 if constexpr(OpT::LEVEL < LEVEL) {
3190 if (tile->isChild()) {
3191 const ChildT* child = this->getChild(tile);
3192 acc.insert(ijk, child);
3193 return child->template getAndCache<OpT>(ijk, acc, args...);
3194 }
3195 }
3196 return OpT::get(*tile, args...);
3197 }
3198 return OpT::get(*this, args...);
3199 }
3200
3201 template<typename OpT, typename AccT, typename... ArgsT>
3202 __hostdev__ void setAndCache(const CoordType& ijk, const AccT& acc, ArgsT&&... args)
3203 {
3204 if (Tile* tile = DataType::probeTile(ijk)) {
3205 if constexpr(OpT::LEVEL < LEVEL) {
3206 if (tile->isChild()) {
3207 ChildT* child = this->getChild(tile);
3208 acc.insert(ijk, child);
3209 return child->template setAndCache<OpT>(ijk, acc, args...);
3210 }
3211 }
3212 return OpT::set(*tile, args...);
3213 }
3214 return OpT::set(*this, args...);
3215 }
3216
3217}; // RootNode class
3218
3219// After the RootNode the memory layout is assumed to be the sorted Tiles
3220
3221// --------------------------> InternalNode <------------------------------------
3222
3223/// @brief Struct with all the member data of the InternalNode (useful during serialization of an openvdb InternalNode)
3224///
3225/// @note No client code should (or can) interface with this struct so it can safely be ignored!
3226template<typename ChildT, uint32_t LOG2DIM>
3227struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) InternalData
3228{
3229 using ValueT = typename ChildT::ValueType;
3230 using BuildT = typename ChildT::BuildType; // in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
3231 using StatsT = typename ChildT::FloatType;
3232 using CoordT = typename ChildT::CoordType;
3233 using MaskT = typename ChildT::template MaskType<LOG2DIM>;
3234 static constexpr bool FIXED_SIZE = true;
3235
3236 union Tile
3237 {
3239 int64_t child; //signed 64 bit byte offset relative to this InternalData, i.e. child-pointer = Tile::child + this
3240 /// @brief This class cannot be constructed or deleted
3241 Tile() = delete;
3242 Tile(const Tile&) = delete;
3243 Tile& operator=(const Tile&) = delete;
3244 ~Tile() = delete;
3245 };
3246
3247 math::BBox<CoordT> mBBox; // 24B. node bounding box. |
3248 uint64_t mFlags; // 8B. node flags. | 32B aligned
3249 MaskT mValueMask; // LOG2DIM(5): 4096B, LOG2DIM(4): 512B | 32B aligned
3250 MaskT mChildMask; // LOG2DIM(5): 4096B, LOG2DIM(4): 512B | 32B aligned
3251
3252 ValueT mMinimum; // typically 4B
3253 ValueT mMaximum; // typically 4B
3254 StatsT mAverage; // typically 4B, average of all the active values in this node and its child nodes
3255 StatsT mStdDevi; // typically 4B, standard deviation of all the active values in this node and its child nodes
3256 // possible padding, e.g. 28 byte padding when ValueType = bool
3257
3258 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
3259 ///
3260 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
3261 __hostdev__ static constexpr uint32_t padding()
3262 {
3263 return sizeof(InternalData) - (24u + 8u + 2 * (sizeof(MaskT) + sizeof(ValueT) + sizeof(StatsT)) + (1u << (3 * LOG2DIM)) * (sizeof(ValueT) > 8u ? sizeof(ValueT) : 8u));
3264 }
3265 alignas(32) Tile mTable[1u << (3 * LOG2DIM)]; // sizeof(ValueT) x (16*16*16 or 32*32*32)
3266
3267 __hostdev__ static uint64_t memUsage() { return sizeof(InternalData); }
3268
3269 __hostdev__ void setChild(uint32_t n, const void* ptr)
3270 {
3271 NANOVDB_ASSERT(mChildMask.isOn(n));
3272 mTable[n].child = util::PtrDiff(ptr, this);
3273 }
3274
3275 template<typename ValueT>
3276 __hostdev__ void setValue(uint32_t n, const ValueT& v)
3277 {
3278 NANOVDB_ASSERT(!mChildMask.isOn(n));
3279 mTable[n].value = v;
3280 }
3281
3282 /// @brief Returns a pointer to the child node at the specifed linear offset.
3283 __hostdev__ ChildT* getChild(uint32_t n)
3284 {
3285 NANOVDB_ASSERT(mChildMask.isOn(n));
3286 return util::PtrAdd<ChildT>(this, mTable[n].child);
3287 }
3288 __hostdev__ const ChildT* getChild(uint32_t n) const
3289 {
3290 NANOVDB_ASSERT(mChildMask.isOn(n));
3291 return util::PtrAdd<ChildT>(this, mTable[n].child);
3292 }
3293
3294 __hostdev__ ValueT getValue(uint32_t n) const
3295 {
3296 NANOVDB_ASSERT(mChildMask.isOff(n));
3297 return mTable[n].value;
3298 }
3299
3300 __hostdev__ bool isActive(uint32_t n) const
3301 {
3302 NANOVDB_ASSERT(mChildMask.isOff(n));
3303 return mValueMask.isOn(n);
3304 }
3305
3306 __hostdev__ bool isChild(uint32_t n) const { return mChildMask.isOn(n); }
3307
3308 template<typename T>
3309 __hostdev__ void setOrigin(const T& ijk) { mBBox[0] = ijk; }
3310
3311 __hostdev__ const ValueT& getMin() const { return mMinimum; }
3312 __hostdev__ const ValueT& getMax() const { return mMaximum; }
3313 __hostdev__ const StatsT& average() const { return mAverage; }
3314 __hostdev__ const StatsT& stdDeviation() const { return mStdDevi; }
3315
3316// GCC 13 (and possibly prior versions) has a regression that results in invalid
3317// warnings when -Wstringop-overflow is turned on. For details, refer to
3318// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101854
3319// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106757
3320#if defined(__GNUC__) && (__GNUC__ < 14) && !defined(__APPLE__) && !defined(__llvm__)
3321#pragma GCC diagnostic push
3322#pragma GCC diagnostic ignored "-Wstringop-overflow"
3323#endif
3324 __hostdev__ void setMin(const ValueT& v) { mMinimum = v; }
3325 __hostdev__ void setMax(const ValueT& v) { mMaximum = v; }
3326 __hostdev__ void setAvg(const StatsT& v) { mAverage = v; }
3327 __hostdev__ void setDev(const StatsT& v) { mStdDevi = v; }
3328#if defined(__GNUC__) && (__GNUC__ < 14) && !defined(__APPLE__) && !defined(__llvm__)
3329#pragma GCC diagnostic pop
3330#endif
3331
3332 /// @brief This class cannot be constructed or deleted
3333 InternalData() = delete;
3334 InternalData(const InternalData&) = delete;
3336 ~InternalData() = delete;
3337}; // InternalData
3338
3339/// @brief Internal nodes of a VDB tree
3340template<typename ChildT, uint32_t Log2Dim = ChildT::LOG2DIM + 1>
3341class InternalNode : public InternalData<ChildT, Log2Dim>
3342{
3343public:
3345 using ValueType = typename DataType::ValueT;
3346 using FloatType = typename DataType::StatsT;
3347 using BuildType = typename DataType::BuildT; // in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
3348 using LeafNodeType = typename ChildT::LeafNodeType;
3349 using ChildNodeType = ChildT;
3350 using CoordType = typename ChildT::CoordType;
3351 static constexpr bool FIXED_SIZE = DataType::FIXED_SIZE;
3352 template<uint32_t LOG2>
3353 using MaskType = typename ChildT::template MaskType<LOG2>;
3354 template<bool On>
3355 using MaskIterT = typename Mask<Log2Dim>::template Iterator<On>;
3356
3357 static constexpr uint32_t LOG2DIM = Log2Dim;
3358 static constexpr uint32_t TOTAL = LOG2DIM + ChildT::TOTAL; // dimension in index space
3359 static constexpr uint32_t DIM = 1u << TOTAL; // number of voxels along each axis of this node
3360 static constexpr uint32_t SIZE = 1u << (3 * LOG2DIM); // number of tile values (or child pointers)
3361 static constexpr uint32_t MASK = (1u << TOTAL) - 1u;
3362 static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
3363 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
3364
3365 /// @brief Visits child nodes of this node only
3366 template <typename ParentT>
3367 class ChildIter : public MaskIterT<true>
3368 {
3369 static_assert(util::is_same<typename util::remove_const<ParentT>::type, InternalNode>::value, "Invalid ParentT");
3370 using BaseT = MaskIterT<true>;
3371 using NodeT = typename util::match_const<ChildT, ParentT>::type;
3372 ParentT* mParent;
3373
3374 public:
3376 : BaseT()
3377 , mParent(nullptr)
3378 {
3379 }
3380 __hostdev__ ChildIter(ParentT* parent)
3381 : BaseT(parent->mChildMask.beginOn())
3382 , mParent(parent)
3383 {
3384 }
3385 ChildIter& operator=(const ChildIter&) = default;
3386 __hostdev__ NodeT& operator*() const
3387 {
3388 NANOVDB_ASSERT(*this);
3389 return *mParent->getChild(BaseT::pos());
3390 }
3392 {
3393 NANOVDB_ASSERT(*this);
3394 return mParent->getChild(BaseT::pos());
3395 }
3397 {
3398 NANOVDB_ASSERT(*this);
3399 return (*this)->origin();
3400 }
3401 __hostdev__ CoordType getCoord() const {return this->getOrigin();}
3402 }; // Member class ChildIter
3403
3406
3409
3410 /// @brief Visits all tile values in this node, i.e. both inactive and active tiles
3411 class ValueIterator : public MaskIterT<false>
3412 {
3413 using BaseT = MaskIterT<false>;
3414 const InternalNode* mParent;
3415
3416 public:
3418 : BaseT()
3419 , mParent(nullptr)
3420 {
3421 }
3423 : BaseT(parent->data()->mChildMask.beginOff())
3424 , mParent(parent)
3425 {
3426 }
3429 {
3430 NANOVDB_ASSERT(*this);
3431 return mParent->data()->getValue(BaseT::pos());
3432 }
3434 {
3435 NANOVDB_ASSERT(*this);
3436 return mParent->offsetToGlobalCoord(BaseT::pos());
3437 }
3438 __hostdev__ CoordType getCoord() const {return this->getOrigin();}
3440 {
3441 NANOVDB_ASSERT(*this);
3442 return mParent->data()->isActive(BaseT::mPos);
3443 }
3444 }; // Member class ValueIterator
3445
3446 __hostdev__ ValueIterator beginValue() const { return ValueIterator(this); }
3447 __hostdev__ ValueIterator cbeginValueAll() const { return ValueIterator(this); }
3448
3449 /// @brief Visits active tile values of this node only
3450 class ValueOnIterator : public MaskIterT<true>
3451 {
3452 using BaseT = MaskIterT<true>;
3453 const InternalNode* mParent;
3454
3455 public:
3457 : BaseT()
3458 , mParent(nullptr)
3459 {
3460 }
3462 : BaseT(parent->data()->mValueMask.beginOn())
3463 , mParent(parent)
3464 {
3465 }
3468 {
3469 NANOVDB_ASSERT(*this);
3470 return mParent->data()->getValue(BaseT::pos());
3471 }
3473 {
3474 NANOVDB_ASSERT(*this);
3475 return mParent->offsetToGlobalCoord(BaseT::pos());
3476 }
3477 __hostdev__ CoordType getCoord() const {return this->getOrigin();}
3478 }; // Member class ValueOnIterator
3479
3480 __hostdev__ ValueOnIterator beginValueOn() const { return ValueOnIterator(this); }
3481 __hostdev__ ValueOnIterator cbeginValueOn() const { return ValueOnIterator(this); }
3482
3483 /// @brief Visits all tile values and child nodes of this node
3484 class DenseIterator : public Mask<Log2Dim>::DenseIterator
3485 {
3486 using BaseT = typename Mask<Log2Dim>::DenseIterator;
3487 const DataType* mParent;
3488
3489 public:
3491 : BaseT()
3492 , mParent(nullptr)
3493 {
3494 }
3496 : BaseT(0)
3497 , mParent(parent->data())
3498 {
3499 }
3501 __hostdev__ const ChildT* probeChild(ValueType& value) const
3502 {
3503 NANOVDB_ASSERT(mParent && bool(*this));
3504 const ChildT* child = nullptr;
3505 if (mParent->mChildMask.isOn(BaseT::pos())) {
3506 child = mParent->getChild(BaseT::pos());
3507 } else {
3508 value = mParent->getValue(BaseT::pos());
3509 }
3510 return child;
3511 }
3513 {
3514 NANOVDB_ASSERT(mParent && bool(*this));
3515 return mParent->isActive(BaseT::pos());
3516 }
3518 {
3519 NANOVDB_ASSERT(mParent && bool(*this));
3520 return mParent->offsetToGlobalCoord(BaseT::pos());
3521 }
3522 __hostdev__ CoordType getCoord() const {return this->getOrigin();}
3523 }; // Member class DenseIterator
3524
3525 __hostdev__ DenseIterator beginDense() const { return DenseIterator(this); }
3526 __hostdev__ DenseIterator cbeginChildAll() const { return DenseIterator(this); } // matches openvdb
3527
3528 /// @brief This class cannot be constructed or deleted
3529 InternalNode() = delete;
3530 InternalNode(const InternalNode&) = delete;
3532 ~InternalNode() = delete;
3533
3534 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
3535
3536 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
3537
3538 /// @brief Return the dimension, in voxel units, of this internal node (typically 8*16 or 8*16*32)
3539 __hostdev__ static uint32_t dim() { return 1u << TOTAL; }
3540
3541 /// @brief Return memory usage in bytes for the class
3542 __hostdev__ static size_t memUsage() { return DataType::memUsage(); }
3543
3544 /// @brief Return a const reference to the bit mask of active voxels in this internal node
3547
3548 /// @brief Return a const reference to the bit mask of child nodes in this internal node
3551
3552 /// @brief Return the origin in index space of this leaf node
3554
3555 /// @brief Return a const reference to the minimum active value encoded in this internal node and any of its child nodes
3556 __hostdev__ const ValueType& minimum() const { return this->getMin(); }
3557
3558 /// @brief Return a const reference to the maximum active value encoded in this internal node and any of its child nodes
3559 __hostdev__ const ValueType& maximum() const { return this->getMax(); }
3560
3561 /// @brief Return a const reference to the average of all the active values encoded in this internal node and any of its child nodes
3563
3564 /// @brief Return the variance of all the active values encoded in this internal node and any of its child nodes
3566
3567 /// @brief Return a const reference to the standard deviation of all the active values encoded in this internal node and any of its child nodes
3569
3570 /// @brief Return a const reference to the bounding box in index space of active values in this internal node and any of its child nodes
3572
3573 /// @brief If the first entry in this node's table is a tile, return the tile's value.
3574 /// Otherwise, return the result of calling getFirstValue() on the child.
3576 {
3577 return DataType::mChildMask.isOn(0) ? this->getChild(0)->getFirstValue() : DataType::getValue(0);
3578 }
3579
3580 /// @brief If the last entry in this node's table is a tile, return the tile's value.
3581 /// Otherwise, return the result of calling getLastValue() on the child.
3583 {
3584 return DataType::mChildMask.isOn(SIZE - 1) ? this->getChild(SIZE - 1)->getLastValue() : DataType::getValue(SIZE - 1);
3585 }
3586
3587 /// @brief Return the value of the given voxel
3588 __hostdev__ ValueType getValue(const CoordType& ijk) const { return this->template get<GetValue<BuildType>>(ijk); }
3589 __hostdev__ bool isActive(const CoordType& ijk) const { return this->template get<GetState<BuildType>>(ijk); }
3590 /// @brief return the state and updates the value of the specified voxel
3591 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->template get<ProbeValue<BuildType>>(ijk, v); }
3592 __hostdev__ const LeafNodeType* probeLeaf(const CoordType& ijk) const { return this->template get<GetLeaf<BuildType>>(ijk); }
3593
3595 {
3596 const uint32_t n = CoordToOffset(ijk);
3597 return DataType::mChildMask.isOn(n) ? this->getChild(n) : nullptr;
3598 }
3600 {
3601 const uint32_t n = CoordToOffset(ijk);
3602 return DataType::mChildMask.isOn(n) ? this->getChild(n) : nullptr;
3603 }
3604
3605 /// @brief Return the linear offset corresponding to the given coordinate
3606 __hostdev__ static uint32_t CoordToOffset(const CoordType& ijk)
3607 {
3608 return (((ijk[0] & MASK) >> ChildT::TOTAL) << (2 * LOG2DIM)) | // note, we're using bitwise OR instead of +
3609 (((ijk[1] & MASK) >> ChildT::TOTAL) << (LOG2DIM)) |
3610 ((ijk[2] & MASK) >> ChildT::TOTAL);
3611 }
3612
3613 /// @return the local coordinate of the n'th tile or child node
3615 {
3616 NANOVDB_ASSERT(n < SIZE);
3617 const uint32_t m = n & ((1 << 2 * LOG2DIM) - 1);
3618 return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & ((1 << LOG2DIM) - 1));
3619 }
3620
3621 /// @brief modifies local coordinates to global coordinates of a tile or child node
3623 {
3624 ijk <<= ChildT::TOTAL;
3625 ijk += this->origin();
3626 }
3627
3629 {
3631 this->localToGlobalCoord(ijk);
3632 return ijk;
3633 }
3634
3635 /// @brief Return true if this node or any of its child nodes contain active values
3636 __hostdev__ bool isActive() const { return DataType::mFlags & uint32_t(2); }
3637
3638 template<typename OpT, typename... ArgsT>
3639 __hostdev__ typename OpT::Type get(const CoordType& ijk, ArgsT&&... args) const
3640 {
3641 const uint32_t n = CoordToOffset(ijk);
3642 if constexpr(OpT::LEVEL < LEVEL) if (this->isChild(n)) return this->getChild(n)->template get<OpT>(ijk, args...);
3643 return OpT::get(*this, n, args...);
3644 }
3645
3646 template<typename OpT, typename... ArgsT>
3647 __hostdev__ void set(const CoordType& ijk, ArgsT&&... args)
3648 {
3649 const uint32_t n = CoordToOffset(ijk);
3650 if constexpr(OpT::LEVEL < LEVEL) if (this->isChild(n)) return this->getChild(n)->template set<OpT>(ijk, args...);
3651 return OpT::set(*this, n, args...);
3652 }
3653
3654private:
3655 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(InternalData) is misaligned");
3656
3657 template<typename, int, int, int>
3658 friend class ReadAccessor;
3659
3660 template<typename>
3661 friend class RootNode;
3662 template<typename, uint32_t>
3663 friend class InternalNode;
3664
3665 template<typename RayT, typename AccT>
3666 __hostdev__ uint32_t getDimAndCache(const CoordType& ijk, const RayT& ray, const AccT& acc) const
3667 {
3668 if (DataType::mFlags & uint32_t(1u))
3669 return this->dim(); // skip this node if the 1st bit is set
3670 //if (!ray.intersects( this->bbox() )) return 1<<TOTAL;
3671
3672 const uint32_t n = CoordToOffset(ijk);
3673 if (DataType::mChildMask.isOn(n)) {
3674 const ChildT* child = this->getChild(n);
3675 acc.insert(ijk, child);
3676 return child->getDimAndCache(ijk, ray, acc);
3677 }
3678 return ChildNodeType::dim(); // tile value
3679 }
3680
3681 /// @brief Returns dim and active state in one traversal. On a skip flag,
3682 /// ActiveExact resolves the true active state but returns this node's dim;
3683 /// ActiveOnLeafOnly returns {dim, false} immediately. Without a skip flag
3684 /// both policies are identical. See GridStats::setFlag.
3685 template<typename Policy = ActiveExact, typename RayT, typename AccT>
3686 __hostdev__ DimAndActive getDimAndActiveAndCache(const CoordType& ijk, const RayT& ray, const AccT& acc) const
3687 {
3688 //if (!ray.intersects( this->bbox() )) return {1<<TOTAL, ...};
3689 // Separate paths keep `skip` out of ActiveOnLeafOnly's recursion,
3690 // saving ~2 registers/thread and avoiding an occupancy cliff.
3691 if constexpr (util::is_same<Policy, ActiveOnLeafOnly>::value) {
3692 if (DataType::mFlags & uint32_t(1u))
3693 return {this->dim(), false}; // active unspecified per policy
3694 const uint32_t n = CoordToOffset(ijk);
3695 if (DataType::mChildMask.isOn(n)) {
3696 const ChildT* child = this->getChild(n);
3697 acc.insert(ijk, child);
3698 return child->template getDimAndActiveAndCache<Policy>(ijk, ray, acc);
3699 }
3700 return {ChildNodeType::dim(), DataType::mValueMask.isOn(n)};
3701 } else {
3702 const bool skip = (DataType::mFlags & uint32_t(1u));
3703 const uint32_t n = CoordToOffset(ijk);
3704 if (DataType::mChildMask.isOn(n)) {
3705 const ChildT* child = this->getChild(n);
3706 acc.insert(ijk, child);
3707 const auto r = child->template getDimAndActiveAndCache<Policy>(ijk, ray, acc);
3708 return {skip ? this->dim() : r.dim(), r.active()};
3709 }
3710 return {skip ? this->dim() : ChildNodeType::dim(), DataType::mValueMask.isOn(n)};
3711 }
3712 }
3713
3714 template<typename OpT, typename AccT, typename... ArgsT>
3715 __hostdev__ typename OpT::Type getAndCache(const CoordType& ijk, const AccT& acc, ArgsT&&... args) const
3716 {
3717 const uint32_t n = CoordToOffset(ijk);
3718 if constexpr(OpT::LEVEL < LEVEL) {
3719 if (this->isChild(n)) {
3720 const ChildT* child = this->getChild(n);
3721 acc.insert(ijk, child);
3722 return child->template getAndCache<OpT>(ijk, acc, args...);
3723 }
3724 }
3725 return OpT::get(*this, n, args...);
3726 }
3727
3728 template<typename OpT, typename AccT, typename... ArgsT>
3729 __hostdev__ void setAndCache(const CoordType& ijk, const AccT& acc, ArgsT&&... args)
3730 {
3731 const uint32_t n = CoordToOffset(ijk);
3732 if constexpr(OpT::LEVEL < LEVEL) {
3733 if (this->isChild(n)) {
3734 ChildT* child = this->getChild(n);
3735 acc.insert(ijk, child);
3736 return child->template setAndCache<OpT>(ijk, acc, args...);
3737 }
3738 }
3739 return OpT::set(*this, n, args...);
3740 }
3741
3742}; // InternalNode class
3743
3744// --------------------------> LeafData<T> <------------------------------------
3745
3746/// @brief Stuct with all the member data of the LeafNode (useful during serialization of an openvdb LeafNode)
3747///
3748/// @note No client code should (or can) interface with this struct so it can safely be ignored!
3749template<typename ValueT, typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3750struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData
3751{
3752 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
3753 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
3754 using ValueType = ValueT;
3755 using BuildType = ValueT;
3757 using ArrayType = ValueT; // type used for the internal mValue array
3758 static constexpr bool FIXED_SIZE = true;
3759
3760 CoordT mBBoxMin; // 12B.
3761 uint8_t mBBoxDif[3]; // 3B.
3762 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: has stats, bits5,6,7: bit-width for FpN
3763 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
3764
3765 ValueType mMinimum; // typically 4B
3766 ValueType mMaximum; // typically 4B
3767 FloatType mAverage; // typically 4B, average of all the active values in this node and its child nodes
3768 FloatType mStdDevi; // typically 4B, standard deviation of all the active values in this node and its child nodes
3769 alignas(32) ValueType mValues[1u << 3 * LOG2DIM];
3770
3771 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
3772 ///
3773 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
3774 __hostdev__ static constexpr uint32_t padding()
3775 {
3776 return sizeof(LeafData) - (12 + 3 + 1 + sizeof(MaskT<LOG2DIM>) + 2 * (sizeof(ValueT) + sizeof(FloatType)) + (1u << (3 * LOG2DIM)) * sizeof(ValueT));
3777 }
3778 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
3779
3780 __hostdev__ static bool hasStats() { return true; }
3781
3782 __hostdev__ ValueType getValue(uint32_t i) const { return mValues[i]; }
3783 __hostdev__ void setValueOnly(uint32_t offset, const ValueType& value) { mValues[offset] = value; }
3784 __hostdev__ void setValue(uint32_t offset, const ValueType& value)
3785 {
3786 mValueMask.setOn(offset);
3787 mValues[offset] = value;
3788 }
3789 __hostdev__ void setOn(uint32_t offset) { mValueMask.setOn(offset); }
3790
3795
3796// GCC 11 (and possibly prior versions) has a regression that results in invalid
3797// warnings when -Wstringop-overflow is turned on. For details, refer to
3798// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101854
3799#if defined(__GNUC__) && (__GNUC__ < 12) && !defined(__APPLE__) && !defined(__llvm__)
3800#pragma GCC diagnostic push
3801#pragma GCC diagnostic ignored "-Wstringop-overflow"
3802#endif
3803 __hostdev__ void setMin(const ValueType& v) { mMinimum = v; }
3804 __hostdev__ void setMax(const ValueType& v) { mMaximum = v; }
3805 __hostdev__ void setAvg(const FloatType& v) { mAverage = v; }
3806 __hostdev__ void setDev(const FloatType& v) { mStdDevi = v; }
3807#if defined(__GNUC__) && (__GNUC__ < 12) && !defined(__APPLE__) && !defined(__llvm__)
3808#pragma GCC diagnostic pop
3809#endif
3810
3811 template<typename T>
3812 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
3813
3815 {
3816 for (auto *p = mValues, *q = p + 512; p != q; ++p)
3817 *p = v;
3818 }
3819
3820 /// @brief This class cannot be constructed or deleted
3821 LeafData() = delete;
3822 LeafData(const LeafData&) = delete;
3823 LeafData& operator=(const LeafData&) = delete;
3824 ~LeafData() = delete;
3825}; // LeafData<ValueT>
3826
3827// --------------------------> LeafFnBase <------------------------------------
3828
3829/// @brief Base-class for quantized float leaf nodes
3830template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3831struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafFnBase
3832{
3833 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
3834 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
3835 using ValueType = float;
3836 using FloatType = float;
3837
3838 CoordT mBBoxMin; // 12B.
3839 uint8_t mBBoxDif[3]; // 3B.
3840 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: has stats, bits5,6,7: bit-width for FpN
3841 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
3842
3843 float mMinimum; // 4B - minimum of ALL values in this node
3844 float mQuantum; // = (max - min)/15 4B
3845 uint16_t mMin, mMax, mAvg, mDev; // quantized representations of statistics of active values
3846 // no padding since it's always 32B aligned
3847 __hostdev__ static uint64_t memUsage() { return sizeof(LeafFnBase); }
3848
3849 __hostdev__ static bool hasStats() { return true; }
3850
3851 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
3852 ///
3853 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
3854 __hostdev__ static constexpr uint32_t padding()
3855 {
3856 return sizeof(LeafFnBase) - (12 + 3 + 1 + sizeof(MaskT<LOG2DIM>) + 2 * 4 + 4 * 2);
3857 }
3858 __hostdev__ void init(float min, float max, uint8_t bitWidth)
3859 {
3860 mMinimum = min;
3861 mQuantum = (max - min) / float((1 << bitWidth) - 1);
3862 }
3863
3864 __hostdev__ void setOn(uint32_t offset) { mValueMask.setOn(offset); }
3865
3866 /// @brief return the quantized minimum of the active values in this node
3867 __hostdev__ float getMin() const { return mMin * mQuantum + mMinimum; }
3868
3869 /// @brief return the quantized maximum of the active values in this node
3870 __hostdev__ float getMax() const { return mMax * mQuantum + mMinimum; }
3871
3872 /// @brief return the quantized average of the active values in this node
3873 __hostdev__ float getAvg() const { return mAvg * mQuantum + mMinimum; }
3874 /// @brief return the quantized standard deviation of the active values in this node
3875
3876 /// @note 0 <= StdDev <= max-min or 0 <= StdDev/(max-min) <= 1
3877 __hostdev__ float getDev() const { return mDev * mQuantum; }
3878
3879 /// @note min <= X <= max or 0 <= (X-min)/(min-max) <= 1
3880 __hostdev__ void setMin(float min) { mMin = uint16_t((min - mMinimum) / mQuantum + 0.5f); }
3881
3882 /// @note min <= X <= max or 0 <= (X-min)/(min-max) <= 1
3883 __hostdev__ void setMax(float max) { mMax = uint16_t((max - mMinimum) / mQuantum + 0.5f); }
3884
3885 /// @note min <= avg <= max or 0 <= (avg-min)/(min-max) <= 1
3886 __hostdev__ void setAvg(float avg) { mAvg = uint16_t((avg - mMinimum) / mQuantum + 0.5f); }
3887
3888 /// @note 0 <= StdDev <= max-min or 0 <= StdDev/(max-min) <= 1
3889 __hostdev__ void setDev(float dev) { mDev = uint16_t(dev / mQuantum + 0.5f); }
3890
3891 template<typename T>
3892 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
3893}; // LeafFnBase
3894
3895// --------------------------> LeafData<Fp4> <------------------------------------
3896
3897/// @brief Stuct with all the member data of the LeafNode (useful during serialization of an openvdb LeafNode)
3898///
3899/// @note No client code should (or can) interface with this struct so it can safely be ignored!
3900template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3901struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<Fp4, CoordT, MaskT, LOG2DIM>
3902 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
3903{
3906 using ArrayType = uint8_t; // type used for the internal mValue array
3907 static constexpr bool FIXED_SIZE = true;
3908 alignas(32) uint8_t mCode[1u << (3 * LOG2DIM - 1)]; // LeafFnBase is 32B aligned and so is mCode
3909
3910 __hostdev__ static constexpr uint64_t memUsage() { return sizeof(LeafData); }
3911 __hostdev__ static constexpr uint32_t padding()
3912 {
3913 static_assert(BaseT::padding() == 0, "expected no padding in LeafFnBase");
3914 return sizeof(LeafData) - sizeof(BaseT) - (1u << (3 * LOG2DIM - 1));
3915 }
3916
3917 __hostdev__ static constexpr uint8_t bitWidth() { return 4u; }
3918 __hostdev__ float getValue(uint32_t i) const
3919 {
3920#if 0
3921 const uint8_t c = mCode[i>>1];
3922 return ( (i&1) ? c >> 4 : c & uint8_t(15) )*BaseT::mQuantum + BaseT::mMinimum;
3923#else
3924 return ((mCode[i >> 1] >> ((i & 1) << 2)) & uint8_t(15)) * BaseT::mQuantum + BaseT::mMinimum;
3925#endif
3926 }
3927
3928 /// @brief This class cannot be constructed or deleted
3929 LeafData() = delete;
3930 LeafData(const LeafData&) = delete;
3931 LeafData& operator=(const LeafData&) = delete;
3932 ~LeafData() = delete;
3933}; // LeafData<Fp4>
3934
3935// --------------------------> LeafBase<Fp8> <------------------------------------
3936
3937template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3938struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<Fp8, CoordT, MaskT, LOG2DIM>
3939 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
3940{
3943 using ArrayType = uint8_t; // type used for the internal mValue array
3944 static constexpr bool FIXED_SIZE = true;
3945 alignas(32) uint8_t mCode[1u << 3 * LOG2DIM];
3946 __hostdev__ static constexpr int64_t memUsage() { return sizeof(LeafData); }
3947 __hostdev__ static constexpr uint32_t padding()
3948 {
3949 static_assert(BaseT::padding() == 0, "expected no padding in LeafFnBase");
3950 return sizeof(LeafData) - sizeof(BaseT) - (1u << 3 * LOG2DIM);
3951 }
3952
3953 __hostdev__ static constexpr uint8_t bitWidth() { return 8u; }
3954 __hostdev__ float getValue(uint32_t i) const
3955 {
3956 return mCode[i] * BaseT::mQuantum + BaseT::mMinimum; // code * (max-min)/255 + min
3957 }
3958 /// @brief This class cannot be constructed or deleted
3959 LeafData() = delete;
3960 LeafData(const LeafData&) = delete;
3961 LeafData& operator=(const LeafData&) = delete;
3962 ~LeafData() = delete;
3963}; // LeafData<Fp8>
3964
3965// --------------------------> LeafData<Fp16> <------------------------------------
3966
3967template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3968struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<Fp16, CoordT, MaskT, LOG2DIM>
3969 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
3970{
3973 using ArrayType = uint16_t; // type used for the internal mValue array
3974 static constexpr bool FIXED_SIZE = true;
3975 alignas(32) uint16_t mCode[1u << 3 * LOG2DIM];
3976
3977 __hostdev__ static constexpr uint64_t memUsage() { return sizeof(LeafData); }
3978 __hostdev__ static constexpr uint32_t padding()
3979 {
3980 static_assert(BaseT::padding() == 0, "expected no padding in LeafFnBase");
3981 return sizeof(LeafData) - sizeof(BaseT) - 2 * (1u << 3 * LOG2DIM);
3982 }
3983
3984 __hostdev__ static constexpr uint8_t bitWidth() { return 16u; }
3985 __hostdev__ float getValue(uint32_t i) const
3986 {
3987 return mCode[i] * BaseT::mQuantum + BaseT::mMinimum; // code * (max-min)/65535 + min
3988 }
3989
3990 /// @brief This class cannot be constructed or deleted
3991 LeafData() = delete;
3992 LeafData(const LeafData&) = delete;
3993 LeafData& operator=(const LeafData&) = delete;
3994 ~LeafData() = delete;
3995}; // LeafData<Fp16>
3996
3997// --------------------------> LeafData<FpN> <------------------------------------
3998
3999template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4000struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<FpN, CoordT, MaskT, LOG2DIM>
4001 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
4002{ // this class has no additional data members, however every instance is immediately followed by
4003 // bitWidth*64 bytes. Since its base class is 32B aligned so are the bitWidth*64 bytes
4006 static constexpr bool FIXED_SIZE = false;
4007 __hostdev__ static constexpr uint32_t padding()
4008 {
4009 static_assert(BaseT::padding() == 0, "expected no padding in LeafFnBase");
4010 return 0;
4011 }
4012
4013 __hostdev__ uint8_t bitWidth() const { return 1 << (BaseT::mFlags >> 5); } // 4,8,16,32 = 2^(2,3,4,5)
4014 __hostdev__ size_t memUsage() const { return sizeof(*this) + this->bitWidth() * 64; }
4015 __hostdev__ static size_t memUsage(uint32_t bitWidth) { return 96u + bitWidth * 64; }
4016 __hostdev__ float getValue(uint32_t i) const
4017 {
4018#ifdef NANOVDB_FPN_BRANCHLESS // faster
4019 const int b = BaseT::mFlags >> 5; // b = 0, 1, 2, 3, 4 corresponding to 1, 2, 4, 8, 16 bits
4020#if 0 // use LUT
4021 uint16_t code = reinterpret_cast<const uint16_t*>(this + 1)[i >> (4 - b)];
4022 const static uint8_t shift[5] = {15, 7, 3, 1, 0};
4023 const static uint16_t mask[5] = {1, 3, 15, 255, 65535};
4024 code >>= (i & shift[b]) << b;
4025 code &= mask[b];
4026#else // no LUT
4027 uint32_t code = reinterpret_cast<const uint32_t*>(this + 1)[i >> (5 - b)];
4028 code >>= (i & ((32 >> b) - 1)) << b;
4029 code &= (1 << (1 << b)) - 1;
4030#endif
4031#else // use branched version (slow)
4032 float code;
4033 auto* values = reinterpret_cast<const uint8_t*>(this + 1);
4034 switch (BaseT::mFlags >> 5) {
4035 case 0u: // 1 bit float
4036 code = float((values[i >> 3] >> (i & 7)) & uint8_t(1));
4037 break;
4038 case 1u: // 2 bits float
4039 code = float((values[i >> 2] >> ((i & 3) << 1)) & uint8_t(3));
4040 break;
4041 case 2u: // 4 bits float
4042 code = float((values[i >> 1] >> ((i & 1) << 2)) & uint8_t(15));
4043 break;
4044 case 3u: // 8 bits float
4045 code = float(values[i]);
4046 break;
4047 default: // 16 bits float
4048 code = float(reinterpret_cast<const uint16_t*>(values)[i]);
4049 }
4050#endif
4051 return float(code) * BaseT::mQuantum + BaseT::mMinimum; // code * (max-min)/UNITS + min
4052 }
4053
4054 /// @brief This class cannot be constructed or deleted
4055 LeafData() = delete;
4056 LeafData(const LeafData&) = delete;
4057 LeafData& operator=(const LeafData&) = delete;
4058 ~LeafData() = delete;
4059}; // LeafData<FpN>
4060
4061// --------------------------> LeafData<bool> <------------------------------------
4062
4063// Partial template specialization of LeafData with bool
4064template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4065struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<bool, CoordT, MaskT, LOG2DIM>
4066{
4067 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
4068 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
4069 using ValueType = bool;
4070 using BuildType = bool;
4071 using FloatType = bool; // dummy value type
4072 using ArrayType = MaskT<LOG2DIM>; // type used for the internal mValue array
4073 static constexpr bool FIXED_SIZE = true;
4074
4075 CoordT mBBoxMin; // 12B.
4076 uint8_t mBBoxDif[3]; // 3B.
4077 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: has stats, bits5,6,7: bit-width for FpN
4078 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
4079 MaskT<LOG2DIM> mValues; // LOG2DIM(3): 64B.
4080 uint64_t mPadding[2]; // 16B padding to 32B alignment
4081
4082 __hostdev__ static constexpr uint32_t padding() { return sizeof(LeafData) - 12u - 3u - 1u - 2 * sizeof(MaskT<LOG2DIM>) - 16u; }
4083 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
4084 __hostdev__ static bool hasStats() { return false; }
4085 __hostdev__ bool getValue(uint32_t i) const { return mValues.isOn(i); }
4086 __hostdev__ bool getMin() const { return false; } // dummy
4087 __hostdev__ bool getMax() const { return false; } // dummy
4088 __hostdev__ bool getAvg() const { return false; } // dummy
4089 __hostdev__ bool getDev() const { return false; } // dummy
4090 __hostdev__ void setValue(uint32_t offset, bool v)
4091 {
4092 mValueMask.setOn(offset);
4093 mValues.set(offset, v);
4094 }
4095 __hostdev__ void setOn(uint32_t offset) { mValueMask.setOn(offset); }
4096 __hostdev__ void setMin(const bool&) {} // no-op
4097 __hostdev__ void setMax(const bool&) {} // no-op
4098 __hostdev__ void setAvg(const bool&) {} // no-op
4099 __hostdev__ void setDev(const bool&) {} // no-op
4100
4101 template<typename T>
4102 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
4103
4104 /// @brief This class cannot be constructed or deleted
4105 LeafData() = delete;
4106 LeafData(const LeafData&) = delete;
4107 LeafData& operator=(const LeafData&) = delete;
4108 ~LeafData() = delete;
4109}; // LeafData<bool>
4110
4111// --------------------------> LeafData<ValueMask> <------------------------------------
4112
4113// Partial template specialization of LeafData with ValueMask
4114template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4115struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<ValueMask, CoordT, MaskT, LOG2DIM>
4116{
4117 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
4118 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
4119 using ValueType = bool;
4121 using FloatType = bool; // dummy value type
4122 using ArrayType = void; // type used for the internal mValue array - void means missing
4123 static constexpr bool FIXED_SIZE = true;
4124
4125 CoordT mBBoxMin; // 12B.
4126 uint8_t mBBoxDif[3]; // 3B.
4127 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: has stats, bits5,6,7: bit-width for FpN
4128 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
4129 uint64_t mPadding[2]; // 16B padding to 32B alignment
4130
4131 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
4132 __hostdev__ static bool hasStats() { return false; }
4133 __hostdev__ static constexpr uint32_t padding()
4134 {
4135 return sizeof(LeafData) - (12u + 3u + 1u + sizeof(MaskT<LOG2DIM>) + 2 * 8u);
4136 }
4137
4138 __hostdev__ bool getValue(uint32_t i) const { return mValueMask.isOn(i); }
4139 __hostdev__ bool getMin() const { return false; } // dummy
4140 __hostdev__ bool getMax() const { return false; } // dummy
4141 __hostdev__ bool getAvg() const { return false; } // dummy
4142 __hostdev__ bool getDev() const { return false; } // dummy
4143 __hostdev__ void setValue(uint32_t offset, bool) { mValueMask.setOn(offset); }
4144 __hostdev__ void setOn(uint32_t offset) { mValueMask.setOn(offset); }
4145 __hostdev__ void setMin(const ValueType&) {} // no-op
4146 __hostdev__ void setMax(const ValueType&) {} // no-op
4147 __hostdev__ void setAvg(const FloatType&) {} // no-op
4148 __hostdev__ void setDev(const FloatType&) {} // no-op
4149
4150 template<typename T>
4151 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
4152
4153 /// @brief This class cannot be constructed or deleted
4154 LeafData() = delete;
4155 LeafData(const LeafData&) = delete;
4156 LeafData& operator=(const LeafData&) = delete;
4157 ~LeafData() = delete;
4158}; // LeafData<ValueMask>
4159
4160// --------------------------> LeafIndexBase <------------------------------------
4161
4162// Partial template specialization of LeafData with ValueIndex
4163template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4164struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafIndexBase
4165{
4166 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
4167 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
4168 using ValueType = uint64_t;
4169 using FloatType = uint64_t;
4170 using ArrayType = void; // type used for the internal mValue array - void means missing
4171 static constexpr bool FIXED_SIZE = true;
4172
4173 CoordT mBBoxMin; // 12B.
4174 uint8_t mBBoxDif[3]; // 3B.
4175 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: has stats, bits5,6,7: bit-width for FpN
4176 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
4177 uint64_t mOffset, mPrefixSum; // 8B offset to first value in this leaf node and 9-bit prefix sum
4178 __hostdev__ static constexpr uint32_t padding()
4179 {
4180 return sizeof(LeafIndexBase) - (12u + 3u + 1u + sizeof(MaskT<LOG2DIM>) + 2 * 8u);
4181 }
4182 __hostdev__ static uint64_t memUsage() { return sizeof(LeafIndexBase); }
4183 __hostdev__ bool hasStats() const { return mFlags & (uint8_t(1) << 4); }
4184 // return the offset to the first value indexed by this leaf node
4185 __hostdev__ const uint64_t& firstOffset() const { return mOffset; }
4186 __hostdev__ void setMin(const ValueType&) {} // no-op
4187 __hostdev__ void setMax(const ValueType&) {} // no-op
4188 __hostdev__ void setAvg(const FloatType&) {} // no-op
4189 __hostdev__ void setDev(const FloatType&) {} // no-op
4190 __hostdev__ void setOn(uint32_t offset) { mValueMask.setOn(offset); }
4191 template<typename T>
4192 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
4193
4194protected:
4195 /// @brief This class should be used as an abstract class and only constructed or deleted via child classes
4196 LeafIndexBase() = default;
4197 LeafIndexBase(const LeafIndexBase&) = default;
4199 ~LeafIndexBase() = default;
4200}; // LeafIndexBase
4201
4202// --------------------------> LeafData<ValueIndex> <------------------------------------
4203
4204// Partial template specialization of LeafData with ValueIndex
4205template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4206struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<ValueIndex, CoordT, MaskT, LOG2DIM>
4207 : public LeafIndexBase<CoordT, MaskT, LOG2DIM>
4208{
4211 // return the total number of values indexed by this leaf node, excluding the optional 4 stats
4212 __hostdev__ static uint32_t valueCount() { return uint32_t(512); } // 8^3 = 2^9
4213 // return the offset to the last value indexed by this leaf node (disregarding optional stats)
4214 __hostdev__ uint64_t lastOffset() const { return BaseT::mOffset + 511u; } // 2^9 - 1
4215 // if stats are available, they are always placed after the last voxel value in this leaf node
4216 __hostdev__ uint64_t getMin() const { return this->hasStats() ? BaseT::mOffset + 512u : 0u; }
4217 __hostdev__ uint64_t getMax() const { return this->hasStats() ? BaseT::mOffset + 513u : 0u; }
4218 __hostdev__ uint64_t getAvg() const { return this->hasStats() ? BaseT::mOffset + 514u : 0u; }
4219 __hostdev__ uint64_t getDev() const { return this->hasStats() ? BaseT::mOffset + 515u : 0u; }
4220 __hostdev__ uint64_t getValue(uint32_t i) const { return BaseT::mOffset + i; } // dense leaf node with active and inactive voxels
4221}; // LeafData<ValueIndex>
4222
4223// --------------------------> LeafData<ValueOnIndex> <------------------------------------
4224
4225template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4226struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<ValueOnIndex, CoordT, MaskT, LOG2DIM>
4227 : public LeafIndexBase<CoordT, MaskT, LOG2DIM>
4228{
4231 __hostdev__ uint32_t valueCount() const
4232 {
4233 return util::countOn(BaseT::mValueMask.words()[7]) + (BaseT::mPrefixSum >> 54u & 511u); // last 9 bits of mPrefixSum do not account for the last word in mValueMask
4234 }
4235 __hostdev__ uint64_t lastOffset() const { return BaseT::mOffset + this->valueCount() - 1u; }
4236 __hostdev__ uint64_t getMin() const { return this->hasStats() ? this->lastOffset() + 1u : 0u; }
4237 __hostdev__ uint64_t getMax() const { return this->hasStats() ? this->lastOffset() + 2u : 0u; }
4238 __hostdev__ uint64_t getAvg() const { return this->hasStats() ? this->lastOffset() + 3u : 0u; }
4239 __hostdev__ uint64_t getDev() const { return this->hasStats() ? this->lastOffset() + 4u : 0u; }
4240 __hostdev__ uint64_t getValue(uint32_t i) const
4241 {
4242 //return mValueMask.isOn(i) ? mOffset + mValueMask.countOn(i) : 0u;// for debugging
4243 uint32_t n = i >> 6;
4244 const uint64_t w = BaseT::mValueMask.words()[n], mask = uint64_t(1) << (i & 63u);
4245 if (!(w & mask)) return uint64_t(0); // if i'th value is inactive return offset to background value
4246 uint64_t sum = BaseT::mOffset + util::countOn(w & (mask - 1u));
4247 if (n--) sum += BaseT::mPrefixSum >> (9u * n) & 511u;
4248 return sum;
4249 }
4250}; // LeafData<ValueOnIndex>
4251
4252// --------------------------> LeafData<Point> <------------------------------------
4253
4254template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4255struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<Point, CoordT, MaskT, LOG2DIM>
4256{
4257 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
4258 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
4259 using ValueType = uint64_t;
4262 using ArrayType = uint16_t; // type used for the internal mValue array
4263 static constexpr bool FIXED_SIZE = true;
4264
4265 CoordT mBBoxMin; // 12B.
4266 uint8_t mBBoxDif[3]; // 3B.
4267 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: has stats, bits5,6,7: bit-width for FpN
4268 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
4269
4270 uint64_t mOffset; // 8B
4271 uint64_t mPointCount; // 8B
4272 alignas(32) uint16_t mValues[1u << 3 * LOG2DIM]; // 1KB
4273 // no padding
4274
4275 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
4276 ///
4277 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
4278 __hostdev__ static constexpr uint32_t padding()
4279 {
4280 return sizeof(LeafData) - (12u + 3u + 1u + sizeof(MaskT<LOG2DIM>) + 2 * 8u + (1u << 3 * LOG2DIM) * 2u);
4281 }
4282 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
4283
4284 __hostdev__ uint64_t offset() const { return mOffset; }
4285 __hostdev__ uint64_t pointCount() const { return mPointCount; }
4286 __hostdev__ uint64_t first(uint32_t i) const { return i ? uint64_t(mValues[i - 1u]) + mOffset : mOffset; }
4287 __hostdev__ uint64_t last(uint32_t i) const { return uint64_t(mValues[i]) + mOffset; }
4288 __hostdev__ uint64_t getValue(uint32_t i) const { return uint64_t(mValues[i]); }
4289 __hostdev__ void setValueOnly(uint32_t offset, uint16_t value) { mValues[offset] = value; }
4290 __hostdev__ void setValue(uint32_t offset, uint16_t value)
4291 {
4292 mValueMask.setOn(offset);
4293 mValues[offset] = value;
4294 }
4295 __hostdev__ void setOn(uint32_t offset) { mValueMask.setOn(offset); }
4296
4299 __hostdev__ FloatType getAvg() const { return 0.0f; }
4300 __hostdev__ FloatType getDev() const { return 0.0f; }
4301
4306
4307 template<typename T>
4308 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
4309
4310 /// @brief This class cannot be constructed or deleted
4311 LeafData() = delete;
4312 LeafData(const LeafData&) = delete;
4313 LeafData& operator=(const LeafData&) = delete;
4314 ~LeafData() = delete;
4315}; // LeafData<Point>
4316
4317// --------------------------> LeafNode<T> <------------------------------------
4318
4319/// @brief Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
4320template<typename BuildT,
4321 typename CoordT = Coord,
4322 template<uint32_t> class MaskT = Mask,
4323 uint32_t Log2Dim = 3>
4324class LeafNode : public LeafData<BuildT, CoordT, MaskT, Log2Dim>
4325{
4326public:
4328 {
4329 static constexpr uint32_t TOTAL = 0;
4330 static constexpr uint32_t DIM = 1;
4331 __hostdev__ static uint32_t dim() { return 1u; }
4332 }; // Voxel
4338 using CoordType = CoordT;
4339 static constexpr bool FIXED_SIZE = DataType::FIXED_SIZE;
4340 template<uint32_t LOG2>
4341 using MaskType = MaskT<LOG2>;
4342 template<bool ON>
4343 using MaskIterT = typename Mask<Log2Dim>::template Iterator<ON>;
4344
4345 /// @brief Visits all active values in a leaf node
4346 class ValueOnIterator : public MaskIterT<true>
4347 {
4348 using BaseT = MaskIterT<true>;
4349 const LeafNode* mParent;
4350
4351 public:
4353 : BaseT()
4354 , mParent(nullptr)
4355 {
4356 }
4358 : BaseT(parent->data()->mValueMask.beginOn())
4359 , mParent(parent)
4360 {
4361 }
4364 {
4365 NANOVDB_ASSERT(*this);
4366 return mParent->getValue(BaseT::pos());
4367 }
4368 __hostdev__ CoordT getCoord() const
4369 {
4370 NANOVDB_ASSERT(*this);
4371 return mParent->offsetToGlobalCoord(BaseT::pos());
4372 }
4373 }; // Member class ValueOnIterator
4374
4375 __hostdev__ ValueOnIterator beginValueOn() const { return ValueOnIterator(this); }
4376 __hostdev__ ValueOnIterator cbeginValueOn() const { return ValueOnIterator(this); }
4377
4378 /// @brief Visits all inactive values in a leaf node
4379 class ValueOffIterator : public MaskIterT<false>
4380 {
4381 using BaseT = MaskIterT<false>;
4382 const LeafNode* mParent;
4383
4384 public:
4386 : BaseT()
4387 , mParent(nullptr)
4388 {
4389 }
4391 : BaseT(parent->data()->mValueMask.beginOff())
4392 , mParent(parent)
4393 {
4394 }
4397 {
4398 NANOVDB_ASSERT(*this);
4399 return mParent->getValue(BaseT::pos());
4400 }
4401 __hostdev__ CoordT getCoord() const
4402 {
4403 NANOVDB_ASSERT(*this);
4404 return mParent->offsetToGlobalCoord(BaseT::pos());
4405 }
4406 }; // Member class ValueOffIterator
4407
4408 __hostdev__ ValueOffIterator beginValueOff() const { return ValueOffIterator(this); }
4409 __hostdev__ ValueOffIterator cbeginValueOff() const { return ValueOffIterator(this); }
4410
4411 /// @brief Visits all values in a leaf node, i.e. both active and inactive values
4413 {
4414 const LeafNode* mParent;
4415 uint32_t mPos;
4416
4417 public:
4419 : mParent(nullptr)
4420 , mPos(1u << 3 * Log2Dim)
4421 {
4422 }
4424 : mParent(parent)
4425 , mPos(0)
4426 {
4427 NANOVDB_ASSERT(parent);
4428 }
4431 {
4432 NANOVDB_ASSERT(*this);
4433 return mParent->getValue(mPos);
4434 }
4435 __hostdev__ CoordT getCoord() const
4436 {
4437 NANOVDB_ASSERT(*this);
4438 return mParent->offsetToGlobalCoord(mPos);
4439 }
4441 {
4442 NANOVDB_ASSERT(*this);
4443 return mParent->isActive(mPos);
4444 }
4445 __hostdev__ operator bool() const { return mPos < (1u << 3 * Log2Dim); }
4447 {
4448 ++mPos;
4449 return *this;
4450 }
4452 {
4453 auto tmp = *this;
4454 ++(*this);
4455 return tmp;
4456 }
4457 }; // Member class ValueIterator
4458
4459 __hostdev__ ValueIterator beginValue() const { return ValueIterator(this); }
4460 __hostdev__ ValueIterator cbeginValueAll() const { return ValueIterator(this); }
4461
4462 static_assert(util::is_same<ValueType, typename BuildToValueMap<BuildType>::Type>::value, "Mismatching BuildType");
4463 static constexpr uint32_t LOG2DIM = Log2Dim;
4464 static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
4465 static constexpr uint32_t DIM = 1u << TOTAL; // number of voxels along each axis of this node
4466 static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
4467 static constexpr uint32_t MASK = (1u << LOG2DIM) - 1u; // mask for bit operations
4468 static constexpr uint32_t LEVEL = 0; // level 0 = leaf
4469 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
4470
4471 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
4472
4473 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
4474
4475 /// @brief Return a const reference to the bit mask of active voxels in this leaf node
4478
4479 /// @brief Return a const reference to the minimum active value encoded in this leaf node
4481
4482 /// @brief Return a const reference to the maximum active value encoded in this leaf node
4484
4485 /// @brief Return a const reference to the average of all the active values encoded in this leaf node
4487
4488 /// @brief Return the variance of all the active values encoded in this leaf node
4490
4491 /// @brief Return a const reference to the standard deviation of all the active values encoded in this leaf node
4493
4494 __hostdev__ uint8_t flags() const { return DataType::mFlags; }
4495
4496 /// @brief Return the origin in index space of this leaf node
4497 __hostdev__ CoordT origin() const { return DataType::mBBoxMin & ~MASK; }
4498
4499 /// @brief Compute the local coordinates from a linear offset
4500 /// @param n Linear offset into this nodes dense table
4501 /// @return Local (vs global) 3D coordinates
4502 __hostdev__ static CoordT OffsetToLocalCoord(uint32_t n)
4503 {
4504 NANOVDB_ASSERT(n < SIZE);
4505 const uint32_t m = n & ((1 << 2 * LOG2DIM) - 1);
4506 return CoordT(n >> 2 * LOG2DIM, m >> LOG2DIM, m & MASK);
4507 }
4508
4509 /// @brief Converts (in place) a local index coordinate to a global index coordinate
4510 __hostdev__ void localToGlobalCoord(Coord& ijk) const { ijk += this->origin(); }
4511
4512 __hostdev__ CoordT offsetToGlobalCoord(uint32_t n) const
4513 {
4514 return OffsetToLocalCoord(n) + this->origin();
4515 }
4516
4517 /// @brief Return the dimension, in index space, of this leaf node (typically 8 as for openvdb leaf nodes!)
4518 __hostdev__ static uint32_t dim() { return 1u << LOG2DIM; }
4519
4520 /// @brief Return the bounding box in index space of active values in this leaf node
4522 {
4524 if (this->hasBBox()) {
4525 bbox.max()[0] += DataType::mBBoxDif[0];
4526 bbox.max()[1] += DataType::mBBoxDif[1];
4527 bbox.max()[2] += DataType::mBBoxDif[2];
4528 } else { // very rare case
4529 bbox = math::BBox<CoordT>(); // invalid
4530 }
4531 return bbox;
4532 }
4533
4534 /// @brief Return the total number of voxels (e.g. values) encoded in this leaf node
4535 __hostdev__ static uint32_t voxelCount() { return 1u << (3 * LOG2DIM); }
4536
4537 __hostdev__ static uint32_t padding() { return DataType::padding(); }
4538
4539 /// @brief return memory usage in bytes for the leaf node
4540 __hostdev__ uint64_t memUsage() const { return DataType::memUsage(); }
4541
4542 /// @brief This class cannot be constructed or deleted
4543 LeafNode() = delete;
4544 LeafNode(const LeafNode&) = delete;
4545 LeafNode& operator=(const LeafNode&) = delete;
4546 ~LeafNode() = delete;
4547
4548 /// @brief Return the voxel value at the given offset.
4549 __hostdev__ ValueType getValue(uint32_t offset) const { return DataType::getValue(offset); }
4550
4551 /// @brief Return the voxel value at the given coordinate.
4552 __hostdev__ ValueType getValue(const CoordT& ijk) const { return DataType::getValue(CoordToOffset(ijk)); }
4553
4554 /// @brief Return the first value in this leaf node.
4555 __hostdev__ ValueType getFirstValue() const { return this->getValue(0); }
4556 /// @brief Return the last value in this leaf node.
4557 __hostdev__ ValueType getLastValue() const { return this->getValue(SIZE - 1); }
4558
4559 /// @brief Sets the value at the specified location and activate its state.
4560 ///
4561 /// @note This is safe since it does not change the topology of the tree (unlike setValue methods on the other nodes)
4562 __hostdev__ void setValue(const CoordT& ijk, const ValueType& v) { DataType::setValue(CoordToOffset(ijk), v); }
4563
4564 /// @brief Sets the value at the specified location but leaves its state unchanged.
4565 ///
4566 /// @note This is safe since it does not change the topology of the tree (unlike setValue methods on the other nodes)
4567 __hostdev__ void setValueOnly(uint32_t offset, const ValueType& v) { DataType::setValueOnly(offset, v); }
4568 __hostdev__ void setValueOnly(const CoordT& ijk, const ValueType& v) { DataType::setValueOnly(CoordToOffset(ijk), v); }
4569
4570 /// @brief Return @c true if the voxel value at the given coordinate is active.
4571 __hostdev__ bool isActive(const CoordT& ijk) const { return DataType::mValueMask.isOn(CoordToOffset(ijk)); }
4572 __hostdev__ bool isActive(uint32_t n) const { return DataType::mValueMask.isOn(n); }
4573
4574 /// @brief Return @c true if any of the voxel value are active in this leaf node.
4576 {
4577 //NANOVDB_ASSERT( bool(DataType::mFlags & uint8_t(2)) != DataType::mValueMask.isOff() );
4578 //return DataType::mFlags & uint8_t(2);
4579 return !DataType::mValueMask.isOff();
4580 }
4581
4582 __hostdev__ bool hasBBox() const { return DataType::mFlags & uint8_t(2); }
4583
4584 /// @brief Return @c true if the voxel value at the given coordinate is active and updates @c v with the value.
4585 __hostdev__ bool probeValue(const CoordT& ijk, ValueType& v) const
4586 {
4587 const uint32_t n = CoordToOffset(ijk);
4588 v = DataType::getValue(n);
4589 return DataType::mValueMask.isOn(n);
4590 }
4591
4592 __hostdev__ const LeafNode* probeLeaf(const CoordT&) const { return this; }
4593
4594 /// @brief Return the linear offset corresponding to the given coordinate
4595 __hostdev__ static uint32_t CoordToOffset(const CoordT& ijk)
4596 {
4597 return ((ijk[0] & MASK) << (2 * LOG2DIM)) | ((ijk[1] & MASK) << LOG2DIM) | (ijk[2] & MASK);
4598 }
4599
4600 /// @brief Updates the local bounding box of active voxels in this node. Return true if bbox was updated.
4601 ///
4602 /// @warning It assumes that the origin and value mask have already been set.
4603 ///
4604 /// @details This method is based on few (intrinsic) bit operations and hence is relatively fast.
4605 /// However, it should only only be called if either the value mask has changed or if the
4606 /// active bounding box is still undefined. e.g. during construction of this node.
4608
4609 template<typename OpT, typename... ArgsT>
4610 __hostdev__ auto get(const CoordType& ijk, ArgsT&&... args) const
4611 {
4612 return OpT::get(*this, CoordToOffset(ijk), args...);
4613 }
4614
4615 template<typename OpT, typename... ArgsT>
4616 __hostdev__ auto get(const uint32_t n, ArgsT&&... args) const
4617 {
4618 return OpT::get(*this, n, args...);
4619 }
4620
4621 template<typename OpT, typename... ArgsT>
4622 __hostdev__ auto set(const CoordType& ijk, ArgsT&&... args)
4623 {
4624 return OpT::set(*this, CoordToOffset(ijk), args...);
4625 }
4626
4627 template<typename OpT, typename... ArgsT>
4628 __hostdev__ auto set(const uint32_t n, ArgsT&&... args)
4629 {
4630 return OpT::set(*this, n, args...);
4631 }
4632
4633private:
4634 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(LeafData) is misaligned");
4635
4636 template<typename, int, int, int>
4637 friend class ReadAccessor;
4638
4639 template<typename>
4640 friend class RootNode;
4641 template<typename, uint32_t>
4642 friend class InternalNode;
4643
4644 template<typename RayT, typename AccT>
4645 __hostdev__ uint32_t getDimAndCache(const CoordT&, const RayT& /*ray*/, const AccT&) const
4646 {
4647 if (DataType::mFlags & uint8_t(1u))
4648 return this->dim(); // skip this node if the 1st bit is set
4649
4650 //if (!ray.intersects( this->bbox() )) return 1 << LOG2DIM;
4651 return ChildNodeType::dim();
4652 }
4653
4654 /// @brief Returns dim and active state in one traversal. @c Policy is
4655 /// accepted for recursion but does not change leaf behavior: the skip flag
4656 /// controls dim while active always comes from mValueMask. Branching here
4657 /// raised parallelForKernel from 64 to 66 registers/thread and reduced
4658 /// occupancy from four to three blocks/SM, negating the descent savings;
4659 /// leaf skip flags are rare because upper-level flags usually short-circuit.
4660 template<typename Policy = ActiveExact, typename RayT, typename AccT>
4661 __hostdev__ DimAndActive getDimAndActiveAndCache(const CoordT& ijk, const RayT& /*ray*/, const AccT&) const
4662 {
4663 //if (!ray.intersects( this->bbox() )) return {1 << LOG2DIM, ...};
4664 const uint32_t n = CoordToOffset(ijk);
4665 const uint32_t dimOut = (DataType::mFlags & uint8_t(1u)) ? this->dim() : ChildNodeType::dim();
4666 return {dimOut, DataType::mValueMask.isOn(n)};
4667 }
4668
4669 template<typename OpT, typename AccT, typename... ArgsT>
4670 __hostdev__ auto
4671 //__hostdev__ decltype(OpT::get(util::declval<const LeafNode&>(), util::declval<uint32_t>(), util::declval<ArgsT>()...))
4672 getAndCache(const CoordType& ijk, const AccT&, ArgsT&&... args) const
4673 {
4674 return OpT::get(*this, CoordToOffset(ijk), args...);
4675 }
4676
4677 template<typename OpT, typename AccT, typename... ArgsT>
4678 //__hostdev__ auto // occasionally fails with NVCC
4679 __hostdev__ decltype(OpT::set(util::declval<LeafNode&>(), util::declval<uint32_t>(), util::declval<ArgsT>()...))
4680 setAndCache(const CoordType& ijk, const AccT&, ArgsT&&... args)
4681 {
4682 return OpT::set(*this, CoordToOffset(ijk), args...);
4683 }
4684
4685}; // LeafNode class
4686
4687// --------------------------> LeafNode<T>::updateBBox <------------------------------------
4688
4689template<typename ValueT, typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4691{
4692 static_assert(LOG2DIM == 3, "LeafNode::updateBBox: only supports LOGDIM = 3!");
4693 if (DataType::mValueMask.isOff()) {
4694 DataType::mFlags &= ~uint8_t(2); // set 2nd bit off, which indicates that this nodes has no bbox
4695 return false;
4696 }
4697 auto update = [&](uint32_t min, uint32_t max, int axis) {
4698 NANOVDB_ASSERT(min <= max && max < 8);
4699 DataType::mBBoxMin[axis] = (DataType::mBBoxMin[axis] & ~MASK) + int(min);
4700 DataType::mBBoxDif[axis] = uint8_t(max - min);
4701 };
4702 uint64_t *w = DataType::mValueMask.words(), word64 = *w;
4703 uint32_t Xmin = word64 ? 0u : 8u, Xmax = Xmin;
4704 for (int i = 1; i < 8; ++i) { // last loop over 7 remaining 64 bit words
4705 if (w[i]) { // skip if word has no set bits
4706 word64 |= w[i]; // union 8 x 64 bits words into one 64 bit word
4707 if (Xmin == 8)
4708 Xmin = i; // only set once
4709 Xmax = i;
4710 }
4711 }
4712 NANOVDB_ASSERT(word64);
4713 update(Xmin, Xmax, 0);
4714 update(util::findLowestOn(word64) >> 3, util::findHighestOn(word64) >> 3, 1);
4715 const uint32_t *p = reinterpret_cast<const uint32_t*>(&word64), word32 = p[0] | p[1];
4716 const uint16_t *q = reinterpret_cast<const uint16_t*>(&word32), word16 = q[0] | q[1];
4717 const uint8_t *b = reinterpret_cast<const uint8_t*>(&word16), byte = b[0] | b[1];
4718 NANOVDB_ASSERT(byte);
4719 update(util::findLowestOn(static_cast<uint32_t>(byte)), util::findHighestOn(static_cast<uint32_t>(byte)), 2);
4720 DataType::mFlags |= uint8_t(2); // set 2nd bit on, which indicates that this nodes has a bbox
4721 return true;
4722} // LeafNode::updateBBox
4723
4724// --------------------------> Template specializations and traits <------------------------------------
4725
4726/// @brief Template specializations to the default configuration used in OpenVDB:
4727/// Root -> 32^3 -> 16^3 -> 8^3
4728template<typename BuildT>
4730template<typename BuildT>
4732template<typename BuildT>
4734template<typename BuildT>
4736template<typename BuildT>
4738template<typename BuildT>
4740
4741/// @brief Trait to map from LEVEL to node type
4742template<typename BuildT, int LEVEL>
4744
4745// Partial template specialization of above Node struct
4746template<typename BuildT>
4747struct NanoNode<BuildT, 0>
4748{
4751};
4752template<typename BuildT>
4753struct NanoNode<BuildT, 1>
4754{
4757};
4758template<typename BuildT>
4759struct NanoNode<BuildT, 2>
4760{
4763};
4764template<typename BuildT>
4765struct NanoNode<BuildT, 3>
4766{
4769};
4770
4771template<typename BuildT, int LEVEL>
4773
4793
4814
4815// --------------------------> callNanoGrid <------------------------------------
4816
4817/**
4818* @brief Below is an example of the struct used for generic programming with callNanoGrid
4819* @details For an example see "struct Crc32TailOld" in nanovdb/tools/GridChecksum.h or
4820* "struct IsNanoGridValid" in nanovdb/tools/GridValidator.h
4821* @code
4822* struct OpT {
4823 // define these two static functions with non-const GridData
4824* template <typename BuildT>
4825* static auto known( GridData *gridData, args...);
4826* static auto unknown( GridData *gridData, args...);
4827* // or alternatively these two static functions with const GridData
4828* template <typename BuildT>
4829* static auto known(const GridData *gridData, args...);
4830* static auto unknown(const GridData *gridData, args...);
4831* };
4832* @endcode
4833*
4834* @brief Here is an example of how to use callNanoGrid in client code
4835* @code
4836* return callNanoGrid<OpT>(gridData, args...);
4837* @endcode
4838*/
4839
4840/// @brief Use this function, which depends on a pointer to GridData, to call
4841/// other functions that depend on a NanoGrid of a known ValueType.
4842/// @details This function allows for generic programming by converting GridData
4843/// to a NanoGrid of the type encoded in GridData::mGridType.
4844template<typename OpT, typename GridDataT, typename... ArgsT>
4845auto callNanoGrid(GridDataT *gridData, ArgsT&&... args)
4846{
4847 static_assert(util::is_same<GridDataT, GridData, const GridData>::value, "Expected gridData to be of type GridData* or const GridData*");
4848 switch (gridData->mGridType){
4849 case GridType::Float:
4850 return OpT::template known<float>(gridData, args...);
4851 case GridType::Double:
4852 return OpT::template known<double>(gridData, args...);
4853 case GridType::Int16:
4854 return OpT::template known<int16_t>(gridData, args...);
4855 case GridType::Int32:
4856 return OpT::template known<int32_t>(gridData, args...);
4857 case GridType::Int64:
4858 return OpT::template known<int64_t>(gridData, args...);
4859 case GridType::Vec3f:
4860 return OpT::template known<Vec3f>(gridData, args...);
4861 case GridType::Vec3d:
4862 return OpT::template known<Vec3d>(gridData, args...);
4863 case GridType::UInt32:
4864 return OpT::template known<uint32_t>(gridData, args...);
4865 case GridType::Mask:
4866 return OpT::template known<ValueMask>(gridData, args...);
4867 case GridType::Index:
4868 return OpT::template known<ValueIndex>(gridData, args...);
4869 case GridType::OnIndex:
4870 return OpT::template known<ValueOnIndex>(gridData, args...);
4871 case GridType::Boolean:
4872 return OpT::template known<bool>(gridData, args...);
4873 case GridType::RGBA8:
4874 return OpT::template known<math::Rgba8>(gridData, args...);
4875 case GridType::Fp4:
4876 return OpT::template known<Fp4>(gridData, args...);
4877 case GridType::Fp8:
4878 return OpT::template known<Fp8>(gridData, args...);
4879 case GridType::Fp16:
4880 return OpT::template known<Fp16>(gridData, args...);
4881 case GridType::FpN:
4882 return OpT::template known<FpN>(gridData, args...);
4883 case GridType::Vec4f:
4884 return OpT::template known<Vec4f>(gridData, args...);
4885 case GridType::Vec4d:
4886 return OpT::template known<Vec4d>(gridData, args...);
4887 case GridType::UInt8:
4888 return OpT::template known<uint8_t>(gridData, args...);
4889 case GridType::Half:
4890 return OpT::template known<Half>(gridData, args...);
4891 default:
4892 return OpT::unknown(gridData, args...);
4893 }
4894}// callNanoGrid
4895
4896// --------------------------> ReadAccessor <------------------------------------
4897
4898/// @brief A read-only value accessor with three levels of node caching. This allows for
4899/// inverse tree traversal during lookup, which is on average significantly faster
4900/// than calling the equivalent method on the tree (i.e. top-down traversal).
4901///
4902/// @note By virtue of the fact that a value accessor accelerates random access operations
4903/// by re-using cached access patterns, this access should be reused for multiple access
4904/// operations. In other words, never create an instance of this accessor for a single
4905/// access only. In general avoid single access operations with this accessor, and
4906/// if that is not possible call the corresponding method on the tree instead.
4907///
4908/// @warning Since this ReadAccessor internally caches raw pointers to the nodes of the tree
4909/// structure, it is not safe to copy between host and device, or even to share among
4910/// multiple threads on the same host or device. However, it is light-weight so simple
4911/// instantiate one per thread (on the host and/or device).
4912///
4913/// @details Used to accelerated random access into a VDB tree. Provides on average
4914/// O(1) random access operations by means of inverse tree traversal,
4915/// which amortizes the non-const time complexity of the root node.
4916
4917template<typename BuildT>
4918class ReadAccessor<BuildT, -1, -1, -1>
4919{
4920 using GridT = NanoGrid<BuildT>; // grid
4921 using TreeT = NanoTree<BuildT>; // tree
4922 using RootT = NanoRoot<BuildT>; // root node
4923 using LeafT = NanoLeaf<BuildT>; // Leaf node
4924 using FloatType = typename RootT::FloatType;
4925 using CoordValueType = typename RootT::CoordType::ValueType;
4926
4927 mutable const RootT* mRoot; // 8 bytes (mutable to allow for access methods to be const)
4928public:
4929 using BuildType = BuildT;
4930 using ValueType = typename RootT::ValueType;
4931 using CoordType = typename RootT::CoordType;
4932
4933 static const int CacheLevels = 0;
4934
4935 /// @brief Constructor from a root node
4937 : mRoot{&root}
4938 {
4939 }
4940
4941 /// @brief Constructor from a grid
4942 __hostdev__ ReadAccessor(const GridT& grid)
4943 : ReadAccessor(grid.tree().root())
4944 {
4945 }
4946
4947 /// @brief Constructor from a tree
4948 __hostdev__ ReadAccessor(const TreeT& tree)
4949 : ReadAccessor(tree.root())
4950 {
4951 }
4952
4953 /// @brief Reset this access to its initial state, i.e. with an empty cache
4954 /// @note Noop since this template specialization has no cache
4956
4957 __hostdev__ const RootT& root() const { return *mRoot; }
4958
4959 /// @brief Defaults constructors
4960 ReadAccessor(const ReadAccessor&) = default;
4961 ~ReadAccessor() = default;
4964 {
4965 return this->template get<GetValue<BuildT>>(ijk);
4966 }
4967 __hostdev__ ValueType getValue(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
4968 __hostdev__ ValueType operator()(const CoordType& ijk) const { return this->template get<GetValue<BuildT>>(ijk); }
4969 __hostdev__ ValueType operator()(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
4970 __hostdev__ auto getNodeInfo(const CoordType& ijk) const { return this->template get<GetNodeInfo<BuildT>>(ijk); }
4971 __hostdev__ bool isActive(const CoordType& ijk) const { return this->template get<GetState<BuildT>>(ijk); }
4972 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->template get<ProbeValue<BuildT>>(ijk, v); }
4973 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const { return this->template get<GetLeaf<BuildT>>(ijk); }
4974 template<typename RayT>
4975 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
4976 {
4977 return mRoot->getDimAndCache(ijk, ray, *this);
4978 }
4979 /// @brief Fused getDim + isActive: one tree walk returns both the HDDA
4980 /// step size and the active state of @a ijk, shaving the second descent
4981 /// / cache-check / leaf ValueMask lookup. See @c ActiveExact /
4982 /// @c ActiveOnLeafOnly for the @c Policy contract.
4983 template<typename Policy = ActiveExact, typename RayT>
4984 __hostdev__ DimAndActive getDimAndActive(const CoordType& ijk, const RayT& ray) const
4985 {
4986 return mRoot->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
4987 }
4988 template<typename OpT, typename... ArgsT>
4989 __hostdev__ auto get(const CoordType& ijk, ArgsT&&... args) const
4990 {
4991 return mRoot->template get<OpT>(ijk, args...);
4992 }
4993
4994 template<typename OpT, typename... ArgsT>
4995 __hostdev__ auto set(const CoordType& ijk, ArgsT&&... args) const
4996 {
4997 return const_cast<RootT*>(mRoot)->template set<OpT>(ijk, args...);
4998 }
4999
5000private:
5001 /// @brief Allow nodes to insert themselves into the cache.
5002 template<typename>
5003 friend class RootNode;
5004 template<typename, uint32_t>
5005 friend class InternalNode;
5006 template<typename, typename, template<uint32_t> class, uint32_t>
5007 friend class LeafNode;
5008
5009 /// @brief No-op
5010 template<typename NodeT>
5011 __hostdev__ void insert(const CoordType&, const NodeT*) const {}
5012}; // ReadAccessor<ValueT, -1, -1, -1> class
5013
5014/// @brief Node caching at a single tree level
5015template<typename BuildT, int LEVEL0>
5016class ReadAccessor<BuildT, LEVEL0, -1, -1> //e.g. 0, 1, 2
5017{
5018 static_assert(LEVEL0 >= 0 && LEVEL0 <= 2, "LEVEL0 should be 0, 1, or 2");
5019
5020 using GridT = NanoGrid<BuildT>; // grid
5021 using TreeT = NanoTree<BuildT>;
5022 using RootT = NanoRoot<BuildT>; // root node
5023 using LeafT = NanoLeaf<BuildT>; // Leaf node
5024 using NodeT = typename NodeTrait<TreeT, LEVEL0>::type;
5025 using CoordT = typename RootT::CoordType;
5026 using ValueT = typename RootT::ValueType;
5027
5028 using FloatType = typename RootT::FloatType;
5029 using CoordValueType = typename RootT::CoordT::ValueType;
5030
5031 // All member data are mutable to allow for access methods to be const
5032 mutable CoordT mKey; // 3*4 = 12 bytes
5033 mutable const RootT* mRoot; // 8 bytes
5034 mutable const NodeT* mNode; // 8 bytes
5035
5036public:
5037 using BuildType = BuildT;
5038 using ValueType = ValueT;
5039 using CoordType = CoordT;
5040
5041 static const int CacheLevels = 1;
5042
5043 /// @brief Constructor from a root node
5045 : mKey(CoordType::max())
5046 , mRoot(&root)
5047 , mNode(nullptr)
5048 {
5049 }
5050
5051 /// @brief Constructor from a grid
5052 __hostdev__ ReadAccessor(const GridT& grid)
5053 : ReadAccessor(grid.tree().root())
5054 {
5055 }
5056
5057 /// @brief Constructor from a tree
5058 __hostdev__ ReadAccessor(const TreeT& tree)
5059 : ReadAccessor(tree.root())
5060 {
5061 }
5062
5063 /// @brief Reset this access to its initial state, i.e. with an empty cache
5065 {
5066 mKey = CoordType::max();
5067 mNode = nullptr;
5068 }
5069
5070 __hostdev__ const RootT& root() const { return *mRoot; }
5071
5072 /// @brief Defaults constructors
5073 ReadAccessor(const ReadAccessor&) = default;
5074 ~ReadAccessor() = default;
5076
5077 __hostdev__ bool isCached(const CoordType& ijk) const
5078 {
5079 return (ijk[0] & int32_t(~NodeT::MASK)) == mKey[0] &&
5080 (ijk[1] & int32_t(~NodeT::MASK)) == mKey[1] &&
5081 (ijk[2] & int32_t(~NodeT::MASK)) == mKey[2];
5082 }
5083
5085 {
5086 return this->template get<GetValue<BuildT>>(ijk);
5087 }
5088 __hostdev__ ValueType getValue(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
5089 __hostdev__ ValueType operator()(const CoordType& ijk) const { return this->template get<GetValue<BuildT>>(ijk); }
5090 __hostdev__ ValueType operator()(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
5091 __hostdev__ auto getNodeInfo(const CoordType& ijk) const { return this->template get<GetNodeInfo<BuildT>>(ijk); }
5092 __hostdev__ bool isActive(const CoordType& ijk) const { return this->template get<GetState<BuildT>>(ijk); }
5093 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->template get<ProbeValue<BuildT>>(ijk, v); }
5094 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const { return this->template get<GetLeaf<BuildT>>(ijk); }
5095
5096 template<typename RayT>
5097 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
5098 {
5099 if (this->isCached(ijk)) return mNode->getDimAndCache(ijk, ray, *this);
5100 return mRoot->getDimAndCache(ijk, ray, *this);
5101 }
5102
5103 /// @brief Fused getDim + isActive: one tree walk returns both the HDDA
5104 /// step size and the active state of @a ijk, shaving the second descent
5105 /// / cache-check / leaf ValueMask lookup. See @c ActiveExact /
5106 /// @c ActiveOnLeafOnly for the @c Policy contract.
5107 template<typename Policy = ActiveExact, typename RayT>
5108 __hostdev__ DimAndActive getDimAndActive(const CoordType& ijk, const RayT& ray) const
5109 {
5110 if (this->isCached(ijk)) return mNode->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5111 return mRoot->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5112 }
5113
5114 template<typename OpT, typename... ArgsT>
5115 __hostdev__ typename OpT::Type get(const CoordType& ijk, ArgsT&&... args) const
5116 {
5117 if constexpr(OpT::LEVEL <= LEVEL0) if (this->isCached(ijk)) return mNode->template getAndCache<OpT>(ijk, *this, args...);
5118 return mRoot->template getAndCache<OpT>(ijk, *this, args...);
5119 }
5120
5121 template<typename OpT, typename... ArgsT>
5122 __hostdev__ void set(const CoordType& ijk, ArgsT&&... args) const
5123 {
5124 if constexpr(OpT::LEVEL <= LEVEL0) if (this->isCached(ijk)) return const_cast<NodeT*>(mNode)->template setAndCache<OpT>(ijk, *this, args...);
5125 return const_cast<RootT*>(mRoot)->template setAndCache<OpT>(ijk, *this, args...);
5126 }
5127
5128private:
5129 /// @brief Allow nodes to insert themselves into the cache.
5130 template<typename>
5131 friend class RootNode;
5132 template<typename, uint32_t>
5133 friend class InternalNode;
5134 template<typename, typename, template<uint32_t> class, uint32_t>
5135 friend class LeafNode;
5136
5137 /// @brief Inserts a leaf node and key pair into this ReadAccessor
5138 __hostdev__ void insert(const CoordType& ijk, const NodeT* node) const
5139 {
5140 mKey = ijk & ~NodeT::MASK;
5141 mNode = node;
5142 }
5143
5144 // no-op
5145 template<typename OtherNodeT>
5146 __hostdev__ void insert(const CoordType&, const OtherNodeT*) const {}
5147
5148}; // ReadAccessor<ValueT, LEVEL0>
5149
5150template<typename BuildT, int LEVEL0, int LEVEL1>
5151class ReadAccessor<BuildT, LEVEL0, LEVEL1, -1> //e.g. (0,1), (1,2), (0,2)
5152{
5153 static_assert(LEVEL0 >= 0 && LEVEL0 <= 2, "LEVEL0 must be 0, 1, 2");
5154 static_assert(LEVEL1 >= 0 && LEVEL1 <= 2, "LEVEL1 must be 0, 1, 2");
5155 static_assert(LEVEL0 < LEVEL1, "Level 0 must be lower than level 1");
5156 using GridT = NanoGrid<BuildT>; // grid
5157 using TreeT = NanoTree<BuildT>;
5158 using RootT = NanoRoot<BuildT>;
5159 using LeafT = NanoLeaf<BuildT>;
5160 using Node1T = typename NodeTrait<TreeT, LEVEL0>::type;
5161 using Node2T = typename NodeTrait<TreeT, LEVEL1>::type;
5162 using CoordT = typename RootT::CoordType;
5163 using ValueT = typename RootT::ValueType;
5164 using FloatType = typename RootT::FloatType;
5165 using CoordValueType = typename RootT::CoordT::ValueType;
5166
5167 // All member data are mutable to allow for access methods to be const
5168#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY // 44 bytes total
5169 mutable CoordT mKey; // 3*4 = 12 bytes
5170#else // 68 bytes total
5171 mutable CoordT mKeys[2]; // 2*3*4 = 24 bytes
5172#endif
5173 mutable const RootT* mRoot;
5174 mutable const Node1T* mNode1;
5175 mutable const Node2T* mNode2;
5176
5177public:
5178 using BuildType = BuildT;
5179 using ValueType = ValueT;
5180 using CoordType = CoordT;
5181
5182 static const int CacheLevels = 2;
5183
5184 /// @brief Constructor from a root node
5186#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5187 : mKey(CoordType::max())
5188#else
5189 : mKeys{CoordType::max(), CoordType::max()}
5190#endif
5191 , mRoot(&root)
5192 , mNode1(nullptr)
5193 , mNode2(nullptr)
5194 {
5195 }
5196
5197 /// @brief Constructor from a grid
5198 __hostdev__ ReadAccessor(const GridT& grid)
5199 : ReadAccessor(grid.tree().root())
5200 {
5201 }
5202
5203 /// @brief Constructor from a tree
5204 __hostdev__ ReadAccessor(const TreeT& tree)
5205 : ReadAccessor(tree.root())
5206 {
5207 }
5208
5209 /// @brief Reset this access to its initial state, i.e. with an empty cache
5211 {
5212#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5213 mKey = CoordType::max();
5214#else
5215 mKeys[0] = mKeys[1] = CoordType::max();
5216#endif
5217 mNode1 = nullptr;
5218 mNode2 = nullptr;
5219 }
5220
5221 __hostdev__ const RootT& root() const { return *mRoot; }
5222
5223 /// @brief Defaults constructors
5224 ReadAccessor(const ReadAccessor&) = default;
5225 ~ReadAccessor() = default;
5227
5228#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5229 __hostdev__ bool isCached1(CoordValueType dirty) const
5230 {
5231 if (!mNode1)
5232 return false;
5233 if (dirty & int32_t(~Node1T::MASK)) {
5234 mNode1 = nullptr;
5235 return false;
5236 }
5237 return true;
5238 }
5239 __hostdev__ bool isCached2(CoordValueType dirty) const
5240 {
5241 if (!mNode2)
5242 return false;
5243 if (dirty & int32_t(~Node2T::MASK)) {
5244 mNode2 = nullptr;
5245 return false;
5246 }
5247 return true;
5248 }
5249 __hostdev__ CoordValueType computeDirty(const CoordType& ijk) const
5250 {
5251 return (ijk[0] ^ mKey[0]) | (ijk[1] ^ mKey[1]) | (ijk[2] ^ mKey[2]);
5252 }
5253#else
5254 __hostdev__ bool isCached1(const CoordType& ijk) const
5255 {
5256 return (ijk[0] & int32_t(~Node1T::MASK)) == mKeys[0][0] &&
5257 (ijk[1] & int32_t(~Node1T::MASK)) == mKeys[0][1] &&
5258 (ijk[2] & int32_t(~Node1T::MASK)) == mKeys[0][2];
5259 }
5260 __hostdev__ bool isCached2(const CoordType& ijk) const
5261 {
5262 return (ijk[0] & int32_t(~Node2T::MASK)) == mKeys[1][0] &&
5263 (ijk[1] & int32_t(~Node2T::MASK)) == mKeys[1][1] &&
5264 (ijk[2] & int32_t(~Node2T::MASK)) == mKeys[1][2];
5265 }
5266#endif
5267
5269 {
5270 return this->template get<GetValue<BuildT>>(ijk);
5271 }
5272 __hostdev__ ValueType getValue(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
5273 __hostdev__ ValueType operator()(const CoordType& ijk) const { return this->template get<GetValue<BuildT>>(ijk); }
5274 __hostdev__ ValueType operator()(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
5275 __hostdev__ auto getNodeInfo(const CoordType& ijk) const { return this->template get<GetNodeInfo<BuildT>>(ijk); }
5276 __hostdev__ bool isActive(const CoordType& ijk) const { return this->template get<GetState<BuildT>>(ijk); }
5277 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->template get<ProbeValue<BuildT>>(ijk, v); }
5278 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const { return this->template get<GetLeaf<BuildT>>(ijk); }
5279
5280 template<typename RayT>
5281 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
5282 {
5283#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5284 const CoordValueType dirty = this->computeDirty(ijk);
5285#else
5286 auto&& dirty = ijk;
5287#endif
5288 if (this->isCached1(dirty)) {
5289 return mNode1->getDimAndCache(ijk, ray, *this);
5290 } else if (this->isCached2(dirty)) {
5291 return mNode2->getDimAndCache(ijk, ray, *this);
5292 }
5293 return mRoot->getDimAndCache(ijk, ray, *this);
5294 }
5295
5296 /// @brief Fused getDim + isActive: one tree walk returns both the HDDA
5297 /// step size and the active state of @a ijk, shaving the second descent
5298 /// / cache-check / leaf ValueMask lookup. See @c ActiveExact /
5299 /// @c ActiveOnLeafOnly for the @c Policy contract.
5300 template<typename Policy = ActiveExact, typename RayT>
5301 __hostdev__ DimAndActive getDimAndActive(const CoordType& ijk, const RayT& ray) const
5302 {
5303#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5304 const CoordValueType dirty = this->computeDirty(ijk);
5305#else
5306 auto&& dirty = ijk;
5307#endif
5308 if (this->isCached1(dirty)) {
5309 return mNode1->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5310 } else if (this->isCached2(dirty)) {
5311 return mNode2->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5312 }
5313 return mRoot->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5314 }
5315
5316 template<typename OpT, typename... ArgsT>
5317 __hostdev__ typename OpT::Type get(const CoordType& ijk, ArgsT&&... args) const
5318 {
5319#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5320 const CoordValueType dirty = this->computeDirty(ijk);
5321#else
5322 auto&& dirty = ijk;
5323#endif
5324 if constexpr(OpT::LEVEL <= LEVEL0) {
5325 if (this->isCached1(dirty)) return mNode1->template getAndCache<OpT>(ijk, *this, args...);
5326 }
5327#ifdef NANOVDB_USE_OLD_ACCESSOR
5328 else
5329#endif
5330 if constexpr(OpT::LEVEL <= LEVEL1) {
5331 if (this->isCached2(dirty)) return mNode2->template getAndCache<OpT>(ijk, *this, args...);
5332 }
5333 return mRoot->template getAndCache<OpT>(ijk, *this, args...);
5334 }
5335
5336 template<typename OpT, typename... ArgsT>
5337 __hostdev__ void set(const CoordType& ijk, ArgsT&&... args) const
5338 {
5339#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5340 const CoordValueType dirty = this->computeDirty(ijk);
5341#else
5342 auto&& dirty = ijk;
5343#endif
5344 if constexpr(OpT::LEVEL <= LEVEL0) {
5345 if (this->isCached1(dirty)) return const_cast<Node1T*>(mNode1)->template setAndCache<OpT>(ijk, *this, args...);
5346 }
5347#ifdef NANOVDB_USE_OLD_ACCESSOR
5348 else
5349#endif
5350 if constexpr(OpT::LEVEL <= LEVEL1) {
5351 if (this->isCached2(dirty)) return const_cast<Node2T*>(mNode2)->template setAndCache<OpT>(ijk, *this, args...);
5352 }
5353 return const_cast<RootT*>(mRoot)->template setAndCache<OpT>(ijk, *this, args...);
5354 }
5355
5356private:
5357 /// @brief Allow nodes to insert themselves into the cache.
5358 template<typename>
5359 friend class RootNode;
5360 template<typename, uint32_t>
5361 friend class InternalNode;
5362 template<typename, typename, template<uint32_t> class, uint32_t>
5363 friend class LeafNode;
5364
5365 /// @brief Inserts a leaf node and key pair into this ReadAccessor
5366 __hostdev__ void insert(const CoordType& ijk, const Node1T* node) const
5367 {
5368#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5369 mKey = ijk;
5370#else
5371 mKeys[0] = ijk & ~Node1T::MASK;
5372#endif
5373 mNode1 = node;
5374 }
5375 __hostdev__ void insert(const CoordType& ijk, const Node2T* node) const
5376 {
5377#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5378 mKey = ijk;
5379#else
5380 mKeys[1] = ijk & ~Node2T::MASK;
5381#endif
5382 mNode2 = node;
5383 }
5384 template<typename OtherNodeT>
5385 __hostdev__ void insert(const CoordType&, const OtherNodeT*) const {}
5386}; // ReadAccessor<BuildT, LEVEL0, LEVEL1>
5387
5388/// @brief Node caching at all (three) tree levels
5389template<typename BuildT>
5390class ReadAccessor<BuildT, 0, 1, 2>
5391{
5392 using GridT = NanoGrid<BuildT>; // grid
5393 using TreeT = NanoTree<BuildT>;
5394 using RootT = NanoRoot<BuildT>; // root node
5395 using NodeT2 = NanoUpper<BuildT>; // upper internal node
5396 using NodeT1 = NanoLower<BuildT>; // lower internal node
5397 using LeafT = NanoLeaf<BuildT>; // Leaf node
5398 using CoordT = typename RootT::CoordType;
5399 using ValueT = typename RootT::ValueType;
5400
5401 using FloatType = typename RootT::FloatType;
5402 using CoordValueType = typename RootT::CoordT::ValueType;
5403
5404 // All member data are mutable to allow for access methods to be const
5405#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY // 44 bytes total
5406 mutable CoordT mKey; // 3*4 = 12 bytes
5407#else // 68 bytes total
5408 mutable CoordT mKeys[3]; // 3*3*4 = 36 bytes
5409#endif
5410 mutable const RootT* mRoot;
5411 mutable const void* mNode[3]; // 4*8 = 32 bytes
5412
5413public:
5414 using BuildType = BuildT;
5415 using ValueType = ValueT;
5416 using CoordType = CoordT;
5417
5418 static const int CacheLevels = 3;
5419
5420 /// @brief Constructor from a root node
5421 __hostdev__ ReadAccessor(const RootT& root)
5422#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5423 : mKey(CoordType::max())
5424#else
5425 : mKeys{CoordType::max(), CoordType::max(), CoordType::max()}
5426#endif
5427 , mRoot(&root)
5428 , mNode{nullptr, nullptr, nullptr}
5429 {
5430 }
5431
5432 /// @brief Constructor from a grid
5433 __hostdev__ ReadAccessor(const GridT& grid)
5434 : ReadAccessor(grid.tree().root())
5435 {
5436 }
5437
5438 /// @brief Constructor from a tree
5439 __hostdev__ ReadAccessor(const TreeT& tree)
5440 : ReadAccessor(tree.root())
5441 {
5442 }
5443
5444 __hostdev__ const RootT& root() const { return *mRoot; }
5445
5446 /// @brief Defaults constructors
5447 ReadAccessor(const ReadAccessor&) = default;
5448 ~ReadAccessor() = default;
5449 ReadAccessor& operator=(const ReadAccessor&) = default;
5450
5451 /// @brief Return a const point to the cached node of the specified type
5452 ///
5453 /// @warning The return value could be NULL.
5454 template<typename NodeT>
5455 __hostdev__ const NodeT* getNode() const
5456 {
5457 using T = typename NodeTrait<TreeT, NodeT::LEVEL>::type;
5458 static_assert(util::is_same<T, NodeT>::value, "ReadAccessor::getNode: Invalid node type");
5459 return reinterpret_cast<const T*>(mNode[NodeT::LEVEL]);
5460 }
5461
5462 template<int LEVEL>
5463 __hostdev__ const typename NodeTrait<TreeT, LEVEL>::type* getNode() const
5464 {
5465 using T = typename NodeTrait<TreeT, LEVEL>::type;
5466 static_assert(LEVEL >= 0 && LEVEL <= 2, "ReadAccessor::getNode: Invalid node type");
5467 return reinterpret_cast<const T*>(mNode[LEVEL]);
5468 }
5469
5470 /// @brief Reset this access to its initial state, i.e. with an empty cache
5471 __hostdev__ void clear()
5472 {
5473#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5474 mKey = CoordType::max();
5475#else
5476 mKeys[0] = mKeys[1] = mKeys[2] = CoordType::max();
5477#endif
5478 mNode[0] = mNode[1] = mNode[2] = nullptr;
5479 }
5480
5481#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5482 template<typename NodeT>
5483 __hostdev__ bool isCached(CoordValueType dirty) const
5484 {
5485 if (!mNode[NodeT::LEVEL])
5486 return false;
5487 if (dirty & int32_t(~NodeT::MASK)) {
5488 mNode[NodeT::LEVEL] = nullptr;
5489 return false;
5490 }
5491 return true;
5492 }
5493
5494 __hostdev__ CoordValueType computeDirty(const CoordType& ijk) const
5495 {
5496 return (ijk[0] ^ mKey[0]) | (ijk[1] ^ mKey[1]) | (ijk[2] ^ mKey[2]);
5497 }
5498#else
5499 template<typename NodeT>
5500 __hostdev__ bool isCached(const CoordType& ijk) const
5501 {
5502 return (ijk[0] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][0] &&
5503 (ijk[1] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][1] &&
5504 (ijk[2] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][2];
5505 }
5506#endif
5507
5508 __hostdev__ ValueType getValue(const CoordType& ijk) const {return this->template get<GetValue<BuildT>>(ijk);}
5509 __hostdev__ ValueType getValue(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
5510 __hostdev__ ValueType operator()(const CoordType& ijk) const { return this->template get<GetValue<BuildT>>(ijk); }
5511 __hostdev__ ValueType operator()(int i, int j, int k) const { return this->template get<GetValue<BuildT>>(CoordType(i, j, k)); }
5512 __hostdev__ auto getNodeInfo(const CoordType& ijk) const { return this->template get<GetNodeInfo<BuildT>>(ijk); }
5513 __hostdev__ bool isActive(const CoordType& ijk) const { return this->template get<GetState<BuildT>>(ijk); }
5514 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->template get<ProbeValue<BuildT>>(ijk, v); }
5515 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const { return this->template get<GetLeaf<BuildT>>(ijk); }
5516
5517 template<typename OpT, typename... ArgsT>
5518 __hostdev__ typename OpT::Type get(const CoordType& ijk, ArgsT&&... args) const
5519 {
5520#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5521 const CoordValueType dirty = this->computeDirty(ijk);
5522#else
5523 auto&& dirty = ijk;
5524#endif
5525 if constexpr(OpT::LEVEL <=0) {
5526 if (this->isCached<LeafT>(dirty)) return ((const LeafT*)mNode[0])->template getAndCache<OpT>(ijk, *this, args...);
5527 }
5528#ifdef NANOVDB_USE_OLD_ACCESSOR
5529 else
5530#endif
5531 if constexpr(OpT::LEVEL <= 1) {
5532 if (this->isCached<NodeT1>(dirty)) return ((const NodeT1*)mNode[1])->template getAndCache<OpT>(ijk, *this, args...);
5533 }
5534#ifdef NANOVDB_USE_OLD_ACCESSOR
5535 else
5536#endif
5537 if constexpr(OpT::LEVEL <= 2) {
5538 if (this->isCached<NodeT2>(dirty)) return ((const NodeT2*)mNode[2])->template getAndCache<OpT>(ijk, *this, args...);
5539 }
5540 return mRoot->template getAndCache<OpT>(ijk, *this, args...);
5541 }
5542
5543 template<typename OpT, typename... ArgsT>
5544 __hostdev__ void set(const CoordType& ijk, ArgsT&&... args) const
5545 {
5546#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5547 const CoordValueType dirty = this->computeDirty(ijk);
5548#else
5549 auto&& dirty = ijk;
5550#endif
5551 if constexpr(OpT::LEVEL <= 0) {
5552 if (this->isCached<LeafT>(dirty)) return ((LeafT*)mNode[0])->template setAndCache<OpT>(ijk, *this, args...);
5553 }
5554#ifdef NANOVDB_USE_OLD_ACCESSOR
5555 else
5556#endif
5557 if constexpr(OpT::LEVEL <= 1) {
5558 if (this->isCached<NodeT1>(dirty)) return ((NodeT1*)mNode[1])->template setAndCache<OpT>(ijk, *this, args...);
5559 }
5560#ifdef NANOVDB_USE_OLD_ACCESSOR
5561 else
5562#endif
5563 if constexpr(OpT::LEVEL <= 2) {
5564 if (this->isCached<NodeT2>(dirty)) return ((NodeT2*)mNode[2])->template setAndCache<OpT>(ijk, *this, args...);
5565 }
5566 return ((RootT*)mRoot)->template setAndCache<OpT>(ijk, *this, args...);
5567 }
5568
5569 template<typename RayT>
5570 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
5571 {
5572#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5573 const CoordValueType dirty = this->computeDirty(ijk);
5574#else
5575 auto&& dirty = ijk;
5576#endif
5577 if (this->isCached<LeafT>(dirty)) {
5578 return ((LeafT*)mNode[0])->getDimAndCache(ijk, ray, *this);
5579 } else if (this->isCached<NodeT1>(dirty)) {
5580 return ((NodeT1*)mNode[1])->getDimAndCache(ijk, ray, *this);
5581 } else if (this->isCached<NodeT2>(dirty)) {
5582 return ((NodeT2*)mNode[2])->getDimAndCache(ijk, ray, *this);
5583 }
5584 return mRoot->getDimAndCache(ijk, ray, *this);
5585 }
5586
5587 /// @brief Fused getDim + isActive: one tree walk returns both the HDDA
5588 /// step size and the active state of @a ijk, shaving the second descent
5589 /// / cache-check / leaf ValueMask lookup. See @c ActiveExact /
5590 /// @c ActiveOnLeafOnly for the @c Policy contract.
5591 template<typename Policy = ActiveExact, typename RayT>
5592 __hostdev__ DimAndActive getDimAndActive(const CoordType& ijk, const RayT& ray) const
5593 {
5594#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5595 const CoordValueType dirty = this->computeDirty(ijk);
5596#else
5597 auto&& dirty = ijk;
5598#endif
5599 if (this->isCached<LeafT>(dirty)) {
5600 return ((LeafT*)mNode[0])->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5601 } else if (this->isCached<NodeT1>(dirty)) {
5602 return ((NodeT1*)mNode[1])->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5603 } else if (this->isCached<NodeT2>(dirty)) {
5604 return ((NodeT2*)mNode[2])->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5605 }
5606 return mRoot->template getDimAndActiveAndCache<Policy>(ijk, ray, *this);
5607 }
5608
5609private:
5610 /// @brief Allow nodes to insert themselves into the cache.
5611 template<typename>
5612 friend class RootNode;
5613 template<typename, uint32_t>
5614 friend class InternalNode;
5615 template<typename, typename, template<uint32_t> class, uint32_t>
5616 friend class LeafNode;
5617
5618 /// @brief Inserts a leaf node and key pair into this ReadAccessor
5619 template<typename NodeT>
5620 __hostdev__ void insert(const CoordType& ijk, const NodeT* node) const
5621 {
5622#ifdef NANOVDB_USE_SINGLE_ACCESSOR_KEY
5623 mKey = ijk;
5624#else
5625 mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
5626#endif
5627 mNode[NodeT::LEVEL] = node;
5628 }
5629}; // ReadAccessor<BuildT, 0, 1, 2>
5630
5631//////////////////////////////////////////////////
5632
5633/// @brief Free-standing function for convenient creation of a ReadAccessor with
5634/// optional and customizable node caching.
5635///
5636/// @details createAccessor<>(grid): No caching of nodes and hence it's thread-safe but slow
5637/// createAccessor<0>(grid): Caching of leaf nodes only
5638/// createAccessor<1>(grid): Caching of lower internal nodes only
5639/// createAccessor<2>(grid): Caching of upper internal nodes only
5640/// createAccessor<0,1>(grid): Caching of leaf and lower internal nodes
5641/// createAccessor<0,2>(grid): Caching of leaf and upper internal nodes
5642/// createAccessor<1,2>(grid): Caching of lower and upper internal nodes
5643/// createAccessor<0,1,2>(grid): Caching of all nodes at all tree levels
5644
5645template<int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1, typename ValueT = float>
5650
5651template<int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1, typename ValueT = float>
5656
5657template<int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1, typename ValueT = float>
5662
5663//////////////////////////////////////////////////
5664
5665/// @brief This is a convenient class that allows for access to grid meta-data
5666/// that are independent of the value type of a grid. That is, this class
5667/// can be used to get information about a grid without actually knowing
5668/// its ValueType.
5670{ // 768 bytes (32 byte aligned)
5671 GridData mGridData; // 672B
5672 TreeData mTreeData; // 64B
5673 CoordBBox mIndexBBox; // 24B. AABB of active values in index space.
5674 uint32_t mRootTableSize, mPadding{0}; // 8B
5675
5676public:
5677 template<typename T>
5679 {
5680 mGridData = *grid.data();
5681 mTreeData = *grid.tree().data();
5682 mIndexBBox = grid.indexBBox();
5683 mRootTableSize = grid.tree().root().getTableSize();
5684 }
5685 GridMetaData(const GridData* gridData)
5686 {
5687 if (GridMetaData::safeCast(gridData)) {
5688 *this = *reinterpret_cast<const GridMetaData*>(gridData);
5689 //util::memcpy(this, (const GridMetaData*)gridData);
5690 } else {// otherwise copy each member individually
5691 mGridData = *gridData;
5692 mTreeData = *reinterpret_cast<const TreeData*>(gridData->treePtr());
5693 mIndexBBox = gridData->indexBBox();
5694 mRootTableSize = gridData->rootTableSize();
5695 }
5696 }
5698 /// @brief return true if the RootData follows right after the TreeData.
5699 /// If so, this implies that it's safe to cast the grid from which
5700 /// this instance was constructed to a GridMetaData
5701 __hostdev__ bool safeCast() const { return mTreeData.isRootNext(); }
5702
5703 /// @brief return true if it is safe to cast the grid to a pointer
5704 /// of type GridMetaData, i.e. construction can be avoided.
5705 __hostdev__ static bool safeCast(const GridData *gridData){
5706 NANOVDB_ASSERT(gridData && gridData->isValid());
5707 return gridData->isRootConnected();
5708 }
5709 /// @brief return true if it is safe to cast the grid to a pointer
5710 /// of type GridMetaData, i.e. construction can be avoided.
5711 template<typename T>
5712 __hostdev__ static bool safeCast(const NanoGrid<T>& grid){return grid.tree().isRootNext();}
5713 __hostdev__ bool isValid() const { return mGridData.isValid(); }
5714 __hostdev__ const GridType& gridType() const { return mGridData.mGridType; }
5715 __hostdev__ const GridClass& gridClass() const { return mGridData.mGridClass; }
5716 __hostdev__ bool isLevelSet() const { return mGridData.mGridClass == GridClass::LevelSet; }
5717 __hostdev__ bool isFogVolume() const { return mGridData.mGridClass == GridClass::FogVolume; }
5718 __hostdev__ bool isStaggered() const { return mGridData.mGridClass == GridClass::Staggered; }
5719 __hostdev__ bool isPointIndex() const { return mGridData.mGridClass == GridClass::PointIndex; }
5720 __hostdev__ bool isGridIndex() const { return mGridData.mGridClass == GridClass::IndexGrid; }
5721 __hostdev__ bool isPointData() const { return mGridData.mGridClass == GridClass::PointData; }
5722 __hostdev__ bool isVoxelBVH() const { return mGridData.mGridClass == GridClass::VoxelBVH; }
5723 __hostdev__ bool isMask() const { return mGridData.mGridClass == GridClass::Topology; }
5724 __hostdev__ bool isUnknown() const { return mGridData.mGridClass == GridClass::Unknown; }
5725 __hostdev__ bool hasMinMax() const { return mGridData.mFlags.isMaskOn(GridFlags::HasMinMax); }
5726 __hostdev__ bool hasBBox() const { return mGridData.mFlags.isMaskOn(GridFlags::HasBBox); }
5727 __hostdev__ bool hasLongGridName() const { return mGridData.mFlags.isMaskOn(GridFlags::HasLongGridName); }
5728 __hostdev__ bool hasAverage() const { return mGridData.mFlags.isMaskOn(GridFlags::HasAverage); }
5729 __hostdev__ bool hasStdDeviation() const { return mGridData.mFlags.isMaskOn(GridFlags::HasStdDeviation); }
5730 __hostdev__ bool isBreadthFirst() const { return mGridData.mFlags.isMaskOn(GridFlags::IsBreadthFirst); }
5731 __hostdev__ uint64_t gridSize() const { return mGridData.mGridSize; }
5732 __hostdev__ uint32_t gridIndex() const { return mGridData.mGridIndex; }
5733 __hostdev__ uint32_t gridCount() const { return mGridData.mGridCount; }
5734 __hostdev__ const char* shortGridName() const { return mGridData.mGridName; }
5735 __hostdev__ const Map& map() const { return mGridData.mMap; }
5736 __hostdev__ const Vec3dBBox& worldBBox() const { return mGridData.mWorldBBox; }
5737 __hostdev__ const CoordBBox& indexBBox() const { return mIndexBBox; }
5738 __hostdev__ Vec3d voxelSize() const { return mGridData.mVoxelSize; }
5739 __hostdev__ uint32_t blindDataCount() const { return mGridData.mBlindMetadataCount; }
5740 __hostdev__ uint64_t activeVoxelCount() const { return mTreeData.mVoxelCount; }
5741 __hostdev__ const uint32_t& activeTileCount(uint32_t level) const { return mTreeData.mTileCount[level - 1]; }
5742 __hostdev__ uint32_t nodeCount(uint32_t level) const { return mTreeData.mNodeCount[level]; }
5743 __hostdev__ const Checksum& checksum() const { return mGridData.mChecksum; }
5744 __hostdev__ uint32_t rootTableSize() const { return mRootTableSize; }
5745 __hostdev__ bool isEmpty() const { return mRootTableSize == 0; }
5746 __hostdev__ Version version() const { return mGridData.mVersion; }
5747}; // GridMetaData
5748
5749/// @brief Class to access points at a specific voxel location
5750///
5751/// @note If GridClass::PointIndex AttT should be uint32_t and if GridClass::PointData Vec3f
5752template<typename AttT, typename BuildT = uint32_t>
5754{
5755 using AccT = DefaultReadAccessor<BuildT>;
5756 const NanoGrid<BuildT>& mGrid;
5757 const AttT* mData;
5758
5759public:
5761 : AccT(grid.tree().root())
5762 , mGrid(grid)
5763 , mData(grid.template getBlindData<AttT>(0))
5764 {
5765 NANOVDB_ASSERT(grid.gridType() == toGridType<BuildT>());
5768 }
5769
5770 /// @brief return true if this access was initialized correctly
5771 __hostdev__ operator bool() const { return mData != nullptr; }
5772
5773 __hostdev__ const NanoGrid<BuildT>& grid() const { return mGrid; }
5774
5775 /// @brief Return the total number of point in the grid and set the
5776 /// iterators to the complete range of points.
5777 __hostdev__ uint64_t gridPoints(const AttT*& begin, const AttT*& end) const
5778 {
5779 const uint64_t count = mGrid.blindMetaData(0u).mValueCount;
5780 begin = mData;
5781 end = begin + count;
5782 return count;
5783 }
5784 /// @brief Return the number of points in the leaf node containing the coordinate @a ijk.
5785 /// If this return value is larger than zero then the iterators @a begin and @a end
5786 /// will point to all the attributes contained within that leaf node.
5787 __hostdev__ uint64_t leafPoints(const Coord& ijk, const AttT*& begin, const AttT*& end) const
5788 {
5789 auto* leaf = this->probeLeaf(ijk);
5790 if (leaf == nullptr) {
5791 return 0;
5792 }
5793 begin = mData + leaf->minimum();
5794 end = begin + leaf->maximum();
5795 return leaf->maximum();
5796 }
5797
5798 /// @brief get iterators over attributes to points at a specific voxel location
5799 __hostdev__ uint64_t voxelPoints(const Coord& ijk, const AttT*& begin, const AttT*& end) const
5800 {
5801 begin = end = nullptr;
5802 if (auto* leaf = this->probeLeaf(ijk)) {
5803 const uint32_t offset = NanoLeaf<BuildT>::CoordToOffset(ijk);
5804 if (leaf->isActive(offset)) {
5805 begin = mData + leaf->minimum();
5806 end = begin + leaf->getValue(offset);
5807 if (offset > 0u)
5808 begin += leaf->getValue(offset - 1);
5809 }
5810 }
5811 return end - begin;
5812 }
5813}; // PointAccessor
5814
5815template<typename AttT>
5816class PointAccessor<AttT, Point> : public DefaultReadAccessor<Point>
5817{
5818 using AccT = DefaultReadAccessor<Point>;
5819 const NanoGrid<Point>& mGrid;
5820 const AttT* mData;
5821
5822public:
5824 : AccT(grid.tree().root())
5825 , mGrid(grid)
5826 , mData(grid.template getBlindData<AttT>(0))
5827 {
5828 NANOVDB_ASSERT(mData);
5835 }
5836
5837 /// @brief return true if this access was initialized correctly
5838 __hostdev__ operator bool() const { return mData != nullptr; }
5839
5840 __hostdev__ const NanoGrid<Point>& grid() const { return mGrid; }
5841
5842 /// @brief Return the total number of point in the grid and set the
5843 /// iterators to the complete range of points.
5844 __hostdev__ uint64_t gridPoints(const AttT*& begin, const AttT*& end) const
5845 {
5846 const uint64_t count = mGrid.blindMetaData(0u).mValueCount;
5847 begin = mData;
5848 end = begin + count;
5849 return count;
5850 }
5851 /// @brief Return the number of points in the leaf node containing the coordinate @a ijk.
5852 /// If this return value is larger than zero then the iterators @a begin and @a end
5853 /// will point to all the attributes contained within that leaf node.
5854 __hostdev__ uint64_t leafPoints(const Coord& ijk, const AttT*& begin, const AttT*& end) const
5855 {
5856 auto* leaf = this->probeLeaf(ijk);
5857 if (leaf == nullptr)
5858 return 0;
5859 begin = mData + leaf->offset();
5860 end = begin + leaf->pointCount();
5861 return leaf->pointCount();
5862 }
5863
5864 /// @brief get iterators over attributes to points at a specific voxel location
5865 __hostdev__ uint64_t voxelPoints(const Coord& ijk, const AttT*& begin, const AttT*& end) const
5866 {
5867 if (auto* leaf = this->probeLeaf(ijk)) {
5868 const uint32_t n = NanoLeaf<Point>::CoordToOffset(ijk);
5869 if (leaf->isActive(n)) {
5870 begin = mData + leaf->first(n);
5871 end = mData + leaf->last(n);
5872 return end - begin;
5873 }
5874 }
5875 begin = end = nullptr;
5876 return 0u; // no leaf or inactive voxel
5877 }
5878}; // PointAccessor<AttT, Point>
5879
5880/// @brief Class to access values in channels at a specific voxel location.
5881///
5882/// @note The ChannelT template parameter can be either const and non-const.
5883template<typename ChannelT, typename IndexT = ValueIndex>
5885{
5886 static_assert(BuildTraits<IndexT>::is_index, "Expected an index build type");
5887 using BaseT = DefaultReadAccessor<IndexT>;
5888
5889 const NanoGrid<IndexT>& mGrid;
5890 ChannelT* mChannel;
5891
5892public:
5893 using ValueType = ChannelT;
5896
5897 /// @brief Ctor from an IndexGrid and an integer ID of an internal channel
5898 /// that is assumed to exist as blind data in the IndexGrid.
5899 __hostdev__ ChannelAccessor(const NanoGrid<IndexT>& grid, uint32_t channelID = 0u)
5900 : BaseT(grid.tree().root())
5901 , mGrid(grid)
5902 , mChannel(nullptr)
5903 {
5904 NANOVDB_ASSERT(isIndex(grid.gridType()));
5906 this->setChannel(channelID);
5907 }
5908
5909 /// @brief Ctor from an IndexGrid and an external channel
5910 __hostdev__ ChannelAccessor(const NanoGrid<IndexT>& grid, ChannelT* channelPtr)
5911 : BaseT(grid.tree().root())
5912 , mGrid(grid)
5913 , mChannel(channelPtr)
5914 {
5915 NANOVDB_ASSERT(isIndex(grid.gridType()));
5917 }
5918
5919 /// @brief return true if this access was initialized correctly
5920 __hostdev__ operator bool() const { return mChannel != nullptr; }
5921
5922 /// @brief Return a const reference to the IndexGrid
5923 __hostdev__ const NanoGrid<IndexT>& grid() const { return mGrid; }
5924
5925 /// @brief Return a const reference to the tree of the IndexGrid
5926 __hostdev__ const TreeType& tree() const { return mGrid.tree(); }
5927
5928 /// @brief Return a vector of the axial voxel sizes
5929 __hostdev__ const Vec3d& voxelSize() const { return mGrid.voxelSize(); }
5930
5931 /// @brief Return total number of values indexed by the IndexGrid
5932 __hostdev__ const uint64_t& valueCount() const { return mGrid.valueCount(); }
5933
5934 /// @brief Change to an external channel
5935 /// @return Pointer to channel data
5936 __hostdev__ ChannelT* setChannel(ChannelT* channelPtr) {return mChannel = channelPtr;}
5937
5938 /// @brief Change to an internal channel, assuming it exists as as blind data
5939 /// in the IndexGrid.
5940 /// @return Pointer to channel data, which could be NULL if channelID is out of range or
5941 /// if ChannelT does not match the value type of the blind data
5942 __hostdev__ ChannelT* setChannel(uint32_t channelID)
5943 {
5944 return mChannel = const_cast<ChannelT*>(mGrid.template getBlindData<ChannelT>(channelID));
5945 }
5946
5947 /// @brief Return the linear offset into a channel that maps to the specified coordinate
5948 __hostdev__ uint64_t getIndex(const math::Coord& ijk) const { return BaseT::getValue(ijk); }
5949 __hostdev__ uint64_t idx(int i, int j, int k) const { return BaseT::getValue(math::Coord(i, j, k)); }
5950
5951 /// @brief Return the value from a cached channel that maps to the specified coordinate
5952 __hostdev__ ChannelT& getValue(const math::Coord& ijk) const { return mChannel[BaseT::getValue(ijk)]; }
5953 __hostdev__ ChannelT& operator()(const math::Coord& ijk) const { return this->getValue(ijk); }
5954 __hostdev__ ChannelT& operator()(int i, int j, int k) const { return this->getValue(math::Coord(i, j, k)); }
5955
5956 /// @brief return the state and updates the value of the specified voxel
5958 {
5959 uint64_t idx;
5960 const bool isActive = BaseT::probeValue(ijk, idx);
5961 v = mChannel[idx];
5962 return isActive;
5963 }
5964 /// @brief Return the value from a specified channel that maps to the specified coordinate
5965 ///
5966 /// @note The template parameter can be either const or non-const
5967 template<typename T>
5968 __hostdev__ T& getValue(const math::Coord& ijk, T* channelPtr) const { return channelPtr[BaseT::getValue(ijk)]; }
5969
5970}; // ChannelAccessor
5971
5972/// @brief Generic Accessor type that maps to either a ReadAccessor or ChannelAccessor
5973/// @tparam BuildT Build type, e.g. float or ValueOnIndex
5974/// @tparam ValueT Value type, e.g. float or Vec3f
5975template <typename BuildT, typename ValueT>
5978
5979/// @brief Generic template functions that return an Accessor to either an index grid or a regular grid
5980template <typename GridT, typename ValueT>
5981inline __hostdev__ auto getAccessor(const GridT &grid, ValueT *sideCar = nullptr)
5982{
5983 using BuildT = typename GridT::BuildType;
5984 if constexpr(BuildTraits<BuildT>::is_index) {
5985 return sideCar ? ChannelAccessor<ValueT, BuildT>(grid, sideCar) : ChannelAccessor<ValueT, BuildT>(grid);
5986 } else {
5987 static_assert(util::is_same<ValueT, typename GridT::ValueType>::value, "wrong ValueT for regular GridT");
5988 return DefaultReadAccessor<BuildT>(grid);
5989 }
5990}
5991
5992#if 0
5993// This MiniGridHandle class is only included as a stand-alone example. Note that aligned_alloc is a C++17 feature!
5994// Normally we recommend using GridHandle defined in util/GridHandle.h but this minimal implementation could be an
5995// alternative when using the IO methods defined below.
5996struct MiniGridHandle {
5997 struct BufferType {
5998 uint8_t *data;
5999 uint64_t size;
6000 BufferType(uint64_t n=0) : data(std::aligned_alloc(NANOVDB_DATA_ALIGNMENT, n)), size(n) {assert(isValid(data));}
6001 BufferType(BufferType &&other) : data(other.data), size(other.size) {other.data=nullptr; other.size=0;}
6002 ~BufferType() {std::free(data);}
6003 BufferType& operator=(const BufferType &other) = delete;
6004 BufferType& operator=(BufferType &&other){data=other.data; size=other.size; other.data=nullptr; other.size=0; return *this;}
6005 static BufferType create(size_t n, BufferType* dummy = nullptr) {return BufferType(n);}
6006 } buffer;
6007 MiniGridHandle(BufferType &&buf) : buffer(std::move(buf)) {}
6008 const uint8_t* data() const {return buffer.data;}
6009};// MiniGridHandle
6010#endif
6011
6012namespace io {
6013
6014/// @brief Define compression codecs
6015///
6016/// @note NONE is the default, ZIP is slow but compact and BLOSC offers a great balance.
6017///
6018/// @throw NanoVDB optionally supports ZIP and BLOSC compression and will throw an exception
6019/// if its support is required but missing.
6020enum class Codec : uint16_t { NONE = 0,
6021 ZIP = 1,
6023 End = 3,
6024 StrLen = 6 + End };
6025
6026__hostdev__ inline const char* toStr(char *dst, Codec codec)
6027{
6028 switch (codec){
6029 case Codec::NONE: return util::strcpy(dst, "NONE");
6030 case Codec::ZIP: return util::strcpy(dst, "ZIP");
6031 case Codec::BLOSC : return util::strcpy(dst, "BLOSC");// StrLen = 5 + 1 + End
6032 default: return util::strcpy(dst, "END");
6033 }
6034}
6035
6036__hostdev__ inline Codec toCodec(const char *str)
6037{
6038 if (util::streq(str, "none")) return Codec::NONE;
6039 if (util::streq(str, "zip")) return Codec::ZIP;
6040 if (util::streq(str, "blosc")) return Codec::BLOSC;
6041 return Codec::End;
6042}
6043
6044/// @brief Data encoded at the head of each segment of a file or stream.
6045///
6046/// @note A file or stream is composed of one or more segments that each contain
6047// one or more grids.
6048struct FileHeader {// 16 bytes
6049 uint64_t magic;// 8 bytes
6050 Version version;// 4 bytes version numbers
6051 uint16_t gridCount;// 2 bytes
6052 Codec codec;// 2 bytes
6054}; // FileHeader ( 16 bytes = 2 words )
6055
6056// @brief Data encoded for each of the grids associated with a segment.
6057// Grid size in memory (uint64_t) |
6058// Grid size on disk (uint64_t) |
6059// Grid name hash key (uint64_t) |
6060// Numer of active voxels (uint64_t) |
6061// Grid type (uint32_t) |
6062// Grid class (uint32_t) |
6063// Characters in grid name (uint32_t) |
6064// AABB in world space (2*3*double) | one per grid in file
6065// AABB in index space (2*3*int) |
6066// Size of a voxel in world units (3*double) |
6067// Byte size of the grid name (uint32_t) |
6068// Number of nodes per level (4*uint32_t) |
6069// Numer of active tiles per level (3*uint32_t) |
6070// Codec for file compression (uint16_t) |
6071// Padding due to 8B alignment (uint16_t) |
6072// Version number (uint32_t) |
6074{// 176 bytes
6075 uint64_t gridSize, fileSize, nameKey, voxelCount; // 4 * 8 = 32B.
6078 Vec3dBBox worldBBox; // 2 * 3 * 8 = 48B.
6079 CoordBBox indexBBox; // 2 * 3 * 4 = 24B.
6081 uint32_t nameSize; // 4B.
6082 uint32_t nodeCount[4]; //4 x 4 = 16B
6083 uint32_t tileCount[3];// 3 x 4 = 12B
6085 uint16_t blindDataCount;// 2B
6087}; // FileMetaData
6088
6089// the following code block uses std and therefore needs to be ignored by CUDA and HIP
6090#if !defined(__CUDA_ARCH__) && !defined(__HIP__)
6091
6092// Note that starting with version 32.6.0 it is possible to write and read raw grid buffers to
6093// files, e.g. os.write((const char*)&buffer.data(), buffer.size()) or more conveniently as
6094// handle.write(fileName). In addition to this simple approach we offer the methods below to
6095// write traditional uncompressed nanovdb files that unlike raw files include metadata that
6096// is used for tools like nanovdb_print.
6097
6098///
6099/// @brief This is a standalone alternative to io::writeGrid(...,Codec::NONE) defined in util/IO.h
6100/// Unlike the latter this function has no dependencies at all, not even NanoVDB.h, so it also
6101/// works if client code only includes PNanoVDB.h!
6102///
6103/// @details Writes a raw NanoVDB buffer, possibly with multiple grids, to a stream WITHOUT compression.
6104/// It follows all the conventions in util/IO.h so the stream can be read by all existing client
6105/// code of NanoVDB.
6106///
6107/// @note This method will always write uncompressed grids to the stream, i.e. Blosc or ZIP compression
6108/// is never applied! This is a fundamental limitation and feature of this standalone function.
6109///
6110/// @throw std::invalid_argument if buffer does not point to a valid NanoVDB grid.
6111///
6112/// @warning This is pretty ugly code that involves lots of pointer and bit manipulations - not for the faint of heart :)
6113template<typename StreamT> // StreamT class must support: "void write(const char*, size_t)"
6114void writeUncompressedGrid(StreamT& os, const GridData* gridData, bool raw = false)
6115{
6118 if (!raw) {// segment with a single grid: FileHeader, FileMetaData, gridName, Grid
6119#ifdef NANOVDB_USE_NEW_MAGIC_NUMBERS
6120 FileHeader head{NANOVDB_MAGIC_FILE, gridData->mVersion, 1u, Codec::NONE};
6121#else
6122 FileHeader head{NANOVDB_MAGIC_NUMB, gridData->mVersion, 1u, Codec::NONE};
6123#endif
6124 const char* gridName = gridData->gridName();
6125 const uint32_t nameSize = util::strlen(gridName) + 1;// include '\0'
6126 const TreeData* treeData = (const TreeData*)(gridData->treePtr());
6127 NANOVDB_ASSERT(gridData->mBlindMetadataCount <= uint32_t( 1u << 16 ));// due to uint32_t -> uin16_t conversion
6128 FileMetaData meta{gridData->mGridSize, gridData->mGridSize, 0u, treeData->mVoxelCount,
6129 gridData->mGridType, gridData->mGridClass, gridData->mWorldBBox,
6130 treeData->bbox(), gridData->mVoxelSize, nameSize,
6131 {treeData->mNodeCount[0], treeData->mNodeCount[1], treeData->mNodeCount[2], 1u},
6132 {treeData->mTileCount[0], treeData->mTileCount[1], treeData->mTileCount[2]},
6133 Codec::NONE, uint16_t(gridData->mBlindMetadataCount), gridData->mVersion }; // FileMetaData
6134 os.write((const char*)&head, sizeof(FileHeader)); // write header
6135 os.write((const char*)&meta, sizeof(FileMetaData)); // write meta data
6136 os.write(gridName, nameSize); // write grid name
6137 }
6138 if (gridData->mGridCount!=1 || gridData->mGridIndex != 0) {
6139 GridData data;
6140 data = *gridData;// deep copy
6141 data.mGridIndex = 0;
6142 data.mGridCount = 1;
6143 os.write((const char*)&data, sizeof(GridData));
6144 os.write((const char*)gridData + sizeof(GridData), gridData->mGridSize - sizeof(GridData));
6145 } else {
6146 os.write((const char*)gridData, gridData->mGridSize);// write the grid
6147 }
6148}// writeUncompressedGrid
6149
6150/// @brief Write an IndexGrid to a stream and append blind data
6151/// @tparam StreamT Type of stream to write the IndexGrid and blind data to
6152/// @tparam ValueT Type of the blind data
6153/// @param os Output stream to write to
6154/// @param gridData GridData containing an IndexGrid WITHOUT existing blind data
6155/// @param blindData Raw point to array of blind data
6156/// @param semantic GridBlindDataSemantic of the blind data
6157/// @param raw If true the IndexGrid and blind data are streamed raw, i.e. without a file header.
6158template<typename StreamT, typename ValueT> // StreamT class must support: "void write(const char*, size_t)"
6159void writeUncompressedGrid(StreamT& os, const GridData* gridData, const ValueT *blindData,
6160 GridBlindDataSemantic semantic = GridBlindDataSemantic::Unknown, bool raw = false)
6161{
6164 NANOVDB_ASSERT(blindData);
6165
6166 char str[256];
6167 if (gridData->mGridClass != GridClass::IndexGrid) {
6168 fprintf(stderr, "nanovdb::writeUncompressedGrid: expected an IndexGrid but got \"%s\"\n", toStr(str, gridData->mGridClass));
6169 exit(EXIT_FAILURE);
6170 } else if (gridData->mBlindMetadataCount != 0u) {// to-do: allow for existing blind data in grid
6171 fprintf(stderr, "nanovdb::writeUncompressedGrid: index grid already has \"%i\" blind data\n", gridData->mBlindMetadataCount);
6172 exit(EXIT_FAILURE);
6173 }
6174 const size_t gridSize = gridData->mGridSize + sizeof(GridBlindMetaData) + gridData->mData1*sizeof(ValueT);
6175 if (!raw) {// segment with a single grid: FileHeader, FileMetaData, gridName, Grid
6176#ifdef NANOVDB_USE_NEW_MAGIC_NUMBERS
6177 FileHeader head{NANOVDB_MAGIC_FILE, gridData->mVersion, 1u/*grid count*/, Codec::NONE};
6178#else
6179 FileHeader head{NANOVDB_MAGIC_NUMB, gridData->mVersion, 1u/*grid count*/, Codec::NONE};
6180#endif
6181 const char* gridName = gridData->gridName();
6182 const uint32_t nameSize = util::strlen(gridName) + 1;// include '\0'
6183 const TreeData* treeData = (const TreeData*)(gridData->treePtr());
6184 FileMetaData meta{gridSize, gridSize, 0u, treeData->mVoxelCount,
6185 gridData->mGridType, gridData->mGridClass, gridData->mWorldBBox,
6186 treeData->bbox(), gridData->mVoxelSize, nameSize,
6187 {treeData->mNodeCount[0], treeData->mNodeCount[1], treeData->mNodeCount[2], 1u},
6188 {treeData->mTileCount[0], treeData->mTileCount[1], treeData->mTileCount[2]},
6189 Codec::NONE, 1u, gridData->mVersion }; // FileMetaData
6190 os.write((const char*)&head, sizeof(FileHeader)); // write header
6191 os.write((const char*)&meta, sizeof(FileMetaData)); // write meta data
6192 os.write(gridName, nameSize); // write grid name
6193 }// if (!raw)
6194 GridData data;
6195 data = *gridData;// deep copy
6196 data.mGridIndex = 0;
6197 data.mGridCount = 1;
6198 data.mGridSize = gridSize;// increment by blind data + meta data
6199 data.mBlindMetadataCount = 1u;
6200 data.mBlindMetadataOffset = gridData->mGridSize;
6201 os.write((const char*)&data, sizeof(GridData));
6202 os.write((const char*)gridData + sizeof(GridData), gridData->mGridSize - sizeof(GridData));// write the IndexGrid
6203 GridBlindMetaData meta(sizeof(GridBlindMetaData), gridData->mData1, sizeof(ValueT),
6205 meta.setName("channel_0");
6206 os.write((const char*)&meta, sizeof(GridBlindMetaData));
6207 os.write((const char*)blindData, gridData->mData1*sizeof(ValueT));
6208}// writeUncompressedGrid
6209
6210/// @brief write multiple NanoVDB grids to a single file, without compression.
6211/// @note To write all grids in a single GridHandle simply use handle.write("fieNane")
6212template<typename GridHandleT, template<typename...> class VecT>
6213void writeUncompressedGrids(const char* fileName, const VecT<GridHandleT>& handles, bool raw = false)
6214{
6215#ifdef NANOVDB_USE_IOSTREAMS // use this to switch between std::ofstream or FILE implementations
6216 std::ofstream os(fileName, std::ios::out | std::ios::binary | std::ios::trunc);
6217#else
6218 struct StreamT {
6219 FILE* fptr;
6220 StreamT(const char* name) { fptr = fopen(name, "wb"); }
6221 ~StreamT() { fclose(fptr); }
6222 void write(const char* data, size_t n) { fwrite(data, 1, n, fptr); }
6223 bool is_open() const { return fptr != NULL; }
6224 } os(fileName);
6225#endif
6226 if (!os.is_open()) {
6227 fprintf(stderr, "nanovdb::writeUncompressedGrids: Unable to open file \"%s\"for output\n", fileName);
6228 exit(EXIT_FAILURE);
6229 }
6230 for (auto& h : handles) {
6231 for (uint32_t n=0; n<h.gridCount(); ++n) writeUncompressedGrid(os, h.gridData(n), raw);
6232 }
6233} // writeUncompressedGrids
6234
6235/// @brief read all uncompressed grids from a stream and return their handles.
6236///
6237/// @throw std::invalid_argument if stream does not contain a single uncompressed valid NanoVDB grid
6238///
6239/// @details StreamT class must support: "bool read(char*, size_t)" and "void skip(uint32_t)"
6240template<typename GridHandleT, typename StreamT, template<typename...> class VecT>
6241VecT<GridHandleT> readUncompressedGrids(StreamT& is, const typename GridHandleT::BufferType& pool = typename GridHandleT::BufferType())
6242{
6243 VecT<GridHandleT> handles;
6244 GridData data;
6245 is.read((char*)&data, sizeof(GridData));
6246 if (data.isValid()) {// stream contains a raw grid buffer
6247 uint64_t size = data.mGridSize, sum = 0u;
6248 while(data.mGridIndex + 1u < data.mGridCount) {
6249 is.skip(data.mGridSize - sizeof(GridData));// skip grid
6250 is.read((char*)&data, sizeof(GridData));// read sizeof(GridData) bytes
6251 sum += data.mGridSize;
6252 }
6253 is.skip(-int64_t(sum + sizeof(GridData)));// rewind to start
6254 auto buffer = GridHandleT::BufferType::create(size + sum, &pool);
6255 is.read((char*)(buffer.data()), buffer.size());
6256 handles.emplace_back(std::move(buffer));
6257 } else {// Header0, MetaData0, gridName0, Grid0...HeaderN, MetaDataN, gridNameN, GridN
6258 is.skip(-sizeof(GridData));// rewind
6259 FileHeader head;
6260 while(is.read((char*)&head, sizeof(FileHeader))) {
6261 if (!head.isValid()) {
6262 fprintf(stderr, "nanovdb::readUncompressedGrids: invalid magic number = \"%s\"\n", (const char*)&(head.magic));
6263 exit(EXIT_FAILURE);
6264 } else if (!head.version.isCompatible()) {
6265 char str[20];
6266 fprintf(stderr, "nanovdb::readUncompressedGrids: invalid major version = \"%s\"\n", toStr(str, head.version));
6267 exit(EXIT_FAILURE);
6268 } else if (head.codec != Codec::NONE) {
6269 char str[8];
6270 fprintf(stderr, "nanovdb::readUncompressedGrids: invalid codec = \"%s\"\n", toStr(str, head.codec));
6271 exit(EXIT_FAILURE);
6272 }
6273 FileMetaData meta;
6274 for (uint16_t i = 0; i < head.gridCount; ++i) { // read all grids in segment
6275 is.read((char*)&meta, sizeof(FileMetaData));// read meta data
6276 is.skip(meta.nameSize); // skip grid name
6277 auto buffer = GridHandleT::BufferType::create(meta.gridSize, &pool);
6278 is.read((char*)buffer.data(), meta.gridSize);// read grid
6279 handles.emplace_back(std::move(buffer));
6280 }// loop over grids in segment
6281 }// loop over segments
6282 }
6283 return handles;
6284} // readUncompressedGrids
6285
6286/// @brief Read a multiple un-compressed NanoVDB grids from a file and return them as a vector.
6287template<typename GridHandleT, template<typename...> class VecT>
6288VecT<GridHandleT> readUncompressedGrids(const char* fileName, const typename GridHandleT::BufferType& buffer = typename GridHandleT::BufferType())
6289{
6290#ifdef NANOVDB_USE_IOSTREAMS // use this to switch between std::ifstream or FILE implementations
6291 struct StreamT : public std::ifstream {
6292 StreamT(const char* name) : std::ifstream(name, std::ios::in | std::ios::binary){}
6293 void skip(int64_t off) { this->seekg(off, std::ios_base::cur); }
6294 };
6295#else
6296 struct StreamT {
6297 FILE* fptr;
6298 StreamT(const char* name) { fptr = fopen(name, "rb"); }
6299 ~StreamT() { fclose(fptr); }
6300 bool read(char* data, size_t n) {
6301 size_t m = fread(data, 1, n, fptr);
6302 return n == m;
6303 }
6304 void skip(int64_t off) { fseek(fptr, (long int)off, SEEK_CUR); }
6305 bool is_open() const { return fptr != NULL; }
6306 };
6307#endif
6308 StreamT is(fileName);
6309 if (!is.is_open()) {
6310 fprintf(stderr, "nanovdb::readUncompressedGrids: Unable to open file \"%s\"for input\n", fileName);
6311 exit(EXIT_FAILURE);
6312 }
6314} // readUncompressedGrids
6315
6316#endif // if !defined(__CUDA_ARCH__) && !defined(__HIP__)
6317
6318} // namespace io
6319
6320// ----------------------------> Implementations of random access methods <--------------------------------------
6321
6322/**
6323* @brief Below is an example of a struct used for random get methods.
6324* @note All member methods, data, and types are mandatory.
6325* @code
6326 template<typename BuildT>
6327 struct GetOpT {
6328 using Type = typename BuildToValueMap<BuildT>::Type;// return type
6329 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6330 __hostdev__ static Type get(const NanoRoot<BuildT>& root, args...) { }
6331 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile& tile, args...) { }
6332 __hostdev__ static Type get(const NanoUpper<BuildT>& node, uint32_t n, args...) { }
6333 __hostdev__ static Type get(const NanoLower<BuildT>& node, uint32_t n, args...) { }
6334 __hostdev__ static Type get(const NanoLeaf<BuildT>& leaf, uint32_t n, args...) { }
6335 };
6336 @endcode
6337
6338 * @brief Below is an example of the struct used for random set methods
6339 * @note All member methods and data are mandatory.
6340 * @code
6341 template<typename BuildT>
6342 struct SetOpT {
6343 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6344 __hostdev__ static void set(NanoRoot<BuildT>& root, args...) { }
6345 __hostdev__ static void set(typename NanoRoot<BuildT>::Tile& tile, args...) { }
6346 __hostdev__ static void set(NanoUpper<BuildT>& node, uint32_t n, args...) { }
6347 __hostdev__ static void set(NanoLower<BuildT>& node, uint32_t n, args...) { }
6348 __hostdev__ static void set(NanoLeaf<BuildT>& leaf, uint32_t n, args...) { }
6349 };
6350 @endcode
6351**/
6352
6353/// @brief Implements Tree::getValue(math::Coord), i.e. return the value associated with a specific coordinate @c ijk.
6354/// @tparam BuildT Build type of the grid being called
6355/// @details The value at a coordinate either maps to the background, a tile value or a leaf value.
6356template<typename BuildT>
6358{
6360 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6361 __hostdev__ static Type get(const NanoRoot<BuildT>& root) { return root.mBackground; }
6362 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile& tile) { return tile.value; }
6363 __hostdev__ static Type get(const NanoUpper<BuildT>& node, uint32_t n) { return node.mTable[n].value; }
6364 __hostdev__ static Type get(const NanoLower<BuildT>& node, uint32_t n) { return node.mTable[n].value; }
6365 __hostdev__ static Type get(const NanoLeaf<BuildT>& leaf, uint32_t n) { return leaf.getValue(n); } // works with all build types
6366}; // GetValue<BuildT>
6367
6368template<typename BuildT>
6370{
6371 static_assert(!BuildTraits<BuildT>::is_special, "SetValue does not support special value types, e.g. Fp4, Fp8, Fp16, FpN");
6373 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6374 __hostdev__ static void set(NanoRoot<BuildT>&, const ValueT&) {} // no-op
6375 __hostdev__ static void set(typename NanoRoot<BuildT>::Tile& tile, const ValueT& v) { tile.value = v; }
6376 __hostdev__ static void set(NanoUpper<BuildT>& node, uint32_t n, const ValueT& v) { node.mTable[n].value = v; }
6377 __hostdev__ static void set(NanoLower<BuildT>& node, uint32_t n, const ValueT& v) { node.mTable[n].value = v; }
6378 __hostdev__ static void set(NanoLeaf<BuildT>& leaf, uint32_t n, const ValueT& v) { leaf.mValues[n] = v; }
6379}; // SetValue<BuildT>
6380
6381template<typename BuildT>
6383{
6384 static_assert(!BuildTraits<BuildT>::is_special, "SetVoxel does not support special value types. e.g. Fp4, Fp8, Fp16, FpN");
6386 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6387 __hostdev__ static void set(NanoRoot<BuildT>&, const ValueT&) {} // no-op
6388 __hostdev__ static void set(typename NanoRoot<BuildT>::Tile&, const ValueT&) {} // no-op
6389 __hostdev__ static void set(NanoUpper<BuildT>&, uint32_t, const ValueT&) {} // no-op
6390 __hostdev__ static void set(NanoLower<BuildT>&, uint32_t, const ValueT&) {} // no-op
6391 __hostdev__ static void set(NanoLeaf<BuildT>& leaf, uint32_t n, const ValueT& v) { leaf.mValues[n] = v; }
6392}; // SetVoxel<BuildT>
6393
6394/// @brief Implements Tree::isActive(math::Coord)
6395/// @tparam BuildT Build type of the grid being called
6396template<typename BuildT>
6398{
6399 using Type = bool;
6400 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6401 __hostdev__ static Type get(const NanoRoot<BuildT>&) { return false; }
6402 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile& tile) { return tile.state > 0; }
6403 __hostdev__ static Type get(const NanoUpper<BuildT>& node, uint32_t n) { return node.mValueMask.isOn(n); }
6404 __hostdev__ static Type get(const NanoLower<BuildT>& node, uint32_t n) { return node.mValueMask.isOn(n); }
6405 __hostdev__ static Type get(const NanoLeaf<BuildT>& leaf, uint32_t n) { return leaf.mValueMask.isOn(n); }
6406}; // GetState<BuildT>
6407
6408/// @brief Implements Tree::getDim(math::Coord)
6409/// @tparam BuildT Build type of the grid being called
6410template<typename BuildT>
6412{
6413 using Type = uint32_t;
6414 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6415 __hostdev__ static Type get(const NanoRoot<BuildT>&) { return 0u; } // background
6416 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile&) { return 4096u; }
6417 __hostdev__ static Type get(const NanoUpper<BuildT>&, uint32_t) { return 128u; }
6418 __hostdev__ static Type get(const NanoLower<BuildT>&, uint32_t) { return 8u; }
6419 __hostdev__ static Type get(const NanoLeaf<BuildT>&, uint32_t) { return 1u; }
6420}; // GetDim<BuildT>
6421
6422/// @brief Return the pointer to the leaf node that contains math::Coord. Implements Tree::probeLeaf(math::Coord)
6423/// @tparam BuildT Build type of the grid being called
6424template<typename BuildT>
6426{
6427 using Type = const NanoLeaf<BuildT>*;
6428 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6429 __hostdev__ static Type get(const NanoRoot<BuildT>&) { return nullptr; }
6430 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile&) { return nullptr; }
6431 __hostdev__ static Type get(const NanoUpper<BuildT>&, uint32_t) { return nullptr; }
6432 __hostdev__ static Type get(const NanoLower<BuildT>&, uint32_t) { return nullptr; }
6433 __hostdev__ static Type get(const NanoLeaf<BuildT>& leaf, uint32_t) { return &leaf; }
6434}; // GetLeaf<BuildT>
6435
6436/// @brief Return point to the lower internal node where math::Coord maps to one of its values, i.e. terminates
6437/// @tparam BuildT Build type of the grid being called
6438template<typename BuildT>
6440{
6441 using Type = const NanoLower<BuildT>*;
6442 static constexpr int LEVEL = 1;// minimum level for the descent during top-down traversal
6443 __hostdev__ static Type get(const NanoRoot<BuildT>&) { return nullptr; }
6444 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile&) { return nullptr; }
6445 __hostdev__ static Type get(const NanoUpper<BuildT>&, uint32_t) { return nullptr; }
6446 __hostdev__ static Type get(const NanoLower<BuildT>& node, uint32_t) { return &node; }
6447}; // GetLower<BuildT>
6448
6449/// @brief Return point to the upper internal node where math::Coord maps to one of its values, i.e. terminates
6450/// @tparam BuildT Build type of the grid being called
6451template<typename BuildT>
6453{
6454 using Type = const NanoUpper<BuildT>*;
6455 static constexpr int LEVEL = 2;// minimum level for the descent during top-down traversal
6456 __hostdev__ static Type get(const NanoRoot<BuildT>&) { return nullptr; }
6457 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile&) { return nullptr; }
6458 __hostdev__ static Type get(const NanoUpper<BuildT>& node, uint32_t) { return &node; }
6459}; // GetUpper<BuildT>
6460
6461/// @brief Return point to the root Tile where math::Coord maps to one of its values, i.e. terminates
6462/// @tparam BuildT Build type of the grid being called
6463template<typename BuildT>
6465{
6466 using Type = const typename NanoRoot<BuildT>::Tile*;
6467 static constexpr int LEVEL = 3;// minimum level for the descent during top-down traversal
6468 __hostdev__ static Type get(const NanoRoot<BuildT>&) { return nullptr; }
6469 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile &tile) { return &tile; }
6470}; // GetTile<BuildT>
6471
6472/// @brief Implements Tree::probeLeaf(math::Coord)
6473/// @tparam BuildT Build type of the grid being called
6474template<typename BuildT>
6476{
6477 using Type = bool;
6478 static constexpr int LEVEL = 0;// minimum level for the descent during top-down traversal
6481 {
6482 v = root.mBackground;
6483 return false;
6484 }
6485 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile& tile, ValueT& v)
6486 {
6487 v = tile.value;
6488 return tile.state > 0u;
6489 }
6490 __hostdev__ static Type get(const NanoUpper<BuildT>& node, uint32_t n, ValueT& v)
6491 {
6492 v = node.mTable[n].value;
6493 return node.mValueMask.isOn(n);
6494 }
6495 __hostdev__ static Type get(const NanoLower<BuildT>& node, uint32_t n, ValueT& v)
6496 {
6497 v = node.mTable[n].value;
6498 return node.mValueMask.isOn(n);
6499 }
6500 __hostdev__ static Type get(const NanoLeaf<BuildT>& leaf, uint32_t n, ValueT& v)
6501 {
6502 v = leaf.getValue(n);
6503 return leaf.mValueMask.isOn(n);
6504 }
6505}; // ProbeValue<BuildT>
6506
6507/// @brief Implements Tree::getNodeInfo(math::Coord)
6508/// @tparam BuildT Build type of the grid being called
6509template<typename BuildT>
6511{
6521 static constexpr int LEVEL = 0;
6524 {
6525 return NodeInfo{3u, NanoUpper<BuildT>::DIM, root.minimum(), root.maximum(), root.average(), root.stdDeviation(), root.bbox()};
6526 }
6527 __hostdev__ static Type get(const typename NanoRoot<BuildT>::Tile& tile)
6528 {
6529 return NodeInfo{3u, NanoUpper<BuildT>::DIM, tile.value, tile.value, static_cast<FloatType>(tile.value), 0, CoordBBox::createCube(tile.origin(), NanoUpper<BuildT>::DIM)};
6530 }
6531 __hostdev__ static Type get(const NanoUpper<BuildT>& node, uint32_t n)
6532 {
6533 return NodeInfo{2u, node.dim(), node.minimum(), node.maximum(), node.average(), node.stdDeviation(), node.bbox()};
6534 }
6535 __hostdev__ static Type get(const NanoLower<BuildT>& node, uint32_t n)
6536 {
6537 return NodeInfo{1u, node.dim(), node.minimum(), node.maximum(), node.average(), node.stdDeviation(), node.bbox()};
6538 }
6539 __hostdev__ static Type get(const NanoLeaf<BuildT>& leaf, uint32_t n)
6540 {
6541 return NodeInfo{0u, leaf.dim(), leaf.minimum(), leaf.maximum(), leaf.average(), leaf.stdDeviation(), leaf.bbox()};
6542 }
6543}; // GetNodeInfo<BuildT>
6544
6545} // namespace nanovdb ===================================================================
6546
6547#endif // end of NANOVDB_NANOVDB_H_HAS_BEEN_INCLUDED
#define NANOVDB_MAGIC_FILE
Definition NanoVDB.h:141
#define NANOVDB_MAGIC_GRID
Definition NanoVDB.h:140
#define NANOVDB_MINOR_VERSION_NUMBER
Definition NanoVDB.h:147
#define NANOVDB_DATA_ALIGNMENT
Definition NanoVDB.h:133
#define NANOVDB_MAJOR_VERSION_NUMBER
Definition NanoVDB.h:146
#define NANOVDB_MAGIC_NUMB
Definition NanoVDB.h:139
#define NANOVDB_PATCH_VERSION_NUMBER
Definition NanoVDB.h:148
Definition NanoVDB.h:958
BitFlags(std::initializer_list< uint8_t > list)
Definition NanoVDB.h:966
__hostdev__ void setBitOn(std::initializer_list< uint8_t > list)
Definition NanoVDB.h:996
__hostdev__ Type getFlags() const
Definition NanoVDB.h:988
__hostdev__ void setOn()
Definition NanoVDB.h:990
BitFlags(Type mask)
Definition NanoVDB.h:965
__hostdev__ bool isMaskOn(MaskT mask) const
Definition NanoVDB.h:1030
__hostdev__ void setBitOff(uint8_t bit)
Definition NanoVDB.h:994
__hostdev__ void setOff()
Definition NanoVDB.h:991
__hostdev__ bool isBitOn(uint8_t bit) const
Definition NanoVDB.h:1027
BitFlags()
Definition NanoVDB.h:964
__hostdev__ void setMaskOff(MaskT mask)
Definition NanoVDB.h:1008
__hostdev__ void initBit(std::initializer_list< uint8_t > list)
Definition NanoVDB.h:977
__hostdev__ bool isMaskOff(std::initializer_list< MaskT > list) const
return true if any of the masks in the list are off
Definition NanoVDB.h:1044
__hostdev__ void initMask(std::initializer_list< MaskT > list)
Definition NanoVDB.h:983
__hostdev__ void setBit(uint8_t bit, bool on)
Definition NanoVDB.h:1021
__hostdev__ void setBitOn(uint8_t bit)
Definition NanoVDB.h:993
__hostdev__ Type & data()
Definition NanoVDB.h:976
BitFlags(std::initializer_list< MaskT > list)
Definition NanoVDB.h:971
__hostdev__ void setMask(MaskT mask, bool on)
Definition NanoVDB.h:1023
__hostdev__ bool isOff() const
Definition NanoVDB.h:1026
__hostdev__ bool isBitOff(uint8_t bit) const
Definition NanoVDB.h:1028
__hostdev__ void setBitOff(std::initializer_list< uint8_t > list)
Definition NanoVDB.h:1000
__hostdev__ void setMaskOff(std::initializer_list< MaskT > list)
Definition NanoVDB.h:1016
__hostdev__ bool isMaskOn(std::initializer_list< MaskT > list) const
return true if any of the masks in the list are on
Definition NanoVDB.h:1035
__hostdev__ Type data() const
Definition NanoVDB.h:975
__hostdev__ bool isOn() const
Definition NanoVDB.h:1025
__hostdev__ void setMaskOn(std::initializer_list< MaskT > list)
Definition NanoVDB.h:1011
__hostdev__ bool isMaskOff(MaskT mask) const
Definition NanoVDB.h:1032
__hostdev__ void setMaskOn(MaskT mask)
Definition NanoVDB.h:1006
decltype(mFlags) Type
Definition NanoVDB.h:963
__hostdev__ BitFlags & operator=(Type n)
required for backwards compatibility
Definition NanoVDB.h:1052
Class to access values in channels at a specific voxel location.
Definition NanoVDB.h:5885
__hostdev__ ChannelT & operator()(int i, int j, int k) const
Definition NanoVDB.h:5954
__hostdev__ ChannelT * setChannel(uint32_t channelID)
Change to an internal channel, assuming it exists as as blind data in the IndexGrid.
Definition NanoVDB.h:5942
NanoTree< IndexT > TreeType
Definition NanoVDB.h:5894
__hostdev__ uint64_t getIndex(const math::Coord &ijk) const
Return the linear offset into a channel that maps to the specified coordinate.
Definition NanoVDB.h:5948
__hostdev__ ChannelAccessor(const NanoGrid< IndexT > &grid, ChannelT *channelPtr)
Ctor from an IndexGrid and an external channel.
Definition NanoVDB.h:5910
__hostdev__ bool probeValue(const math::Coord &ijk, typename util::remove_const< ChannelT >::type &v) const
return the state and updates the value of the specified voxel
Definition NanoVDB.h:5957
__hostdev__ const uint64_t & valueCount() const
Return total number of values indexed by the IndexGrid.
Definition NanoVDB.h:5932
__hostdev__ ChannelT & operator()(const math::Coord &ijk) const
Definition NanoVDB.h:5953
__hostdev__ uint64_t idx(int i, int j, int k) const
Definition NanoVDB.h:5949
__hostdev__ const TreeType & tree() const
Definition NanoVDB.h:5926
__hostdev__ ChannelAccessor(const NanoGrid< IndexT > &grid, uint32_t channelID=0u)
Ctor from an IndexGrid and an integer ID of an internal channel that is assumed to exist as blind dat...
Definition NanoVDB.h:5899
__hostdev__ const NanoGrid< IndexT > & grid() const
Definition NanoVDB.h:5923
ChannelT ValueType
Definition NanoVDB.h:5893
ChannelAccessor< ChannelT, IndexT > AccessorType
Definition NanoVDB.h:5895
__hostdev__ const Vec3d & voxelSize() const
Return a vector of the axial voxel sizes.
Definition NanoVDB.h:5929
__hostdev__ T & getValue(const math::Coord &ijk, T *channelPtr) const
Return the value from a specified channel that maps to the specified coordinate.
Definition NanoVDB.h:5968
__hostdev__ ChannelT * setChannel(ChannelT *channelPtr)
Definition NanoVDB.h:5936
__hostdev__ ChannelT & getValue(const math::Coord &ijk) const
Return the value from a cached channel that maps to the specified coordinate.
Definition NanoVDB.h:5952
Class that encapsulates two CRC32 checksums, one for the Grid, Tree and Root node meta data and one f...
Definition NanoVDB.h:1870
__hostdev__ Checksum(uint64_t checksum, CheckMode mode=CheckMode::Full)
Definition NanoVDB.h:1893
__hostdev__ bool isFull() const
return true if the 64 bit checksum is fill, i.e. of both had and nodes
Definition NanoVDB.h:1919
__hostdev__ Checksum(uint32_t head, uint32_t tail)
Constructor that allows the two 32bit checksums to be initiated explicitly.
Definition NanoVDB.h:1888
__hostdev__ uint64_t checksum() const
return the 64 bit checksum of this instance
Definition NanoVDB.h:1900
__hostdev__ uint64_t full() const
Definition NanoVDB.h:1906
__hostdev__ uint64_t & full()
Definition NanoVDB.h:1907
__hostdev__ bool isEmpty() const
return true if the 64 bit checksum is disables (unset)
Definition NanoVDB.h:1922
__hostdev__ bool operator==(const Checksum &rhs) const
return true if the checksums are identical
Definition NanoVDB.h:1935
__hostdev__ Checksum()
default constructor initiates checksum to EMPTY
Definition NanoVDB.h:1883
__hostdev__ bool isHalf() const
Definition NanoVDB.h:1916
__hostdev__ uint32_t head() const
Definition NanoVDB.h:1908
__hostdev__ uint32_t & head()
Definition NanoVDB.h:1909
uint64_t mCRC64
Definition NanoVDB.h:1875
uint32_t mCRC32[2]
Definition NanoVDB.h:1875
static constexpr uint32_t EMPTY32
Definition NanoVDB.h:1879
__hostdev__ uint32_t tail() const
Definition NanoVDB.h:1910
__hostdev__ uint32_t checksum(int i) const
Definition NanoVDB.h:1904
__hostdev__ uint32_t & checksum(int i)
Definition NanoVDB.h:1902
__hostdev__ bool operator!=(const Checksum &rhs) const
return true if the checksums are not identical
Definition NanoVDB.h:1939
static constexpr uint64_t EMPTY64
Definition NanoVDB.h:1880
__hostdev__ bool isPartial() const
return true if the 64 bit checksum is partial, i.e. of head only
Definition NanoVDB.h:1915
__hostdev__ CheckMode mode() const
return the mode of the 64 bit checksum
Definition NanoVDB.h:1927
__hostdev__ uint32_t & tail()
Definition NanoVDB.h:1911
__hostdev__ void disable()
Definition NanoVDB.h:1924
Dummy type for a 16bit quantization of float point values.
Definition NanoVDB.h:199
Dummy type for a 4bit quantization of float point values.
Definition NanoVDB.h:193
Dummy type for a 8bit quantization of float point values.
Definition NanoVDB.h:196
Dummy type for a variable bit quantization of floating point values.
Definition NanoVDB.h:202
__hostdev__ const GridClass & gridClass() const
Definition NanoVDB.h:5715
static __hostdev__ bool safeCast(const GridData *gridData)
return true if it is safe to cast the grid to a pointer of type GridMetaData, i.e....
Definition NanoVDB.h:5705
__hostdev__ bool hasMinMax() const
Definition NanoVDB.h:5725
__hostdev__ bool isEmpty() const
Definition NanoVDB.h:5745
__hostdev__ bool safeCast() const
return true if the RootData follows right after the TreeData. If so, this implies that it's safe to c...
Definition NanoVDB.h:5701
__hostdev__ const Map & map() const
Definition NanoVDB.h:5735
__hostdev__ uint32_t blindDataCount() const
Definition NanoVDB.h:5739
__hostdev__ bool hasStdDeviation() const
Definition NanoVDB.h:5729
__hostdev__ uint32_t gridIndex() const
Definition NanoVDB.h:5732
__hostdev__ bool isUnknown() const
Definition NanoVDB.h:5724
__hostdev__ const GridType & gridType() const
Definition NanoVDB.h:5714
__hostdev__ const Checksum & checksum() const
Definition NanoVDB.h:5743
__hostdev__ bool isVoxelBVH() const
Definition NanoVDB.h:5722
GridMetaData & operator=(const GridMetaData &)=default
__hostdev__ bool isValid() const
Definition NanoVDB.h:5713
__hostdev__ uint64_t gridSize() const
Definition NanoVDB.h:5731
__hostdev__ uint32_t nodeCount(uint32_t level) const
Definition NanoVDB.h:5742
__hostdev__ Version version() const
Definition NanoVDB.h:5746
__hostdev__ bool hasLongGridName() const
Definition NanoVDB.h:5727
__hostdev__ bool hasBBox() const
Definition NanoVDB.h:5726
GridMetaData(const NanoGrid< T > &grid)
Definition NanoVDB.h:5678
__hostdev__ const CoordBBox & indexBBox() const
Definition NanoVDB.h:5737
__hostdev__ const char * shortGridName() const
Definition NanoVDB.h:5734
__hostdev__ uint32_t rootTableSize() const
Definition NanoVDB.h:5744
__hostdev__ bool isMask() const
Definition NanoVDB.h:5723
__hostdev__ uint64_t activeVoxelCount() const
Definition NanoVDB.h:5740
__hostdev__ bool isBreadthFirst() const
Definition NanoVDB.h:5730
__hostdev__ bool isPointIndex() const
Definition NanoVDB.h:5719
__hostdev__ bool hasAverage() const
Definition NanoVDB.h:5728
__hostdev__ bool isGridIndex() const
Definition NanoVDB.h:5720
static __hostdev__ bool safeCast(const NanoGrid< T > &grid)
return true if it is safe to cast the grid to a pointer of type GridMetaData, i.e....
Definition NanoVDB.h:5712
__hostdev__ const Vec3dBBox & worldBBox() const
Definition NanoVDB.h:5736
__hostdev__ bool isLevelSet() const
Definition NanoVDB.h:5716
GridMetaData(const GridData *gridData)
Definition NanoVDB.h:5685
__hostdev__ uint32_t gridCount() const
Definition NanoVDB.h:5733
__hostdev__ bool isPointData() const
Definition NanoVDB.h:5721
__hostdev__ const uint32_t & activeTileCount(uint32_t level) const
Definition NanoVDB.h:5741
__hostdev__ bool isStaggered() const
Definition NanoVDB.h:5718
__hostdev__ bool isFogVolume() const
Definition NanoVDB.h:5717
__hostdev__ Vec3d voxelSize() const
Definition NanoVDB.h:5738
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition NanoVDB.h:2179
__hostdev__ const NanoTree< BuildT > & tree() const
Definition NanoVDB.h:2233
typename RootType::LeafNodeType LeafNodeType
Definition NanoVDB.h:2186
__hostdev__ const GridClass & gridClass() const
Definition NanoVDB.h:2308
typename TreeT::ValueType ValueType
Definition NanoVDB.h:2188
__hostdev__ DataType * data()
Definition NanoVDB.h:2202
__hostdev__ Vec3T worldToIndexF(const Vec3T &xyz) const
Definition NanoVDB.h:2272
typename TreeT::RootType RootType
Definition NanoVDB.h:2182
__hostdev__ bool hasMinMax() const
Definition NanoVDB.h:2318
__hostdev__ util::enable_if< util::is_same< T, Point >::value, constuint64_t & >::type pointCount() const
Definition NanoVDB.h:2230
__hostdev__ int findBlindData(const char *name) const
__hostdev__ const Map & map() const
Definition NanoVDB.h:2245
typename TreeT::CoordType CoordType
Definition NanoVDB.h:2190
typename RootNodeType::ChildNodeType UpperNodeType
Definition NanoVDB.h:2184
__hostdev__ const GridBlindMetaData & blindMetaData(uint32_t n) const
Definition NanoVDB.h:2385
__hostdev__ uint32_t blindDataCount() const
Definition NanoVDB.h:2351
__hostdev__ bool hasStdDeviation() const
Definition NanoVDB.h:2322
__hostdev__ BlindDataT * getBlindData(uint32_t n)
Definition NanoVDB.h:2379
__hostdev__ uint32_t gridIndex() const
Definition NanoVDB.h:2213
__hostdev__ bool isUnknown() const
Definition NanoVDB.h:2317
__hostdev__ Vec3T worldToIndexDir(const Vec3T &dir) const
Definition NanoVDB.h:2263
__hostdev__ const GridType & gridType() const
Definition NanoVDB.h:2307
__hostdev__ bool isSequential() const
Definition NanoVDB.h:2336
__hostdev__ const Checksum & checksum() const
Definition NanoVDB.h:2345
__hostdev__ bool isVoxelBVH() const
Definition NanoVDB.h:2315
GridData DataType
Definition NanoVDB.h:2187
RootType RootNodeType
Definition NanoVDB.h:2183
__hostdev__ bool isValid() const
Definition NanoVDB.h:2306
__hostdev__ uint64_t gridSize() const
Definition NanoVDB.h:2210
__hostdev__ Version version() const
Definition NanoVDB.h:2200
__hostdev__ Vec3T indexToWorldGrad(const Vec3T &grad) const
Definition NanoVDB.h:2268
__hostdev__ bool hasLongGridName() const
Definition NanoVDB.h:2320
__hostdev__ Vec3T indexToWorldGradF(const Vec3T &grad) const
Definition NanoVDB.h:2291
__hostdev__ bool hasBBox() const
Definition NanoVDB.h:2319
__hostdev__ util::enable_if< BuildTraits< T >::is_index, constuint64_t & >::type valueCount() const
Definition NanoVDB.h:2223
__hostdev__ Vec3T indexToWorldDirF(const Vec3T &dir) const
Definition NanoVDB.h:2281
__hostdev__ const char * shortGridName() const
Definition NanoVDB.h:2342
__hostdev__ const char * gridName() const
Definition NanoVDB.h:2339
__hostdev__ bool isMask() const
Definition NanoVDB.h:2316
__hostdev__ const BlindDataT * getBlindData(uint32_t n) const
Definition NanoVDB.h:2372
__hostdev__ uint64_t activeVoxelCount() const
Definition NanoVDB.h:2303
DefaultReadAccessor< BuildType > AccessorType
Definition NanoVDB.h:2191
__hostdev__ bool isBreadthFirst() const
Definition NanoVDB.h:2323
__hostdev__ bool isPointIndex() const
Definition NanoVDB.h:2312
__hostdev__ bool hasAverage() const
Definition NanoVDB.h:2321
__hostdev__ bool isGridIndex() const
Definition NanoVDB.h:2313
__hostdev__ Vec3T indexToWorldDir(const Vec3T &dir) const
Definition NanoVDB.h:2258
__hostdev__ Vec3T indexToWorld(const Vec3T &xyz) const
Definition NanoVDB.h:2253
__hostdev__ bool isLevelSet() const
Definition NanoVDB.h:2309
__hostdev__ uint32_t gridCount() const
Definition NanoVDB.h:2216
__hostdev__ bool isPointData() const
Definition NanoVDB.h:2314
typename UpperNodeType::ChildNodeType LowerNodeType
Definition NanoVDB.h:2185
__hostdev__ AccessorType getAccessor() const
Definition NanoVDB.h:2239
__hostdev__ Vec3T worldToIndex(const Vec3T &xyz) const
Definition NanoVDB.h:2249
__hostdev__ const void * blindData(uint32_t n) const
Definition NanoVDB.h:2364
__hostdev__ const DataType * data() const
Definition NanoVDB.h:2204
__hostdev__ bool isStaggered() const
Definition NanoVDB.h:2311
__hostdev__ Vec3T worldToIndexDirF(const Vec3T &dir) const
Definition NanoVDB.h:2286
__hostdev__ Vec3T indexToWorldF(const Vec3T &xyz) const
Definition NanoVDB.h:2276
__hostdev__ const Vec3d & voxelSize() const
Definition NanoVDB.h:2242
TreeT TreeType
Definition NanoVDB.h:2181
Grid(const Grid &)=delete
Disallow constructions, copy and assignment.
typename TreeT::BuildType BuildType
Definition NanoVDB.h:2189
Grid & operator=(const Grid &)=delete
__hostdev__ bool isFogVolume() const
Definition NanoVDB.h:2310
__hostdev__ bool isSequential() const
Definition NanoVDB.h:2328
__hostdev__ int findBlindDataForSemantic(GridBlindDataSemantic semantic) const
__hostdev__ NanoTree< BuildT > & tree()
Definition NanoVDB.h:2236
Type containing raw 16 bits for half precision floating point values (IEEE 754 Half)
Definition NanoVDB.h:187
uint16_t raw
Definition NanoVDB.h:189
Visits child nodes of this node only.
Definition NanoVDB.h:3368
__hostdev__ NodeT & operator*() const
Definition NanoVDB.h:3386
__hostdev__ ChildIter(ParentT *parent)
Definition NanoVDB.h:3380
ChildIter & operator=(const ChildIter &)=default
__hostdev__ CoordType getOrigin() const
Definition NanoVDB.h:3396
__hostdev__ NodeT * operator->() const
Definition NanoVDB.h:3391
__hostdev__ CoordType getCoord() const
Definition NanoVDB.h:3401
__hostdev__ ChildIter()
Definition NanoVDB.h:3375
DenseIterator & operator=(const DenseIterator &)=default
__hostdev__ DenseIterator(const InternalNode *parent)
Definition NanoVDB.h:3495
__hostdev__ CoordType getOrigin() const
Definition NanoVDB.h:3517
__hostdev__ const ChildT * probeChild(ValueType &value) const
Definition NanoVDB.h:3501
__hostdev__ bool isValueOn() const
Definition NanoVDB.h:3512
__hostdev__ DenseIterator()
Definition NanoVDB.h:3490
__hostdev__ CoordType getCoord() const
Definition NanoVDB.h:3522
ValueIterator & operator=(const ValueIterator &)=default
__hostdev__ ValueIterator(const InternalNode *parent)
Definition NanoVDB.h:3422
__hostdev__ ValueIterator()
Definition NanoVDB.h:3417
__hostdev__ CoordType getOrigin() const
Definition NanoVDB.h:3433
__hostdev__ ValueType operator*() const
Definition NanoVDB.h:3428
__hostdev__ CoordType getCoord() const
Definition NanoVDB.h:3438
__hostdev__ bool isActive() const
Definition NanoVDB.h:3439
__hostdev__ ValueOnIterator(const InternalNode *parent)
Definition NanoVDB.h:3461
__hostdev__ ValueOnIterator()
Definition NanoVDB.h:3456
__hostdev__ CoordType getOrigin() const
Definition NanoVDB.h:3472
ValueOnIterator & operator=(const ValueOnIterator &)=default
__hostdev__ ValueType operator*() const
Definition NanoVDB.h:3467
__hostdev__ CoordType getCoord() const
Definition NanoVDB.h:3477
Internal nodes of a VDB tree.
Definition NanoVDB.h:3342
__hostdev__ const MaskType< LOG2DIM > & childMask() const
Definition NanoVDB.h:3549
__hostdev__ const FloatType & stdDeviation() const
Definition NanoVDB.h:3568
__hostdev__ const ValueType & minimum() const
Definition NanoVDB.h:3556
__hostdev__ ConstChildIterator cbeginChild() const
Definition NanoVDB.h:3408
__hostdev__ const ChildNodeType * probeChild(const CoordType &ijk) const
Definition NanoVDB.h:3599
__hostdev__ const ValueType & maximum() const
Definition NanoVDB.h:3559
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:3351
__hostdev__ DenseIterator beginDense() const
Definition NanoVDB.h:3525
__hostdev__ DataType * data()
Definition NanoVDB.h:3534
ChildIter< const InternalNode > ConstChildIterator
Definition NanoVDB.h:3405
__hostdev__ DenseIterator cbeginChildAll() const
Definition NanoVDB.h:3526
InternalData< ChildT, Log2Dim > DataType
Definition NanoVDB.h:3344
__hostdev__ bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:3589
static __hostdev__ Coord OffsetToLocalCoord(uint32_t n)
Definition NanoVDB.h:3614
__hostdev__ ChildNodeType * probeChild(const CoordType &ijk)
Definition NanoVDB.h:3594
friend class ReadAccessor
Definition NanoVDB.h:3658
static constexpr uint32_t MASK
Definition NanoVDB.h:3361
static __hostdev__ uint32_t dim()
Definition NanoVDB.h:3539
typename ChildT::CoordType CoordType
Definition NanoVDB.h:3350
static constexpr uint32_t LEVEL
Definition NanoVDB.h:3362
__hostdev__ const MaskType< LOG2DIM > & getValueMask() const
Definition NanoVDB.h:3546
__hostdev__ FloatType variance() const
Definition NanoVDB.h:3565
__hostdev__ ValueIterator cbeginValueAll() const
Definition NanoVDB.h:3447
friend class InternalNode
Definition NanoVDB.h:3663
static constexpr uint32_t DIM
Definition NanoVDB.h:3359
__hostdev__ OpT::Type get(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:3639
typename DataType::BuildT BuildType
Definition NanoVDB.h:3347
__hostdev__ void localToGlobalCoord(Coord &ijk) const
Definition NanoVDB.h:3622
typename Mask< Log2Dim >::template Iterator< On > MaskIterT
Definition NanoVDB.h:3355
__hostdev__ ValueType getFirstValue() const
Definition NanoVDB.h:3575
ChildT ChildNodeType
Definition NanoVDB.h:3349
typename DataType::ValueT ValueType
Definition NanoVDB.h:3345
typename DataType::StatsT FloatType
Definition NanoVDB.h:3346
__hostdev__ bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:3591
__hostdev__ void set(const CoordType &ijk, ArgsT &&... args)
Definition NanoVDB.h:3647
__hostdev__ ValueOnIterator beginValueOn() const
Definition NanoVDB.h:3480
__hostdev__ CoordType origin() const
Definition NanoVDB.h:3553
typename ChildT::LeafNodeType LeafNodeType
Definition NanoVDB.h:3348
static constexpr uint32_t TOTAL
Definition NanoVDB.h:3358
ChildIter< InternalNode > ChildIterator
Definition NanoVDB.h:3404
__hostdev__ ValueOnIterator cbeginValueOn() const
Definition NanoVDB.h:3481
static constexpr uint32_t LOG2DIM
Definition NanoVDB.h:3357
__hostdev__ ValueType getLastValue() const
Definition NanoVDB.h:3582
__hostdev__ const math::BBox< CoordType > & bbox() const
Definition NanoVDB.h:3571
__hostdev__ const MaskType< LOG2DIM > & getChildMask() const
Definition NanoVDB.h:3550
__hostdev__ ValueIterator beginValue() const
Definition NanoVDB.h:3446
static __hostdev__ uint32_t CoordToOffset(const CoordType &ijk)
Definition NanoVDB.h:3606
__hostdev__ Coord offsetToGlobalCoord(uint32_t n) const
Definition NanoVDB.h:3628
static constexpr uint32_t SIZE
Definition NanoVDB.h:3360
typename ChildT::template MaskType< LOG2 > MaskType
Definition NanoVDB.h:3353
__hostdev__ const LeafNodeType * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:3592
__hostdev__ ChildIterator beginChild()
Definition NanoVDB.h:3407
__hostdev__ const MaskType< LOG2DIM > & valueMask() const
Definition NanoVDB.h:3545
__hostdev__ const DataType * data() const
Definition NanoVDB.h:3536
__hostdev__ ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:3588
__hostdev__ const FloatType & average() const
Definition NanoVDB.h:3562
static constexpr uint64_t NUM_VALUES
Definition NanoVDB.h:3363
InternalNode & operator=(const InternalNode &)=delete
InternalNode(const InternalNode &)=delete
__hostdev__ bool isActive() const
Definition NanoVDB.h:3636
friend class RootNode
Definition NanoVDB.h:3661
static __hostdev__ size_t memUsage()
Definition NanoVDB.h:3542
ValueIterator & operator=(const ValueIterator &)=default
__hostdev__ CoordT getCoord() const
Definition NanoVDB.h:4435
__hostdev__ ValueIterator(const LeafNode *parent)
Definition NanoVDB.h:4423
__hostdev__ ValueIterator()
Definition NanoVDB.h:4418
__hostdev__ ValueType operator*() const
Definition NanoVDB.h:4430
__hostdev__ ValueIterator & operator++()
Definition NanoVDB.h:4446
__hostdev__ ValueIterator operator++(int)
Definition NanoVDB.h:4451
__hostdev__ bool isActive() const
Definition NanoVDB.h:4440
__hostdev__ CoordT getCoord() const
Definition NanoVDB.h:4401
__hostdev__ ValueOffIterator()
Definition NanoVDB.h:4385
ValueOffIterator & operator=(const ValueOffIterator &)=default
__hostdev__ ValueType operator*() const
Definition NanoVDB.h:4396
__hostdev__ ValueOffIterator(const LeafNode *parent)
Definition NanoVDB.h:4390
__hostdev__ ValueOnIterator()
Definition NanoVDB.h:4352
__hostdev__ CoordT getCoord() const
Definition NanoVDB.h:4368
__hostdev__ ValueOnIterator(const LeafNode *parent)
Definition NanoVDB.h:4357
ValueOnIterator & operator=(const ValueOnIterator &)=default
__hostdev__ ValueType operator*() const
Definition NanoVDB.h:4363
Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
Definition NanoVDB.h:4325
__hostdev__ void setValueOnly(uint32_t offset, const ValueType &v)
Sets the value at the specified location but leaves its state unchanged.
Definition NanoVDB.h:4567
__hostdev__ FloatType stdDeviation() const
Return a const reference to the standard deviation of all the active values encoded in this leaf node...
Definition NanoVDB.h:4492
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:4339
__hostdev__ DataType * data()
Definition NanoVDB.h:4471
typename DataType::BuildType BuildType
Definition NanoVDB.h:4337
static __hostdev__ CoordT OffsetToLocalCoord(uint32_t n)
Compute the local coordinates from a linear offset.
Definition NanoVDB.h:4502
static __hostdev__ uint32_t padding()
Definition NanoVDB.h:4537
LeafData< BuildT, CoordT, MaskT, Log2Dim > DataType
Definition NanoVDB.h:4334
friend class ReadAccessor
Definition NanoVDB.h:4637
static constexpr uint32_t MASK
Definition NanoVDB.h:4467
__hostdev__ CoordT offsetToGlobalCoord(uint32_t n) const
Definition NanoVDB.h:4512
static __hostdev__ uint32_t dim()
Return the dimension, in index space, of this leaf node (typically 8 as for openvdb leaf nodes!...
Definition NanoVDB.h:4518
LeafNode< BuildT, CoordT, MaskT, Log2Dim > LeafNodeType
Definition NanoVDB.h:4333
static constexpr uint32_t LEVEL
Definition NanoVDB.h:4468
__hostdev__ const MaskType< LOG2DIM > & getValueMask() const
Definition NanoVDB.h:4477
__hostdev__ FloatType variance() const
Return the variance of all the active values encoded in this leaf node.
Definition NanoVDB.h:4489
__hostdev__ auto set(const uint32_t n, ArgsT &&... args)
Definition NanoVDB.h:4628
LeafNode & operator=(const LeafNode &)=delete
__hostdev__ CoordT origin() const
Return the origin in index space of this leaf node.
Definition NanoVDB.h:4497
__hostdev__ ValueIterator cbeginValueAll() const
Definition NanoVDB.h:4460
friend class InternalNode
Definition NanoVDB.h:4642
static constexpr uint32_t DIM
Definition NanoVDB.h:4465
__hostdev__ const LeafNode * probeLeaf(const CoordT &) const
Definition NanoVDB.h:4592
__hostdev__ ValueOffIterator cbeginValueOff() const
Definition NanoVDB.h:4409
__hostdev__ void localToGlobalCoord(Coord &ijk) const
Converts (in place) a local index coordinate to a global index coordinate.
Definition NanoVDB.h:4510
typename DataType::FloatType FloatType
Definition NanoVDB.h:4336
__hostdev__ ValueType getFirstValue() const
Return the first value in this leaf node.
Definition NanoVDB.h:4555
static __hostdev__ uint32_t CoordToOffset(const CoordT &ijk)
Definition NanoVDB.h:4595
typename Mask< Log2Dim >::template Iterator< ON > MaskIterT
Definition NanoVDB.h:4343
__hostdev__ void setValueOnly(const CoordT &ijk, const ValueType &v)
Definition NanoVDB.h:4568
__hostdev__ FloatType average() const
Return a const reference to the average of all the active values encoded in this leaf node.
Definition NanoVDB.h:4486
__hostdev__ math::BBox< CoordT > bbox() const
Return the bounding box in index space of active values in this leaf node.
Definition NanoVDB.h:4521
__hostdev__ bool probeValue(const CoordT &ijk, ValueType &v) const
Return true if the voxel value at the given coordinate is active and updates v with the value.
Definition NanoVDB.h:4585
__hostdev__ uint8_t flags() const
Definition NanoVDB.h:4494
__hostdev__ bool hasBBox() const
Definition NanoVDB.h:4582
__hostdev__ auto set(const CoordType &ijk, ArgsT &&... args)
Definition NanoVDB.h:4622
__hostdev__ ValueOffIterator beginValueOff() const
Definition NanoVDB.h:4408
__hostdev__ ValueOnIterator beginValueOn() const
Definition NanoVDB.h:4375
static constexpr uint32_t TOTAL
Definition NanoVDB.h:4464
__hostdev__ void setValue(const CoordT &ijk, const ValueType &v)
Sets the value at the specified location and activate its state.
Definition NanoVDB.h:4562
__hostdev__ bool isActive(const CoordT &ijk) const
Return true if the voxel value at the given coordinate is active.
Definition NanoVDB.h:4571
__hostdev__ ValueType minimum() const
Return a const reference to the minimum active value encoded in this leaf node.
Definition NanoVDB.h:4480
__hostdev__ auto get(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:4610
__hostdev__ ValueOnIterator cbeginValueOn() const
Definition NanoVDB.h:4376
MaskT< LOG2 > MaskType
Definition NanoVDB.h:4341
__hostdev__ ValueType maximum() const
Return a const reference to the maximum active value encoded in this leaf node.
Definition NanoVDB.h:4483
static constexpr uint32_t LOG2DIM
Definition NanoVDB.h:4463
__hostdev__ ValueType getLastValue() const
Return the last value in this leaf node.
Definition NanoVDB.h:4557
__hostdev__ bool isActive(uint32_t n) const
Definition NanoVDB.h:4572
LeafNode(const LeafNode &)=delete
__hostdev__ ValueType getValue(const CoordT &ijk) const
Return the voxel value at the given coordinate.
Definition NanoVDB.h:4552
LeafNode()=delete
This class cannot be constructed or deleted.
__hostdev__ bool updateBBox()
Updates the local bounding box of active voxels in this node. Return true if bbox was updated.
Definition NanoVDB.h:4690
__hostdev__ ValueIterator beginValue() const
Definition NanoVDB.h:4459
__hostdev__ uint64_t memUsage() const
return memory usage in bytes for the leaf node
Definition NanoVDB.h:4540
static constexpr uint32_t SIZE
Definition NanoVDB.h:4466
typename DataType::ValueType ValueType
Definition NanoVDB.h:4335
__hostdev__ auto get(const uint32_t n, ArgsT &&... args) const
Definition NanoVDB.h:4616
__hostdev__ ValueType getValue(uint32_t offset) const
Return the voxel value at the given offset.
Definition NanoVDB.h:4549
__hostdev__ const MaskType< LOG2DIM > & valueMask() const
Return a const reference to the bit mask of active voxels in this leaf node.
Definition NanoVDB.h:4476
__hostdev__ const DataType * data() const
Definition NanoVDB.h:4473
static constexpr uint64_t NUM_VALUES
Definition NanoVDB.h:4469
static __hostdev__ uint32_t voxelCount()
Return the total number of voxels (e.g. values) encoded in this leaf node.
Definition NanoVDB.h:4535
__hostdev__ bool isActive() const
Return true if any of the voxel value are active in this leaf node.
Definition NanoVDB.h:4575
friend class RootNode
Definition NanoVDB.h:4640
Definition NanoVDB.h:1133
DenseIterator & operator=(const DenseIterator &)=default
__hostdev__ DenseIterator & operator++()
Definition NanoVDB.h:1143
__hostdev__ DenseIterator operator++(int)
Definition NanoVDB.h:1148
__hostdev__ uint32_t pos() const
Definition NanoVDB.h:1141
__hostdev__ uint32_t operator*() const
Definition NanoVDB.h:1140
__hostdev__ DenseIterator(uint32_t pos=Mask::SIZE)
Definition NanoVDB.h:1135
Definition NanoVDB.h:1099
__hostdev__ Iterator operator++(int)
Definition NanoVDB.h:1120
__hostdev__ Iterator()
Definition NanoVDB.h:1101
Iterator & operator=(const Iterator &)=default
__hostdev__ uint32_t pos() const
Definition NanoVDB.h:1113
__hostdev__ uint32_t operator*() const
Definition NanoVDB.h:1112
__hostdev__ Iterator & operator++()
Definition NanoVDB.h:1115
__hostdev__ Iterator(uint32_t pos, const Mask *parent)
Definition NanoVDB.h:1106
Bit-mask to encode active states and facilitate sequential iterators and a fast codec for I/O compres...
Definition NanoVDB.h:1065
__hostdev__ void setAtomic(uint32_t n, bool on)
Definition NanoVDB.h:1267
__hostdev__ bool isOff(uint32_t n) const
Return true if the given bit is NOT set.
Definition NanoVDB.h:1234
__hostdev__ void set(uint32_t n, bool on)
Set the specified bit on or off.
Definition NanoVDB.h:1295
__hostdev__ void setOffAtomic(uint32_t n)
Definition NanoVDB.h:1263
__hostdev__ void setOnAtomic(uint32_t n)
Definition NanoVDB.h:1259
__hostdev__ void setOn()
Set all bits on.
Definition NanoVDB.h:1308
__hostdev__ uint32_t countOn(uint32_t i) const
Return the number of lower set bits in mask up to but excluding the i'th bit.
Definition NanoVDB.h:1089
NANOVDB_HOSTDEV_DISABLE_WARNING __hostdev__ uint32_t findNext(uint32_t start) const
Definition NanoVDB.h:1378
__hostdev__ uint32_t countOn() const
Return the total number of set bits in this Mask.
Definition NanoVDB.h:1080
__hostdev__ uint64_t * words()
Return a pointer to the list of words of the bit mask.
Definition NanoVDB.h:1185
__hostdev__ Mask(bool on)
Definition NanoVDB.h:1174
__hostdev__ DenseIterator beginAll() const
Definition NanoVDB.h:1166
__hostdev__ void setOff(uint32_t n)
Set the specified bit off.
Definition NanoVDB.h:1257
__hostdev__ void setOff()
Set all bits off.
Definition NanoVDB.h:1314
Iterator< false > OffIterator
Definition NanoVDB.h:1160
Mask & operator=(const Mask &)=default
__hostdev__ Mask()
Initialize all bits to zero.
Definition NanoVDB.h:1169
__hostdev__ Mask & operator&=(const Mask &other)
Bitwise intersection.
Definition NanoVDB.h:1334
Iterator< true > OnIterator
Definition NanoVDB.h:1159
__hostdev__ util::enable_if<!util::is_same< MaskT, Mask >::value, Mask & >::type operator=(const MaskT &other)
Assignment operator that works with openvdb::util::NodeMask.
Definition NanoVDB.h:1205
__hostdev__ void toggle(uint32_t n)
Definition NanoVDB.h:1331
__hostdev__ bool operator!=(const Mask &other) const
Definition NanoVDB.h:1228
__hostdev__ bool isOff() const
Return true if none of the bits are set in this Mask.
Definition NanoVDB.h:1246
static constexpr uint32_t WORD_COUNT
Definition NanoVDB.h:1068
__hostdev__ OffIterator beginOff() const
Definition NanoVDB.h:1164
__hostdev__ void toggle()
brief Toggle the state of all bits in the mask
Definition NanoVDB.h:1326
__hostdev__ const uint64_t * words() const
Definition NanoVDB.h:1186
__hostdev__ void set(bool on)
Set all bits off.
Definition NanoVDB.h:1320
__hostdev__ OnIterator beginOn() const
Definition NanoVDB.h:1162
static __hostdev__ uint32_t wordCount()
Return the number of machine words used by this Mask.
Definition NanoVDB.h:1077
static __hostdev__ uint32_t bitCount()
Return the number of bits available in this Mask.
Definition NanoVDB.h:1074
__hostdev__ Mask & operator|=(const Mask &other)
Bitwise union.
Definition NanoVDB.h:1342
__hostdev__ bool operator==(const Mask &other) const
Definition NanoVDB.h:1219
NANOVDB_HOSTDEV_DISABLE_WARNING __hostdev__ uint32_t findPrev(uint32_t start) const
Definition NanoVDB.h:1392
Mask(const Mask &)=default
Copy constructor.
__hostdev__ bool isOn(uint32_t n) const
Return true if the given bit is set.
Definition NanoVDB.h:1231
static constexpr uint32_t SIZE
Definition NanoVDB.h:1067
__hostdev__ bool isOn() const
Return true if all the bits are set in this Mask.
Definition NanoVDB.h:1237
__hostdev__ void setWord(WordT w, uint32_t n)
Definition NanoVDB.h:1196
NANOVDB_HOSTDEV_DISABLE_WARNING __hostdev__ uint32_t findFirst() const
Definition NanoVDB.h:1368
__hostdev__ Mask & operator-=(const Mask &other)
Bitwise difference.
Definition NanoVDB.h:1350
__hostdev__ Mask & operator^=(const Mask &other)
Bitwise XOR.
Definition NanoVDB.h:1358
__hostdev__ WordT getWord(uint32_t n) const
Definition NanoVDB.h:1189
__hostdev__ void setOn(uint32_t n)
Set the specified bit on.
Definition NanoVDB.h:1255
static __hostdev__ size_t memUsage()
Return the memory footprint in bytes of this Mask.
Definition NanoVDB.h:1071
__hostdev__ uint64_t voxelPoints(const Coord &ijk, const AttT *&begin, const AttT *&end) const
get iterators over attributes to points at a specific voxel location
Definition NanoVDB.h:5865
PointAccessor(const NanoGrid< Point > &grid)
Definition NanoVDB.h:5823
__hostdev__ uint64_t leafPoints(const Coord &ijk, const AttT *&begin, const AttT *&end) const
Return the number of points in the leaf node containing the coordinate ijk. If this return value is l...
Definition NanoVDB.h:5854
__hostdev__ uint64_t gridPoints(const AttT *&begin, const AttT *&end) const
Return the total number of point in the grid and set the iterators to the complete range of points.
Definition NanoVDB.h:5844
__hostdev__ const NanoGrid< Point > & grid() const
Definition NanoVDB.h:5840
__hostdev__ uint64_t voxelPoints(const Coord &ijk, const AttT *&begin, const AttT *&end) const
get iterators over attributes to points at a specific voxel location
Definition NanoVDB.h:5799
__hostdev__ uint64_t leafPoints(const Coord &ijk, const AttT *&begin, const AttT *&end) const
Return the number of points in the leaf node containing the coordinate ijk. If this return value is l...
Definition NanoVDB.h:5787
__hostdev__ uint64_t gridPoints(const AttT *&begin, const AttT *&end) const
Return the total number of point in the grid and set the iterators to the complete range of points.
Definition NanoVDB.h:5777
__hostdev__ const NanoGrid< BuildT > & grid() const
Definition NanoVDB.h:5773
PointAccessor(const NanoGrid< BuildT > &grid)
Definition NanoVDB.h:5760
Dummy type for indexing points into voxels.
Definition NanoVDB.h:205
__hostdev__ auto set(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:4995
__hostdev__ DimAndActive getDimAndActive(const CoordType &ijk, const RayT &ray) const
Fused getDim + isActive: one tree walk returns both the HDDA step size and the active state of ijk,...
Definition NanoVDB.h:4984
ReadAccessor & operator=(const ReadAccessor &)=default
__hostdev__ bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:4971
__hostdev__ ReadAccessor(const RootT &root)
Constructor from a root node.
Definition NanoVDB.h:4936
friend class InternalNode
Definition NanoVDB.h:5005
__hostdev__ uint32_t getDim(const CoordType &ijk, const RayT &ray) const
Definition NanoVDB.h:4975
__hostdev__ const LeafT * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:4973
__hostdev__ bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:4972
__hostdev__ ValueType operator()(int i, int j, int k) const
Definition NanoVDB.h:4969
typename RootT::CoordType CoordType
Definition NanoVDB.h:4931
__hostdev__ auto get(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:4989
__hostdev__ auto getNodeInfo(const CoordType &ijk) const
Definition NanoVDB.h:4970
__hostdev__ ReadAccessor(const TreeT &tree)
Constructor from a tree.
Definition NanoVDB.h:4948
friend class LeafNode
Definition NanoVDB.h:5007
ReadAccessor(const ReadAccessor &)=default
Defaults constructors.
typename RootT::ValueType ValueType
Definition NanoVDB.h:4930
__hostdev__ ReadAccessor(const GridT &grid)
Constructor from a grid.
Definition NanoVDB.h:4942
__hostdev__ void clear()
Reset this access to its initial state, i.e. with an empty cache.
Definition NanoVDB.h:4955
__hostdev__ ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:4963
static const int CacheLevels
Definition NanoVDB.h:4933
BuildT BuildType
Definition NanoVDB.h:4929
__hostdev__ ValueType operator()(const CoordType &ijk) const
Definition NanoVDB.h:4968
__hostdev__ ValueType getValue(int i, int j, int k) const
Definition NanoVDB.h:4967
__hostdev__ const RootT & root() const
Definition NanoVDB.h:4957
friend class RootNode
Allow nodes to insert themselves into the cache.
Definition NanoVDB.h:5003
__hostdev__ DimAndActive getDimAndActive(const CoordType &ijk, const RayT &ray) const
Fused getDim + isActive: one tree walk returns both the HDDA step size and the active state of ijk,...
Definition NanoVDB.h:5108
ReadAccessor & operator=(const ReadAccessor &)=default
__hostdev__ void set(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:5122
__hostdev__ bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:5092
CoordT CoordType
Definition NanoVDB.h:5039
__hostdev__ ReadAccessor(const RootT &root)
Constructor from a root node.
Definition NanoVDB.h:5044
friend class InternalNode
Definition NanoVDB.h:5133
__hostdev__ uint32_t getDim(const CoordType &ijk, const RayT &ray) const
Definition NanoVDB.h:5097
__hostdev__ OpT::Type get(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:5115
ValueT ValueType
Definition NanoVDB.h:5038
__hostdev__ const LeafT * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:5094
__hostdev__ bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:5093
__hostdev__ ValueType operator()(int i, int j, int k) const
Definition NanoVDB.h:5090
__hostdev__ bool isCached(const CoordType &ijk) const
Definition NanoVDB.h:5077
__hostdev__ auto getNodeInfo(const CoordType &ijk) const
Definition NanoVDB.h:5091
__hostdev__ ReadAccessor(const TreeT &tree)
Constructor from a tree.
Definition NanoVDB.h:5058
friend class LeafNode
Definition NanoVDB.h:5135
ReadAccessor(const ReadAccessor &)=default
Defaults constructors.
__hostdev__ ReadAccessor(const GridT &grid)
Constructor from a grid.
Definition NanoVDB.h:5052
__hostdev__ void clear()
Reset this access to its initial state, i.e. with an empty cache.
Definition NanoVDB.h:5064
__hostdev__ ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:5084
static const int CacheLevels
Definition NanoVDB.h:5041
BuildT BuildType
Definition NanoVDB.h:5037
__hostdev__ ValueType operator()(const CoordType &ijk) const
Definition NanoVDB.h:5089
__hostdev__ ValueType getValue(int i, int j, int k) const
Definition NanoVDB.h:5088
__hostdev__ const RootT & root() const
Definition NanoVDB.h:5070
friend class RootNode
Allow nodes to insert themselves into the cache.
Definition NanoVDB.h:5131
__hostdev__ DimAndActive getDimAndActive(const CoordType &ijk, const RayT &ray) const
Fused getDim + isActive: one tree walk returns both the HDDA step size and the active state of ijk,...
Definition NanoVDB.h:5301
ReadAccessor & operator=(const ReadAccessor &)=default
__hostdev__ bool isCached1(const CoordType &ijk) const
Definition NanoVDB.h:5254
__hostdev__ void set(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:5337
__hostdev__ bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:5276
__hostdev__ ReadAccessor(const RootT &root)
Constructor from a root node.
Definition NanoVDB.h:5185
friend class InternalNode
Definition NanoVDB.h:5361
__hostdev__ uint32_t getDim(const CoordType &ijk, const RayT &ray) const
Definition NanoVDB.h:5281
__hostdev__ OpT::Type get(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:5317
__hostdev__ const LeafT * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:5278
__hostdev__ bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:5277
__hostdev__ ValueType operator()(int i, int j, int k) const
Definition NanoVDB.h:5274
__hostdev__ bool isCached2(const CoordType &ijk) const
Definition NanoVDB.h:5260
__hostdev__ auto getNodeInfo(const CoordType &ijk) const
Definition NanoVDB.h:5275
__hostdev__ ReadAccessor(const TreeT &tree)
Constructor from a tree.
Definition NanoVDB.h:5204
friend class LeafNode
Definition NanoVDB.h:5363
ReadAccessor(const ReadAccessor &)=default
Defaults constructors.
__hostdev__ ReadAccessor(const GridT &grid)
Constructor from a grid.
Definition NanoVDB.h:5198
__hostdev__ void clear()
Reset this access to its initial state, i.e. with an empty cache.
Definition NanoVDB.h:5210
__hostdev__ ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:5268
static const int CacheLevels
Definition NanoVDB.h:5182
__hostdev__ ValueType operator()(const CoordType &ijk) const
Definition NanoVDB.h:5273
__hostdev__ ValueType getValue(int i, int j, int k) const
Definition NanoVDB.h:5272
__hostdev__ const RootT & root() const
Definition NanoVDB.h:5221
friend class RootNode
Allow nodes to insert themselves into the cache.
Definition NanoVDB.h:5359
Definition NanoVDB.h:2168
Definition NanoVDB.h:2742
__hostdev__ TileT & operator*() const
Definition NanoVDB.h:2766
TileT * mPos
Definition NanoVDB.h:2746
__hostdev__ TileIter()
Definition NanoVDB.h:2749
TileT * mBegin
Definition NanoVDB.h:2746
__hostdev__ TileIter(DataT *data, uint32_t pos=0)
Definition NanoVDB.h:2750
typename util::match_const< ChildT, DataT >::type NodeT
Definition NanoVDB.h:2745
__hostdev__ bool isChild() const
Definition NanoVDB.h:2781
typename util::match_const< Tile, DataT >::type TileT
Definition NanoVDB.h:2744
TileT * mEnd
Definition NanoVDB.h:2746
__hostdev__ ValueT value() const
Definition NanoVDB.h:2801
__hostdev__ RootData * data() const
Definition NanoVDB.h:2776
__hostdev__ bool isValueOn() const
Definition NanoVDB.h:2791
__hostdev__ bool isValue() const
Definition NanoVDB.h:2786
__hostdev__ NodeT * child() const
Definition NanoVDB.h:2796
__hostdev__ auto pos() const
Definition NanoVDB.h:2760
__hostdev__ TileIter & operator++()
Definition NanoVDB.h:2761
__hostdev__ TileT * operator->() const
Definition NanoVDB.h:2771
__hostdev__ BaseIter(DataT *data)
Definition NanoVDB.h:2917
__hostdev__ BaseIter()
Definition NanoVDB.h:2916
typename util::match_const< Tile, RootT >::type TileT
Definition NanoVDB.h:2914
DataType::template TileIter< DataT > mTileIter
Definition NanoVDB.h:2915
__hostdev__ CoordType getOrigin() const
Definition NanoVDB.h:2923
typename util::match_const< DataType, RootT >::type DataT
Definition NanoVDB.h:2913
__hostdev__ uint32_t pos() const
Definition NanoVDB.h:2921
__hostdev__ TileT * tile() const
Definition NanoVDB.h:2922
__hostdev__ CoordType getCoord() const
Definition NanoVDB.h:2924
Definition NanoVDB.h:2929
__hostdev__ NodeT & operator*() const
Definition NanoVDB.h:2941
__hostdev__ ChildIter operator++(int)
Definition NanoVDB.h:2949
__hostdev__ ChildIter(RootT *parent)
Definition NanoVDB.h:2937
__hostdev__ ChildIter & operator++()
Definition NanoVDB.h:2943
__hostdev__ NodeT * operator->() const
Definition NanoVDB.h:2942
__hostdev__ ChildIter()
Definition NanoVDB.h:2936
Definition NanoVDB.h:3032
__hostdev__ NodeT * probeChild(ValueType &value) const
Definition NanoVDB.h:3040
__hostdev__ DenseIter operator++(int)
Definition NanoVDB.h:3052
__hostdev__ DenseIter & operator++()
Definition NanoVDB.h:3047
__hostdev__ DenseIter()
Definition NanoVDB.h:3038
__hostdev__ DenseIter(RootT *parent)
Definition NanoVDB.h:3039
__hostdev__ bool isValueOn() const
Definition NanoVDB.h:3046
Definition NanoVDB.h:2965
__hostdev__ ValueIter & operator++()
Definition NanoVDB.h:2977
__hostdev__ ValueType operator*() const
Definition NanoVDB.h:2975
__hostdev__ ValueIter operator++(int)
Definition NanoVDB.h:2983
__hostdev__ ValueIter()
Definition NanoVDB.h:2970
__hostdev__ ValueIter(RootT *parent)
Definition NanoVDB.h:2971
__hostdev__ bool isActive() const
Definition NanoVDB.h:2976
Definition NanoVDB.h:2999
__hostdev__ ValueOnIter(RootT *parent)
Definition NanoVDB.h:3005
__hostdev__ ValueOnIter()
Definition NanoVDB.h:3004
__hostdev__ ValueType operator*() const
Definition NanoVDB.h:3009
__hostdev__ ValueOnIter operator++(int)
Definition NanoVDB.h:3016
__hostdev__ ValueOnIter & operator++()
Definition NanoVDB.h:3010
Top-most node of the VDB tree structure.
Definition NanoVDB.h:2888
__hostdev__ const FloatType & stdDeviation() const
Definition NanoVDB.h:3105
__hostdev__ const ValueType & minimum() const
Definition NanoVDB.h:3093
__hostdev__ ConstChildIterator cbeginChild() const
Definition NanoVDB.h:2961
__hostdev__ DenseIterator beginDense()
Definition NanoVDB.h:3063
__hostdev__ const ValueType & maximum() const
Definition NanoVDB.h:3096
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:2905
ChildIter< const RootNode > ConstChildIterator
Definition NanoVDB.h:2958
__hostdev__ DataType * data()
Definition NanoVDB.h:3075
__hostdev__ bool isEmpty() const
Definition NanoVDB.h:3114
__hostdev__ bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:3119
__hostdev__ ConstValueOnIterator cbeginValueOn() const
Definition NanoVDB.h:3028
__hostdev__ ValueIterator beginValue()
Definition NanoVDB.h:2994
friend class ReadAccessor
Definition NanoVDB.h:3149
ChildT UpperNodeType
Definition NanoVDB.h:2894
typename ChildT::CoordType CoordType
Definition NanoVDB.h:2901
static constexpr uint32_t LEVEL
Definition NanoVDB.h:2907
__hostdev__ FloatType variance() const
Definition NanoVDB.h:3102
RootNode & operator=(const RootNode &)=delete
ValueOnIter< RootNode > ValueOnIterator
Definition NanoVDB.h:3024
ValueIter< const RootNode > ConstValueIterator
Definition NanoVDB.h:2992
__hostdev__ OpT::Type get(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:3125
RootData< ChildT > DataType
Definition NanoVDB.h:2890
__hostdev__ const uint32_t & tileCount() const
Definition NanoVDB.h:3089
typename DataType::BuildT BuildType
Definition NanoVDB.h:2899
ValueIter< RootNode > ValueIterator
Definition NanoVDB.h:2991
ChildT ChildNodeType
Definition NanoVDB.h:2891
typename DataType::ValueT ValueType
Definition NanoVDB.h:2897
__hostdev__ ConstDenseIterator cbeginDense() const
Definition NanoVDB.h:3064
RootType RootNodeType
Definition NanoVDB.h:2893
__hostdev__ ConstValueIterator cbeginValueAll() const
Definition NanoVDB.h:2995
RootNode< ChildT > RootType
Definition NanoVDB.h:2892
typename DataType::StatsT FloatType
Definition NanoVDB.h:2898
__hostdev__ const ValueType & background() const
Definition NanoVDB.h:3086
ChildIter< RootNode > ChildIterator
Definition NanoVDB.h:2957
__hostdev__ bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:3121
__hostdev__ ValueOnIterator beginValueOn()
Definition NanoVDB.h:3027
__hostdev__ void set(const CoordType &ijk, ArgsT &&... args)
Definition NanoVDB.h:3135
friend class Tree
Definition NanoVDB.h:3152
typename ChildT::LeafNodeType LeafNodeType
Definition NanoVDB.h:2896
DefaultReadAccessor< BuildType > AccessorType
Definition NanoVDB.h:2903
math::BBox< CoordType > BBoxType
Definition NanoVDB.h:2902
ValueOnIter< const RootNode > ConstValueOnIterator
Definition NanoVDB.h:3025
__hostdev__ ConstDenseIterator cbeginChildAll() const
Definition NanoVDB.h:3065
__hostdev__ const BBoxType & bbox() const
Definition NanoVDB.h:3080
typename DataType::Tile Tile
Definition NanoVDB.h:2904
__hostdev__ uint64_t memUsage() const
Definition NanoVDB.h:3111
typename UpperNodeType::ChildNodeType LowerNodeType
Definition NanoVDB.h:2895
__hostdev__ AccessorType getAccessor() const
Definition NanoVDB.h:3073
__hostdev__ const LeafNodeType * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:3122
static __hostdev__ uint64_t memUsage(uint32_t tableSize)
Definition NanoVDB.h:3108
__hostdev__ ChildIterator beginChild()
Definition NanoVDB.h:2960
__hostdev__ const DataType * data() const
Definition NanoVDB.h:3077
RootNode()=delete
This class cannot be constructed or deleted.
__hostdev__ const uint32_t & getTableSize() const
Definition NanoVDB.h:3090
__hostdev__ ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:3117
__hostdev__ const FloatType & average() const
Definition NanoVDB.h:3099
DenseIter< const RootNode > ConstDenseIterator
Definition NanoVDB.h:3061
DenseIter< RootNode > DenseIterator
Definition NanoVDB.h:3060
__hostdev__ ValueType getValue(int i, int j, int k) const
Definition NanoVDB.h:3118
VDB Tree, which is a thin wrapper around a RootNode.
Definition NanoVDB.h:2478
typename RootT::ChildNodeType Node2
Definition NanoVDB.h:2497
__hostdev__ const NodeT * getFirstNode() const
Definition NanoVDB.h:2588
typename RootType::LeafNodeType LeafNodeType
Definition NanoVDB.h:2490
__hostdev__ DataType * data()
Definition NanoVDB.h:2507
RootT Node3
Definition NanoVDB.h:2496
__hostdev__ bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:2525
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:2512
__hostdev__ const NodeTrait< NanoRoot< BuildT >, 2 >::type * getFirstUpper() const
Definition NanoVDB.h:2618
__hostdev__ NanoRoot< BuildT > & root()
Definition NanoVDB.h:2514
__hostdev__ NodeTrait< NanoRoot< BuildT >, 1 >::type * getFirstLower()
Definition NanoVDB.h:2615
__hostdev__ uint32_t nodeCount() const
Definition NanoVDB.h:2557
typename RootNodeType::ChildNodeType UpperNodeType
Definition NanoVDB.h:2488
__hostdev__ LeafNodeType * getFirstLeaf()
Definition NanoVDB.h:2613
Tree()=delete
This class cannot be constructed or deleted.
__hostdev__ const LeafNodeType * getFirstLeaf() const
Definition NanoVDB.h:2614
__hostdev__ const ValueType & background() const
Definition NanoVDB.h:2534
__hostdev__ bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:2531
__hostdev__ auto set(const CoordType &ijk, ArgsT &&... args)
Definition NanoVDB.h:2627
RootT RootNodeType
Definition NanoVDB.h:2487
typename RootT::CoordType CoordType
Definition NanoVDB.h:2493
__hostdev__ uint64_t activeVoxelCount() const
Definition NanoVDB.h:2543
DefaultReadAccessor< BuildType > AccessorType
Definition NanoVDB.h:2494
__hostdev__ auto get(const CoordType &ijk, ArgsT &&... args) const
Definition NanoVDB.h:2621
LeafNodeType Node0
Definition NanoVDB.h:2499
__hostdev__ NodeTrait< NanoRoot< BuildT >, LEVEL >::type * getFirstNode()
Definition NanoVDB.h:2598
__hostdev__ NodeT * getFirstNode()
Definition NanoVDB.h:2578
typename Node2::ChildNodeType Node1
Definition NanoVDB.h:2498
__hostdev__ uint32_t totalNodeCount() const
Definition NanoVDB.h:2569
RootT RootType
Definition NanoVDB.h:2486
__hostdev__ void extrema(ValueType &min, ValueType &max) const
Tree & operator=(const Tree &)=delete
__hostdev__ const NodeTrait< NanoRoot< BuildT >, 1 >::type * getFirstLower() const
Definition NanoVDB.h:2616
typename UpperNodeType::ChildNodeType LowerNodeType
Definition NanoVDB.h:2489
__hostdev__ AccessorType getAccessor() const
Definition NanoVDB.h:2518
typename RootT::ValueType ValueType
Definition NanoVDB.h:2491
__hostdev__ const NodeTrait< NanoRoot< BuildT >, LEVEL >::type * getFirstNode() const
Definition NanoVDB.h:2607
__hostdev__ uint32_t nodeCount(int level) const
Definition NanoVDB.h:2563
__hostdev__ const uint32_t & activeTileCount(uint32_t level) const
Definition NanoVDB.h:2550
TreeData DataType
Definition NanoVDB.h:2485
__hostdev__ const DataType * data() const
Definition NanoVDB.h:2509
__hostdev__ ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:2521
__hostdev__ NodeTrait< NanoRoot< BuildT >, 2 >::type * getFirstUpper()
Definition NanoVDB.h:2617
__hostdev__ ValueType getValue(int i, int j, int k) const
Definition NanoVDB.h:2522
__hostdev__ const NanoRoot< BuildT > & root() const
Definition NanoVDB.h:2516
typename RootT::BuildType BuildType
Definition NanoVDB.h:2492
Dummy type for a voxel whose value equals an offset into an external value array.
Definition NanoVDB.h:177
Dummy type for a voxel whose value equals its binary active state.
Definition NanoVDB.h:183
Dummy type for a voxel whose value equals an offset into an external value array of active values.
Definition NanoVDB.h:180
Bit-compacted representation of all three version numbers.
Definition NanoVDB.h:727
__hostdev__ Version(uint32_t major, uint32_t minor, uint32_t patch)
Constructor from major.minor.patch version numbers.
Definition NanoVDB.h:741
__hostdev__ uint32_t getMajor() const
Definition NanoVDB.h:754
__hostdev__ Version()
Default constructor.
Definition NanoVDB.h:732
static constexpr uint32_t End
Definition NanoVDB.h:730
__hostdev__ bool operator<=(const Version &rhs) const
Definition NanoVDB.h:750
__hostdev__ bool operator==(const Version &rhs) const
Definition NanoVDB.h:748
__hostdev__ Version(uint32_t data)
Constructor from a raw uint32_t data representation.
Definition NanoVDB.h:739
__hostdev__ int age() const
Returns the difference between major version of this instance and NANOVDB_MAJOR_VERSION_NUMBER.
Definition NanoVDB.h:761
__hostdev__ bool isCompatible() const
Definition NanoVDB.h:757
__hostdev__ bool operator>(const Version &rhs) const
Definition NanoVDB.h:751
__hostdev__ uint32_t getMinor() const
Definition NanoVDB.h:755
__hostdev__ bool operator>=(const Version &rhs) const
Definition NanoVDB.h:752
__hostdev__ bool operator<(const Version &rhs) const
Definition NanoVDB.h:749
__hostdev__ uint32_t id() const
Definition NanoVDB.h:753
__hostdev__ uint32_t getPatch() const
Definition NanoVDB.h:756
static constexpr uint32_t StrLen
Definition NanoVDB.h:730
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition Math.h:425
Definition Range.h:31
#define __hostdev__
Definition SampleFromVoxels.h:29
Definition NanoVDB.h:6012
void writeUncompressedGrid(StreamT &os, const GridData *gridData, bool raw=false)
This is a standalone alternative to io::writeGrid(...,Codec::NONE) defined in util/IO....
Definition NanoVDB.h:6114
__hostdev__ Codec toCodec(const char *str)
Definition NanoVDB.h:6036
VecT< GridHandleT > readUncompressedGrids(StreamT &is, const typename GridHandleT::BufferType &pool=typename GridHandleT::BufferType())
read all uncompressed grids from a stream and return their handles.
Definition NanoVDB.h:6241
__hostdev__ const char * toStr(char *dst, Codec codec)
Definition NanoVDB.h:6026
Codec
Define compression codecs.
Definition NanoVDB.h:6020
@ StrLen
Definition NanoVDB.h:6024
@ ZIP
Definition NanoVDB.h:6021
@ End
Definition NanoVDB.h:6023
@ BLOSC
Definition NanoVDB.h:6022
@ NONE
Definition NanoVDB.h:6020
void writeUncompressedGrids(const char *fileName, const VecT< GridHandleT > &handles, bool raw=false)
write multiple NanoVDB grids to a single file, without compression.
Definition NanoVDB.h:6213
__hostdev__ constexpr T Pow2(T x) noexcept
Return x * x.
Definition Math.h:258
__hostdev__ constexpr Vec3T matMult(const float *mat, const Vec3T &xyz) noexcept
Multiply a 3x3 matrix and a 3d vector using 32bit floating point arithmetics.
Definition Math.h:2201
__hostdev__ constexpr uint64_t AlignUp(uint64_t byteCount) noexcept
round up byteSize to the nearest wordSize, e.g. to align to machine word: AlignUp<sizeof(size_t)(n)
Definition Math.h:411
__hostdev__ constexpr Vec3T matMultT(const float *mat, const Vec3T &xyz) noexcept
Multiply the transposed of a 3x3 matrix and a 3d vector using 32bit floating point arithmetics.
Definition Math.h:2271
Definition GridChecksum.h:86
size_t strlen(const char *str)
length of a c-sting, excluding '\0'.
Definition Util.h:191
uint32_t countOn(uint64_t v)
Definition Util.h:694
uint32_t findHighestOn(uint32_t v)
Returns the index of the highest, i.e. most significant, on bit in the specified 32 bit word.
Definition Util.h:644
char * strncpy(char *dst, const char *src, size_t max)
Copies the first num characters of src to dst. If the end of the source C string (which is signaled b...
Definition Util.h:223
bool streq(const char *lhs, const char *rhs)
Test if two null-terminated byte strings are the same.
Definition Util.h:306
static DstT * PtrAdd(void *p, int64_t offset)
Adds a byte offset to a non-const pointer to produce another non-const pointer.
Definition Util.h:550
static void * memzero(void *dst, size_t byteCount)
Zero initialization of memory.
Definition Util.h:335
char * strcpy(char *dst, const char *src)
Copy characters from src to dst.
Definition Util.h:204
uint32_t findLowestOn(uint32_t v)
Returns the index of the lowest, i.e. least significant, on bit in the specified 32 bit word.
Definition Util.h:574
static int64_t PtrDiff(const void *p, const void *q)
Compute the distance, in bytes, between two pointers, dist = p - q.
Definition Util.h:536
uint64_t atomicOr(uint64_t *target, uint64_t mask)
Atomically ORs mask into the 64-bit word at target (relaxed ordering). Returns the old value....
Definition Util.h:719
char * sprint(char *dst, T var1, Types... var2)
prints a variable number of string and/or numbers to a destination string
Definition Util.h:324
uint64_t atomicAnd(uint64_t *target, uint64_t mask)
Atomically ANDs mask into the 64-bit word at target (relaxed ordering). Returns the old value....
Definition Util.h:743
Defines a simple memory pool used to call cub functions that use dynamic temporary storage.
Definition GridHandle.h:32
__hostdev__ bool isFloatingPoint(GridType gridType)
return true if the GridType maps to a floating point type
Definition NanoVDB.h:613
math::Vec4< float > Vec4f
Definition Math.h:2832
__hostdev__ auto getAccessor(const GridT &grid, ValueT *sideCar=nullptr)
Generic template functions that return an Accessor to either an index grid or a regular grid.
Definition NanoVDB.h:5981
Grid< Fp4Tree > Fp4Grid
Definition NanoVDB.h:4795
ReadAccessor< BuildT, 0, 1, 2 > DefaultReadAccessor
Definition NanoVDB.h:2171
PointType
Definition NanoVDB.h:399
@ Voxel32
Definition NanoVDB.h:405
@ Grid32
Definition NanoVDB.h:404
@ Voxel8
Definition NanoVDB.h:407
@ Default
Definition NanoVDB.h:408
@ PointID
Definition NanoVDB.h:400
@ World32
Definition NanoVDB.h:402
@ Disable
Definition NanoVDB.h:399
@ Voxel16
Definition NanoVDB.h:406
@ World64
Definition NanoVDB.h:401
@ Grid64
Definition NanoVDB.h:403
auto callNanoGrid(GridDataT *gridData, ArgsT &&... args)
Below is an example of the struct used for generic programming with callNanoGrid.
Definition NanoVDB.h:4845
__hostdev__ constexpr uint32_t strlen()
return the number of characters (including null termination) required to convert enum type to a strin...
Definition NanoVDB.h:213
Grid< Vec4fTree > Vec4fGrid
Definition NanoVDB.h:4805
Grid< NanoTree< BuildT > > NanoGrid
Definition NanoVDB.h:4739
__hostdev__ CheckMode toCheckMode(const Checksum &checksum)
Maps 64 bit checksum to CheckMode enum.
Definition NanoVDB.h:1945
__hostdev__ GridType toGridType()
Maps from a templated build type to a GridType enum.
Definition NanoVDB.h:848
typename NodeTrait< GridOrTreeOrRootT, LEVEL >::type NodeTraitT
Definition NanoVDB.h:1783
__hostdev__ char * toStr(char *dst, GridType gridType)
Maps a GridType to a c-string.
Definition NanoVDB.h:257
NanoTree< Vec3i > Vec3ITree
Definition NanoVDB.h:4787
Grid< Fp16Tree > Fp16Grid
Definition NanoVDB.h:4797
Grid< FloatTree > FloatGrid
Definition NanoVDB.h:4794
math::Vec3< uint16_t > Vec3u16
Definition Math.h:2828
math::Vec3< uint8_t > Vec3u8
Definition Math.h:2827
Grid< Vec3fTree > Vec3fGrid
Definition NanoVDB.h:4803
__hostdev__ bool isInteger(GridType gridType)
Return true if the GridType maps to a POD integer type.
Definition NanoVDB.h:639
__hostdev__ GridClass toGridClass(GridBlindDataSemantic semantics, GridClass defaultClass=GridClass::Unknown)
Maps from GridBlindDataSemantic to GridClass.
Definition NanoVDB.h:452
InternalNode< NanoLeaf< BuildT >, 4 > NanoLower
Definition NanoVDB.h:4731
Grid< Vec4dTree > Vec4dGrid
Definition NanoVDB.h:4806
typename GridTree< GridT >::type GridTreeT
Definition NanoVDB.h:2471
__hostdev__ MagicType toMagic(uint64_t magic)
maps 64 bits of magic number to enum
Definition NanoVDB.h:370
Grid< BoolTree > BoolGrid
Definition NanoVDB.h:4809
math::Vec3< float > Vec3f
Definition Math.h:2824
InternalNode< NanoLower< BuildT >, 5 > NanoUpper
Definition NanoVDB.h:4733
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
Definition NanoVDB.h:292
@ FogVolume
Definition NanoVDB.h:294
@ TensorGrid
Definition NanoVDB.h:301
@ VoxelVolume
Definition NanoVDB.h:299
@ End
Definition NanoVDB.h:303
@ Unknown
Definition NanoVDB.h:292
@ Topology
Definition NanoVDB.h:298
@ VoxelBVH
Definition NanoVDB.h:302
@ PointIndex
Definition NanoVDB.h:296
@ IndexGrid
Definition NanoVDB.h:300
@ PointData
Definition NanoVDB.h:297
@ Staggered
Definition NanoVDB.h:295
@ LevelSet
Definition NanoVDB.h:293
GridType
List of types that are currently supported by NanoVDB.
Definition NanoVDB.h:223
@ Vec3u8
Definition NanoVDB.h:247
@ Float
Definition NanoVDB.h:224
@ Boolean
Definition NanoVDB.h:234
@ Vec4f
Definition NanoVDB.h:240
@ Int16
Definition NanoVDB.h:226
@ StrLen
Definition NanoVDB.h:251
@ Fp4
Definition NanoVDB.h:236
@ Mask
Definition NanoVDB.h:231
@ Vec3u16
Definition NanoVDB.h:248
@ Vec4d
Definition NanoVDB.h:241
@ Fp8
Definition NanoVDB.h:237
@ End
Definition NanoVDB.h:250
@ Unknown
Definition NanoVDB.h:223
@ Index
Definition NanoVDB.h:242
@ FpN
Definition NanoVDB.h:239
@ UInt8
Definition NanoVDB.h:249
@ RGBA8
Definition NanoVDB.h:235
@ Int32
Definition NanoVDB.h:227
@ OnIndex
Definition NanoVDB.h:243
@ Half
Definition NanoVDB.h:232
@ PointIndex
Definition NanoVDB.h:246
@ Vec3d
Definition NanoVDB.h:230
@ Double
Definition NanoVDB.h:225
@ UInt32
Definition NanoVDB.h:233
@ Vec3f
Definition NanoVDB.h:229
@ Int64
Definition NanoVDB.h:228
@ Fp16
Definition NanoVDB.h:238
CheckMode
List of different modes for computing for a checksum.
Definition NanoVDB.h:1843
@ Partial
Definition NanoVDB.h:1846
@ Full
Definition NanoVDB.h:1848
@ Disable
Definition NanoVDB.h:1843
@ Half
Definition NanoVDB.h:1845
@ Empty
Definition NanoVDB.h:1844
Grid< Vec3dTree > Vec3dGrid
Definition NanoVDB.h:4804
typename NanoNode< BuildT, LEVEL >::type NanoNodeT
Definition NanoVDB.h:4772
Grid< Point > PointGrid
Definition NanoVDB.h:4810
RootNode< NanoUpper< BuildT > > NanoRoot
Definition NanoVDB.h:4735
typename util::conditional< BuildTraits< BuildT >::is_index, ChannelAccessor< ValueT, BuildT >, DefaultReadAccessor< BuildT > >::type AccType
Generic Accessor type that maps to either a ReadAccessor or ChannelAccessor.
Definition NanoVDB.h:5976
ReadAccessor< ValueT, LEVEL0, LEVEL1, LEVEL2 > createAccessor(const NanoGrid< ValueT > &grid)
Free-standing function for convenient creation of a ReadAccessor with optional and customizable node ...
Definition NanoVDB.h:5646
NanoTree< ValueMask > MaskTree
Definition NanoVDB.h:4788
GridFlags
Grid flags which indicate what extra information is present in the grid buffer.
Definition NanoVDB.h:331
@ HasAverage
Definition NanoVDB.h:335
@ HasStdDeviation
Definition NanoVDB.h:336
@ HasLongGridName
Definition NanoVDB.h:332
@ HasMinMax
Definition NanoVDB.h:334
@ End
Definition NanoVDB.h:338
@ HasBBox
Definition NanoVDB.h:333
@ IsBreadthFirst
Definition NanoVDB.h:337
Grid< OnIndexTree > OnIndexGrid
Definition NanoVDB.h:4812
Grid< Vec3ITree > Vec3IGrid
Definition NanoVDB.h:4807
Grid< Fp8Tree > Fp8Grid
Definition NanoVDB.h:4796
__hostdev__ GridBlindDataSemantic toSemantic(GridClass gridClass, GridBlindDataSemantic defaultSemantic=GridBlindDataSemantic::Unknown)
Maps from GridClass to GridBlindDataSemantic.
Definition NanoVDB.h:486
Grid< Int64Tree > Int64Grid
Definition NanoVDB.h:4802
Tree< NanoRoot< BuildT > > NanoTree
Definition NanoVDB.h:4737
__hostdev__ GridType mapToGridType()
Definition NanoVDB.h:904
NanoTree< int32_t > Int32Tree
Definition NanoVDB.h:4780
LeafNode< BuildT, Coord, Mask, 3 > NanoLeaf
Template specializations to the default configuration used in OpenVDB: Root -> 32^3 -> 16^3 -> 8^3.
Definition NanoVDB.h:4729
NanoTree< ValueOnIndex > OnIndexTree
Definition NanoVDB.h:4791
NanoTree< Half > HalfTree
Definition NanoVDB.h:4792
GridBlindDataClass
Blind-data Classes that are currently supported by NanoVDB.
Definition NanoVDB.h:414
@ ChannelArray
Definition NanoVDB.h:418
@ End
Definition NanoVDB.h:419
@ IndexArray
Definition NanoVDB.h:415
@ AttributeArray
Definition NanoVDB.h:416
@ GridName
Definition NanoVDB.h:417
NanoTree< double > DoubleTree
Definition NanoVDB.h:4779
NanoTree< ValueIndex > IndexTree
Definition NanoVDB.h:4790
__hostdev__ bool isFloatingPointVector(GridType gridType)
return true if the GridType maps to a floating point vec3.
Definition NanoVDB.h:627
NanoTree< Vec4d > Vec4dTree
Definition NanoVDB.h:4786
Grid< UInt32Tree > UInt32Grid
Definition NanoVDB.h:4801
NanoTree< Fp8 > Fp8Tree
Definition NanoVDB.h:4776
static __hostdev__ bool isAligned(const void *p)
return true if the specified pointer is 32 byte aligned
Definition NanoVDB.h:597
math::BBox< Vec3d > Vec3dBBox
Definition Math.h:2836
MagicType
Enums used to identify magic numbers recognized by NanoVDB.
Definition NanoVDB.h:361
@ OpenVDB
Definition NanoVDB.h:362
@ NanoGrid
Definition NanoVDB.h:364
@ Unknown
Definition NanoVDB.h:361
@ NanoVDB
Definition NanoVDB.h:363
@ NanoFile
Definition NanoVDB.h:365
typename BuildToValueMap< T >::type BuildToValueMapT
Definition NanoVDB.h:592
NanoTree< int64_t > Int64Tree
Definition NanoVDB.h:4782
__hostdev__ bool isValid(GridType gridType, GridClass gridClass)
return true if the combination of GridType and GridClass is valid.
Definition NanoVDB.h:661
NanoTree< Vec4f > Vec4fTree
Definition NanoVDB.h:4785
NanoTree< Vec3d > Vec3dTree
Definition NanoVDB.h:4784
NanoTree< Fp16 > Fp16Tree
Definition NanoVDB.h:4777
Grid< MaskTree > MaskGrid
Definition NanoVDB.h:4808
static __hostdev__ uint64_t alignmentPadding(const void *p)
return the smallest number of bytes that when added to the specified pointer results in a 32 byte ali...
Definition NanoVDB.h:600
NanoTree< FpN > FpNTree
Definition NanoVDB.h:4778
math::Vec3< double > Vec3d
Definition Math.h:2823
__hostdev__ bool isIndex(GridType gridType)
Return true if the GridType maps to a special index type (not a POD integer type).
Definition NanoVDB.h:652
math::BBox< Coord > CoordBBox
Definition Math.h:2835
Grid< HalfTree > HalfGrid
Definition NanoVDB.h:4813
math::Vec4< double > Vec4d
Definition Math.h:2831
static __hostdev__ T * alignPtr(T *p)
offset the specified pointer so it is 32 byte aligned. Works with both const and non-const pointers.
Definition NanoVDB.h:608
Grid< IndexTree > IndexGrid
Definition NanoVDB.h:4811
GridBlindDataSemantic
Blind-data Semantics that are currently understood by NanoVDB.
Definition NanoVDB.h:422
@ GaussianId
Definition NanoVDB.h:442
@ PointQuat
Definition NanoVDB.h:436
@ TriangleId
Definition NanoVDB.h:441
@ FogVolume
Definition NanoVDB.h:433
@ PointRadius
Definition NanoVDB.h:426
@ LineId
Definition NanoVDB.h:440
@ PointOpacity
Definition NanoVDB.h:435
@ PointPosition
Definition NanoVDB.h:423
@ PointColor
Definition NanoVDB.h:424
@ VoxelCoords
Definition NanoVDB.h:431
@ PointVelocity
Definition NanoVDB.h:427
@ End
Definition NanoVDB.h:445
@ Unknown
Definition NanoVDB.h:422
@ GridCoords
Definition NanoVDB.h:430
@ WorldCoords
Definition NanoVDB.h:429
@ VoxelBVH
Definition NanoVDB.h:444
@ PointNormal
Definition NanoVDB.h:425
@ PointSH0
Definition NanoVDB.h:438
@ PointSHN
Definition NanoVDB.h:439
@ Staggered
Definition NanoVDB.h:434
@ LevelSet
Definition NanoVDB.h:432
@ PointScale
Definition NanoVDB.h:437
@ PointId
Definition NanoVDB.h:428
Grid< Int32Tree > Int32Grid
Definition NanoVDB.h:4800
NanoTree< Vec3f > Vec3fTree
Definition NanoVDB.h:4783
NanoTree< bool > BoolTree
Definition NanoVDB.h:4789
NanoTree< uint32_t > UInt32Tree
Definition NanoVDB.h:4781
__hostdev__ GridClass mapToGridClass(GridClass defaultClass=GridClass::Unknown)
Definition NanoVDB.h:926
Grid< DoubleTree > DoubleGrid
Definition NanoVDB.h:4799
Grid< FpNTree > FpNGrid
Definition NanoVDB.h:4798
NanoTree< float > FloatTree
Definition NanoVDB.h:4774
NanoTree< Fp4 > Fp4Tree
Definition NanoVDB.h:4775
Definition Coord.h:590
Math functions and classes.
Utility functions.
#define NANOVDB_HOSTDEV_DISABLE_WARNING
Definition Util.h:106
#define NANOVDB_ASSERT(x)
Definition Util.h:53
Policy that exactly matches separate getDim and isActive calls. A skip flag still controls dim but ca...
Definition NanoVDB.h:1831
Policy that preserves getDim's skip-flag fast path. If an InternalNode short-circuits,...
Definition NanoVDB.h:1838
uint16_t mFlags
Definition NanoVDB.h:943
uint32_t mFlags
Definition NanoVDB.h:948
uint64_t mFlags
Definition NanoVDB.h:953
uint8_t mFlags
Definition NanoVDB.h:938
Definition NanoVDB.h:934
float type
Definition NanoVDB.h:574
float Type
Definition NanoVDB.h:573
float type
Definition NanoVDB.h:560
float Type
Definition NanoVDB.h:559
float type
Definition NanoVDB.h:567
float Type
Definition NanoVDB.h:566
float type
Definition NanoVDB.h:581
float Type
Definition NanoVDB.h:580
uint64_t Type
Definition NanoVDB.h:587
uint64_t type
Definition NanoVDB.h:588
uint64_t Type
Definition NanoVDB.h:538
uint64_t type
Definition NanoVDB.h:539
bool Type
Definition NanoVDB.h:552
bool type
Definition NanoVDB.h:553
uint64_t Type
Definition NanoVDB.h:545
uint64_t type
Definition NanoVDB.h:546
Maps one type (e.g. the build types above) to other (actual) types.
Definition NanoVDB.h:530
T Type
Definition NanoVDB.h:531
T type
Definition NanoVDB.h:532
Define static boolean tests for template build types.
Definition NanoVDB.h:510
static constexpr bool is_offindex
Definition NanoVDB.h:514
static constexpr bool is_onindex
Definition NanoVDB.h:513
static constexpr bool is_index
Definition NanoVDB.h:512
static constexpr bool is_Fp
Definition NanoVDB.h:518
static constexpr bool is_float
Definition NanoVDB.h:520
static constexpr bool is_special
Definition NanoVDB.h:522
static constexpr bool is_FpX
Definition NanoVDB.h:516
Result of a fused ReadAccessor::getDimAndActive traversal: the getDim(ijk, ray) step size and the pol...
Definition NanoVDB.h:1812
uint32_t packed
Definition NanoVDB.h:1813
__hostdev__ DimAndActive()
Definition NanoVDB.h:1815
__hostdev__ uint32_t dim() const
Definition NanoVDB.h:1822
__hostdev__ bool active() const
Definition NanoVDB.h:1823
__hostdev__ DimAndActive(uint32_t d, bool a)
Definition NanoVDB.h:1816
double FloatType
Definition NanoVDB.h:841
double FloatType
Definition NanoVDB.h:811
uint64_t FloatType
Definition NanoVDB.h:823
bool FloatType
Definition NanoVDB.h:835
uint64_t FloatType
Definition NanoVDB.h:829
bool FloatType
Definition NanoVDB.h:817
Definition NanoVDB.h:804
float FloatType
Definition NanoVDB.h:805
Implements Tree::getDim(math::Coord)
Definition NanoVDB.h:6412
static __hostdev__ Type get(const NanoUpper< BuildT > &, uint32_t)
Definition NanoVDB.h:6417
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &)
Definition NanoVDB.h:6416
uint32_t Type
Definition NanoVDB.h:6413
static __hostdev__ Type get(const NanoLower< BuildT > &, uint32_t)
Definition NanoVDB.h:6418
static constexpr int LEVEL
Definition NanoVDB.h:6414
static __hostdev__ Type get(const NanoLeaf< BuildT > &, uint32_t)
Definition NanoVDB.h:6419
static __hostdev__ Type get(const NanoRoot< BuildT > &)
Definition NanoVDB.h:6415
Return the pointer to the leaf node that contains math::Coord. Implements Tree::probeLeaf(math::Coord...
Definition NanoVDB.h:6426
static __hostdev__ Type get(const NanoUpper< BuildT > &, uint32_t)
Definition NanoVDB.h:6431
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &)
Definition NanoVDB.h:6430
static __hostdev__ Type get(const NanoLower< BuildT > &, uint32_t)
Definition NanoVDB.h:6432
static constexpr int LEVEL
Definition NanoVDB.h:6428
const NanoLeaf< BuildT > * Type
Definition NanoVDB.h:6427
static __hostdev__ Type get(const NanoRoot< BuildT > &)
Definition NanoVDB.h:6429
static __hostdev__ Type get(const NanoLeaf< BuildT > &leaf, uint32_t)
Definition NanoVDB.h:6433
Return point to the lower internal node where math::Coord maps to one of its values,...
Definition NanoVDB.h:6440
const NanoLower< BuildT > * Type
Definition NanoVDB.h:6441
static __hostdev__ Type get(const NanoUpper< BuildT > &, uint32_t)
Definition NanoVDB.h:6445
static __hostdev__ Type get(const NanoLower< BuildT > &node, uint32_t)
Definition NanoVDB.h:6446
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &)
Definition NanoVDB.h:6444
static constexpr int LEVEL
Definition NanoVDB.h:6442
static __hostdev__ Type get(const NanoRoot< BuildT > &)
Definition NanoVDB.h:6443
Definition NanoVDB.h:6515
uint32_t level
Definition NanoVDB.h:6516
FloatType average
Definition NanoVDB.h:6518
ValueType maximum
Definition NanoVDB.h:6517
CoordBBox bbox
Definition NanoVDB.h:6519
ValueType minimum
Definition NanoVDB.h:6517
uint32_t dim
Definition NanoVDB.h:6516
FloatType stdDevi
Definition NanoVDB.h:6518
Implements Tree::getNodeInfo(math::Coord)
Definition NanoVDB.h:6511
static __hostdev__ Type get(const NanoUpper< BuildT > &node, uint32_t n)
Definition NanoVDB.h:6531
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &tile)
Definition NanoVDB.h:6527
static __hostdev__ Type get(const NanoLeaf< BuildT > &leaf, uint32_t n)
Definition NanoVDB.h:6539
typename NanoLeaf< BuildT >::ValueType ValueType
Definition NanoVDB.h:6512
static constexpr int LEVEL
Definition NanoVDB.h:6521
NodeInfo Type
Definition NanoVDB.h:6522
typename NanoLeaf< BuildT >::FloatType FloatType
Definition NanoVDB.h:6513
static __hostdev__ Type get(const NanoRoot< BuildT > &root)
Definition NanoVDB.h:6523
static __hostdev__ Type get(const NanoLower< BuildT > &node, uint32_t n)
Definition NanoVDB.h:6535
Implements Tree::isActive(math::Coord)
Definition NanoVDB.h:6398
static __hostdev__ Type get(const NanoUpper< BuildT > &node, uint32_t n)
Definition NanoVDB.h:6403
bool Type
Definition NanoVDB.h:6399
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &tile)
Definition NanoVDB.h:6402
static __hostdev__ Type get(const NanoLeaf< BuildT > &leaf, uint32_t n)
Definition NanoVDB.h:6405
static constexpr int LEVEL
Definition NanoVDB.h:6400
static __hostdev__ Type get(const NanoRoot< BuildT > &)
Definition NanoVDB.h:6401
static __hostdev__ Type get(const NanoLower< BuildT > &node, uint32_t n)
Definition NanoVDB.h:6404
Return point to the root Tile where math::Coord maps to one of its values, i.e. terminates.
Definition NanoVDB.h:6465
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &tile)
Definition NanoVDB.h:6469
static constexpr int LEVEL
Definition NanoVDB.h:6467
static __hostdev__ Type get(const NanoRoot< BuildT > &)
Definition NanoVDB.h:6468
const typename NanoRoot< BuildT >::Tile * Type
Definition NanoVDB.h:6466
Return point to the upper internal node where math::Coord maps to one of its values,...
Definition NanoVDB.h:6453
static __hostdev__ Type get(const NanoUpper< BuildT > &node, uint32_t)
Definition NanoVDB.h:6458
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &)
Definition NanoVDB.h:6457
static constexpr int LEVEL
Definition NanoVDB.h:6455
const NanoUpper< BuildT > * Type
Definition NanoVDB.h:6454
static __hostdev__ Type get(const NanoRoot< BuildT > &)
Definition NanoVDB.h:6456
Below is an example of a struct used for random get methods.
Definition NanoVDB.h:6358
static __hostdev__ Type get(const NanoUpper< BuildT > &node, uint32_t n)
Definition NanoVDB.h:6363
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &tile)
Definition NanoVDB.h:6362
static __hostdev__ Type get(const NanoLeaf< BuildT > &leaf, uint32_t n)
Definition NanoVDB.h:6365
static constexpr int LEVEL
Definition NanoVDB.h:6360
static __hostdev__ Type get(const NanoRoot< BuildT > &root)
Definition NanoVDB.h:6361
static __hostdev__ Type get(const NanoLower< BuildT > &node, uint32_t n)
Definition NanoVDB.h:6364
typename NanoLeaf< BuildT >::ValueType Type
Definition NanoVDB.h:6359
Definition NanoVDB.h:1585
GridBlindMetaData(int64_t dataOffset, uint64_t valueCount, uint32_t valueSize, GridBlindDataSemantic semantic, GridBlindDataClass dataClass, GridType dataType)
Definition NanoVDB.h:1608
GridBlindMetaData(const GridBlindMetaData &other)
Copy constructor that resets mDataOffset and zeros out mName.
Definition NanoVDB.h:1620
GridBlindMetaData()
Empty constructor.
Definition NanoVDB.h:1597
__hostdev__ uint64_t blindDataSize() const
return size in bytes of the blind data represented by this blind meta data
Definition NanoVDB.h:1709
GridType mDataType
Definition NanoVDB.h:1592
__hostdev__ void setBlindData(const void *blindData)
Definition NanoVDB.h:1646
GridBlindDataSemantic mSemantic
Definition NanoVDB.h:1590
uint32_t mValueSize
Definition NanoVDB.h:1589
const GridBlindMetaData & operator=(const GridBlindMetaData &rhs)
Copy assignment operator that resets mDataOffset and copies mName.
Definition NanoVDB.h:1634
GridBlindDataClass mDataClass
Definition NanoVDB.h:1591
__hostdev__ bool isValid() const
return true if this meta data has a valid combination of semantic, class and value tags.
Definition NanoVDB.h:1677
__hostdev__ bool setName(const char *name)
Sets the name string.
Definition NanoVDB.h:1654
uint64_t mValueCount
Definition NanoVDB.h:1588
__hostdev__ const BlindDataT * getBlindData() const
Get a const pointer to the blind data represented by this meta data.
Definition NanoVDB.h:1669
__hostdev__ const void * blindData() const
returns a const void point to the blind data
Definition NanoVDB.h:1658
int64_t mDataOffset
Definition NanoVDB.h:1587
char mName[MaxNameSize]
Definition NanoVDB.h:1593
static const int MaxNameSize
Definition NanoVDB.h:1586
Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
Definition NanoVDB.h:1974
__hostdev__ Vec3T applyInverseJacobian(const Vec3T &xyz) const
Definition NanoVDB.h:2063
__hostdev__ bool isEmpty() const
test if the grid is empty, e.i the root table has size 0
Definition NanoVDB.h:2159
__hostdev__ bool isRootConnected() const
return true if RootData follows TreeData in memory without any extra padding
Definition NanoVDB.h:2163
static __hostdev__ uint64_t memUsage()
Return memory usage in bytes for this class only.
Definition NanoVDB.h:2142
uint32_t mBlindMetadataCount
Definition NanoVDB.h:1990
__hostdev__ const void * treePtr() const
Definition NanoVDB.h:2082
Version mVersion
Definition NanoVDB.h:1978
uint32_t mData0
Definition NanoVDB.h:1991
__hostdev__ uint32_t nodeCount() const
Return number of nodes at LEVEL.
Definition NanoVDB.h:2110
GridType mGridType
Definition NanoVDB.h:1988
__hostdev__ void setMinMaxOn(bool on=true)
Definition NanoVDB.h:2044
uint64_t mMagic
Definition NanoVDB.h:1976
__hostdev__ void * nodePtr()
Return a non-const void pointer to the first node at LEVEL.
Definition NanoVDB.h:2099
__hostdev__ Vec3T applyIJTF(const Vec3T &xyz) const
Definition NanoVDB.h:2076
GridClass mGridClass
Definition NanoVDB.h:1987
__hostdev__ void setBBoxOn(bool on=true)
Definition NanoVDB.h:2045
__hostdev__ void setLongGridNameOn(bool on=true)
Definition NanoVDB.h:2046
uint64_t mGridSize
Definition NanoVDB.h:1982
__hostdev__ const GridBlindMetaData * blindMetaData(uint32_t n) const
Returns a const reference to the blindMetaData at the specified linear offset.
Definition NanoVDB.h:2119
__hostdev__ Vec3T applyInverseJacobianF(const Vec3T &xyz) const
Definition NanoVDB.h:2074
__hostdev__ bool isValid() const
return true if the magic number and the version are both valid
Definition NanoVDB.h:2031
__hostdev__ Vec3T applyInverseMapF(const Vec3T &xyz) const
Definition NanoVDB.h:2070
__hostdev__ void init(std::initializer_list< GridFlags > list={GridFlags::IsBreadthFirst}, uint64_t gridSize=0u, const Map &map=Map(), GridType gridType=GridType::Unknown, GridClass gridClass=GridClass::Unknown)
Definition NanoVDB.h:1997
GridData & operator=(const GridData &)=default
Use this method to initiate most member data.
__hostdev__ const CoordBBox & indexBBox() const
return AABB of active values in index space
Definition NanoVDB.h:2148
Checksum mChecksum
Definition NanoVDB.h:1977
Vec3dBBox mWorldBBox
Definition NanoVDB.h:1985
__hostdev__ uint32_t rootTableSize() const
return the root table has size
Definition NanoVDB.h:2151
__hostdev__ const char * gridName() const
Definition NanoVDB.h:2125
__hostdev__ Vec3T applyIJT(const Vec3T &xyz) const
Definition NanoVDB.h:2065
uint64_t mData1
Definition NanoVDB.h:1992
uint32_t mGridCount
Definition NanoVDB.h:1981
__hostdev__ const void * nodePtr() const
Return a non-const void pointer to the first node at LEVEL.
Definition NanoVDB.h:2087
__hostdev__ void setStdDeviationOn(bool on=true)
Definition NanoVDB.h:2048
__hostdev__ Vec3T applyMap(const Vec3T &xyz) const
Definition NanoVDB.h:2057
uint64_t mData2
Definition NanoVDB.h:1993
__hostdev__ Vec3T applyJacobianF(const Vec3T &xyz) const
Definition NanoVDB.h:2072
__hostdev__ Vec3T applyInverseMap(const Vec3T &xyz) const
Definition NanoVDB.h:2059
Map mMap
Definition NanoVDB.h:1984
__hostdev__ const Vec3dBBox & worldBBox() const
return AABB of active values in world space
Definition NanoVDB.h:2145
__hostdev__ Vec3T applyJacobian(const Vec3T &xyz) const
Definition NanoVDB.h:2061
Vec3d mVoxelSize
Definition NanoVDB.h:1986
BitFlags< 32 > mFlags
Definition NanoVDB.h:1979
char mGridName[MaxNameSize]
Definition NanoVDB.h:1983
int64_t mBlindMetadataOffset
Definition NanoVDB.h:1989
uint32_t mGridIndex
Definition NanoVDB.h:1980
static const int MaxNameSize
Definition NanoVDB.h:1975
__hostdev__ void * treePtr()
Definition NanoVDB.h:2079
__hostdev__ Vec3T applyMapF(const Vec3T &xyz) const
Definition NanoVDB.h:2068
__hostdev__ bool setGridName(const char *src)
Definition NanoVDB.h:2049
__hostdev__ void setAverageOn(bool on=true)
Definition NanoVDB.h:2047
const typename GridT::TreeType Type
Definition NanoVDB.h:2466
const typename GridT::TreeType type
Definition NanoVDB.h:2467
defines a tree type from a grid type while preserving constness
Definition NanoVDB.h:2459
typename GridT::TreeType Type
Definition NanoVDB.h:2460
typename GridT::TreeType type
Definition NanoVDB.h:2461
StatsT mAverage
Definition NanoVDB.h:3254
typename ChildT::CoordType CoordT
Definition NanoVDB.h:3232
__hostdev__ void setMin(const ValueT &v)
Definition NanoVDB.h:3324
__hostdev__ const StatsT & average() const
Definition NanoVDB.h:3313
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:3234
__hostdev__ const ValueT & getMin() const
Definition NanoVDB.h:3311
MaskT mChildMask
Definition NanoVDB.h:3250
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:3267
__hostdev__ const ValueT & getMax() const
Definition NanoVDB.h:3312
__hostdev__ void setDev(const StatsT &v)
Definition NanoVDB.h:3327
math::BBox< CoordT > mBBox
Definition NanoVDB.h:3247
InternalData(const InternalData &)=delete
__hostdev__ void setChild(uint32_t n, const void *ptr)
Definition NanoVDB.h:3269
typename ChildT::FloatType StatsT
Definition NanoVDB.h:3231
__hostdev__ void setAvg(const StatsT &v)
Definition NanoVDB.h:3326
__hostdev__ bool isChild(uint32_t n) const
Definition NanoVDB.h:3306
__hostdev__ void setValue(uint32_t n, const ValueT &v)
Definition NanoVDB.h:3276
typename ChildT::BuildType BuildT
Definition NanoVDB.h:3230
static __hostdev__ constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:3261
StatsT mStdDevi
Definition NanoVDB.h:3255
Tile mTable[1u<<(3 *LOG2DIM)]
Definition NanoVDB.h:3265
__hostdev__ void setMax(const ValueT &v)
Definition NanoVDB.h:3325
__hostdev__ void setOrigin(const T &ijk)
Definition NanoVDB.h:3309
__hostdev__ ChildT * getChild(uint32_t n)
Returns a pointer to the child node at the specifed linear offset.
Definition NanoVDB.h:3283
ValueT mMaximum
Definition NanoVDB.h:3253
__hostdev__ bool isActive(uint32_t n) const
Definition NanoVDB.h:3300
MaskT mValueMask
Definition NanoVDB.h:3249
typename ChildT::template MaskType< LOG2DIM > MaskT
Definition NanoVDB.h:3233
__hostdev__ ValueT getValue(uint32_t n) const
Definition NanoVDB.h:3294
__hostdev__ const StatsT & stdDeviation() const
Definition NanoVDB.h:3314
InternalData & operator=(const InternalData &)=delete
typename ChildT::ValueType ValueT
Definition NanoVDB.h:3229
__hostdev__ const ChildT * getChild(uint32_t n) const
Definition NanoVDB.h:3288
ValueT mMinimum
Definition NanoVDB.h:3252
InternalData()=delete
This class cannot be constructed or deleted.
uint64_t mFlags
Definition NanoVDB.h:3248
static __hostdev__ constexpr uint64_t memUsage()
Definition NanoVDB.h:3977
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:3974
__hostdev__ float getValue(uint32_t i) const
Definition NanoVDB.h:3985
uint16_t mCode[1u<< 3 *LOG2DIM]
Definition NanoVDB.h:3975
LeafData & operator=(const LeafData &)=delete
static __hostdev__ constexpr uint32_t padding()
Definition NanoVDB.h:3978
uint16_t ArrayType
Definition NanoVDB.h:3973
LeafData()=delete
This class cannot be constructed or deleted.
LeafFnBase< CoordT, MaskT, LOG2DIM > BaseT
Definition NanoVDB.h:3971
static __hostdev__ constexpr uint8_t bitWidth()
Definition NanoVDB.h:3984
static __hostdev__ constexpr uint64_t memUsage()
Definition NanoVDB.h:3910
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:3907
__hostdev__ float getValue(uint32_t i) const
Definition NanoVDB.h:3918
LeafData & operator=(const LeafData &)=delete
uint8_t mCode[1u<<(3 *LOG2DIM - 1)]
Definition NanoVDB.h:3908
static __hostdev__ constexpr uint32_t padding()
Definition NanoVDB.h:3911
LeafData()=delete
This class cannot be constructed or deleted.
LeafFnBase< CoordT, MaskT, LOG2DIM > BaseT
Definition NanoVDB.h:3904
uint8_t ArrayType
Definition NanoVDB.h:3906
static __hostdev__ constexpr uint8_t bitWidth()
Definition NanoVDB.h:3917
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:3944
__hostdev__ float getValue(uint32_t i) const
Definition NanoVDB.h:3954
LeafData & operator=(const LeafData &)=delete
static __hostdev__ constexpr uint32_t padding()
Definition NanoVDB.h:3947
LeafData()=delete
This class cannot be constructed or deleted.
LeafFnBase< CoordT, MaskT, LOG2DIM > BaseT
Definition NanoVDB.h:3941
uint8_t ArrayType
Definition NanoVDB.h:3943
static __hostdev__ constexpr int64_t memUsage()
Definition NanoVDB.h:3946
uint8_t mCode[1u<< 3 *LOG2DIM]
Definition NanoVDB.h:3945
static __hostdev__ constexpr uint8_t bitWidth()
Definition NanoVDB.h:3953
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:4006
__hostdev__ float getValue(uint32_t i) const
Definition NanoVDB.h:4016
static __hostdev__ size_t memUsage(uint32_t bitWidth)
Definition NanoVDB.h:4015
__hostdev__ uint8_t bitWidth() const
Definition NanoVDB.h:4013
LeafData & operator=(const LeafData &)=delete
static __hostdev__ constexpr uint32_t padding()
Definition NanoVDB.h:4007
LeafData()=delete
This class cannot be constructed or deleted.
LeafFnBase< CoordT, MaskT, LOG2DIM > BaseT
Definition NanoVDB.h:4004
__hostdev__ size_t memUsage() const
Definition NanoVDB.h:4014
uint64_t mOffset
Definition NanoVDB.h:4270
uint16_t mValues[1u<< 3 *LOG2DIM]
Definition NanoVDB.h:4272
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:4263
__hostdev__ void setMin(const ValueType &)
Definition NanoVDB.h:4302
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:4282
__hostdev__ void setDev(const FloatType &)
Definition NanoVDB.h:4305
__hostdev__ void setValueOnly(uint32_t offset, uint16_t value)
Definition NanoVDB.h:4289
uint64_t ValueType
Definition NanoVDB.h:4259
__hostdev__ uint64_t last(uint32_t i) const
Definition NanoVDB.h:4287
uint8_t mFlags
Definition NanoVDB.h:4267
LeafData & operator=(const LeafData &)=delete
__hostdev__ void setValue(uint32_t offset, uint16_t value)
Definition NanoVDB.h:4290
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:4268
CoordT mBBoxMin
Definition NanoVDB.h:4265
uint8_t mBBoxDif[3]
Definition NanoVDB.h:4266
__hostdev__ void setOn(uint32_t offset)
Definition NanoVDB.h:4295
static __hostdev__ constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:4278
__hostdev__ void setAvg(const FloatType &)
Definition NanoVDB.h:4304
uint16_t ArrayType
Definition NanoVDB.h:4262
__hostdev__ ValueType getMax() const
Definition NanoVDB.h:4298
typename FloatTraits< ValueType >::FloatType FloatType
Definition NanoVDB.h:4261
__hostdev__ uint64_t offset() const
Definition NanoVDB.h:4284
LeafData()=delete
This class cannot be constructed or deleted.
__hostdev__ uint64_t first(uint32_t i) const
Definition NanoVDB.h:4286
__hostdev__ void setOrigin(const T &ijk)
Definition NanoVDB.h:4308
__hostdev__ FloatType getDev() const
Definition NanoVDB.h:4300
__hostdev__ uint64_t getValue(uint32_t i) const
Definition NanoVDB.h:4288
uint64_t mPointCount
Definition NanoVDB.h:4271
__hostdev__ FloatType getAvg() const
Definition NanoVDB.h:4299
__hostdev__ void setMax(const ValueType &)
Definition NanoVDB.h:4303
__hostdev__ ValueType getMin() const
Definition NanoVDB.h:4297
__hostdev__ uint64_t pointCount() const
Definition NanoVDB.h:4285
static __hostdev__ uint32_t valueCount()
Definition NanoVDB.h:4212
__hostdev__ uint64_t getMax() const
Definition NanoVDB.h:4217
ValueIndex BuildType
Definition NanoVDB.h:4210
LeafIndexBase< CoordT, MaskT, LOG2DIM > BaseT
Definition NanoVDB.h:4209
__hostdev__ uint64_t getAvg() const
Definition NanoVDB.h:4218
__hostdev__ uint64_t getValue(uint32_t i) const
Definition NanoVDB.h:4220
__hostdev__ uint64_t lastOffset() const
Definition NanoVDB.h:4214
__hostdev__ uint64_t getDev() const
Definition NanoVDB.h:4219
__hostdev__ uint64_t getMin() const
Definition NanoVDB.h:4216
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:4123
__hostdev__ void setMin(const ValueType &)
Definition NanoVDB.h:4145
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:4131
__hostdev__ bool getDev() const
Definition NanoVDB.h:4142
__hostdev__ bool getValue(uint32_t i) const
Definition NanoVDB.h:4138
__hostdev__ void setDev(const FloatType &)
Definition NanoVDB.h:4148
ValueMask BuildType
Definition NanoVDB.h:4120
LeafData & operator=(const LeafData &)=delete
__hostdev__ void setValue(uint32_t offset, bool)
Definition NanoVDB.h:4143
static __hostdev__ bool hasStats()
Definition NanoVDB.h:4132
__hostdev__ bool getMax() const
Definition NanoVDB.h:4140
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:4128
uint8_t mBBoxDif[3]
Definition NanoVDB.h:4126
__hostdev__ void setOn(uint32_t offset)
Definition NanoVDB.h:4144
static __hostdev__ constexpr uint32_t padding()
Definition NanoVDB.h:4133
__hostdev__ void setAvg(const FloatType &)
Definition NanoVDB.h:4147
LeafData()=delete
This class cannot be constructed or deleted.
__hostdev__ void setOrigin(const T &ijk)
Definition NanoVDB.h:4151
uint64_t mPadding[2]
Definition NanoVDB.h:4129
__hostdev__ bool getMin() const
Definition NanoVDB.h:4139
__hostdev__ void setMax(const ValueType &)
Definition NanoVDB.h:4146
__hostdev__ bool getAvg() const
Definition NanoVDB.h:4141
__hostdev__ uint64_t getMax() const
Definition NanoVDB.h:4237
LeafIndexBase< CoordT, MaskT, LOG2DIM > BaseT
Definition NanoVDB.h:4229
__hostdev__ uint64_t getAvg() const
Definition NanoVDB.h:4238
__hostdev__ uint64_t getValue(uint32_t i) const
Definition NanoVDB.h:4240
__hostdev__ uint64_t lastOffset() const
Definition NanoVDB.h:4235
__hostdev__ uint64_t getDev() const
Definition NanoVDB.h:4239
__hostdev__ uint64_t getMin() const
Definition NanoVDB.h:4236
__hostdev__ uint32_t valueCount() const
Definition NanoVDB.h:4231
ValueOnIndex BuildType
Definition NanoVDB.h:4230
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:4073
__hostdev__ void setMax(const bool &)
Definition NanoVDB.h:4097
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:4083
__hostdev__ bool getDev() const
Definition NanoVDB.h:4089
__hostdev__ bool getValue(uint32_t i) const
Definition NanoVDB.h:4085
uint8_t mFlags
Definition NanoVDB.h:4077
LeafData & operator=(const LeafData &)=delete
__hostdev__ void setAvg(const bool &)
Definition NanoVDB.h:4098
MaskT< LOG2DIM > ArrayType
Definition NanoVDB.h:4072
static __hostdev__ bool hasStats()
Definition NanoVDB.h:4084
__hostdev__ void setMin(const bool &)
Definition NanoVDB.h:4096
__hostdev__ bool getMax() const
Definition NanoVDB.h:4087
__hostdev__ void setDev(const bool &)
Definition NanoVDB.h:4099
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:4078
MaskT< LOG2DIM > mValues
Definition NanoVDB.h:4079
CoordT mBBoxMin
Definition NanoVDB.h:4075
uint8_t mBBoxDif[3]
Definition NanoVDB.h:4076
__hostdev__ void setOn(uint32_t offset)
Definition NanoVDB.h:4095
static __hostdev__ constexpr uint32_t padding()
Definition NanoVDB.h:4082
LeafData()=delete
This class cannot be constructed or deleted.
__hostdev__ void setOrigin(const T &ijk)
Definition NanoVDB.h:4102
__hostdev__ void setValue(uint32_t offset, bool v)
Definition NanoVDB.h:4090
uint64_t mPadding[2]
Definition NanoVDB.h:4080
__hostdev__ bool getMin() const
Definition NanoVDB.h:4086
__hostdev__ bool getAvg() const
Definition NanoVDB.h:4088
ValueType mMaximum
Definition NanoVDB.h:3766
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:3758
typename FloatTraits< ValueT >::FloatType FloatType
Definition NanoVDB.h:3756
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:3778
FloatType mAverage
Definition NanoVDB.h:3767
__hostdev__ void setAvg(const FloatType &v)
Definition NanoVDB.h:3805
LeafData & operator=(const LeafData &)=delete
LeafData(const LeafData &)=delete
static __hostdev__ bool hasStats()
Definition NanoVDB.h:3780
ValueT ValueType
Definition NanoVDB.h:3754
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:3763
uint8_t mBBoxDif[3]
Definition NanoVDB.h:3761
__hostdev__ void setOn(uint32_t offset)
Definition NanoVDB.h:3789
static __hostdev__ constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:3774
__hostdev__ ValueType getValue(uint32_t i) const
Definition NanoVDB.h:3782
__hostdev__ void fill(const ValueType &v)
Definition NanoVDB.h:3814
__hostdev__ ValueType getMax() const
Definition NanoVDB.h:3792
LeafData()=delete
This class cannot be constructed or deleted.
ValueT ArrayType
Definition NanoVDB.h:3757
__hostdev__ void setMin(const ValueType &v)
Definition NanoVDB.h:3803
__hostdev__ void setOrigin(const T &ijk)
Definition NanoVDB.h:3812
__hostdev__ void setValueOnly(uint32_t offset, const ValueType &value)
Definition NanoVDB.h:3783
__hostdev__ FloatType getDev() const
Definition NanoVDB.h:3794
ValueType mMinimum
Definition NanoVDB.h:3765
__hostdev__ FloatType getAvg() const
Definition NanoVDB.h:3793
__hostdev__ void setValue(uint32_t offset, const ValueType &value)
Definition NanoVDB.h:3784
ValueT BuildType
Definition NanoVDB.h:3755
ValueType mValues[1u<< 3 *LOG2DIM]
Definition NanoVDB.h:3769
FloatType mStdDevi
Definition NanoVDB.h:3768
__hostdev__ ValueType getMin() const
Definition NanoVDB.h:3791
__hostdev__ void setMax(const ValueType &v)
Definition NanoVDB.h:3804
__hostdev__ void setDev(const FloatType &v)
Definition NanoVDB.h:3806
Base-class for quantized float leaf nodes.
Definition NanoVDB.h:3832
__hostdev__ float getAvg() const
return the quantized average of the active values in this node
Definition NanoVDB.h:3873
float ValueType
Definition NanoVDB.h:3835
__hostdev__ float getMax() const
return the quantized maximum of the active values in this node
Definition NanoVDB.h:3870
__hostdev__ float getDev() const
return the quantized standard deviation of the active values in this node
Definition NanoVDB.h:3877
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:3847
__hostdev__ void setDev(float dev)
Definition NanoVDB.h:3889
uint16_t mMax
Definition NanoVDB.h:3845
uint8_t mFlags
Definition NanoVDB.h:3840
uint16_t mMin
Definition NanoVDB.h:3845
static __hostdev__ bool hasStats()
Definition NanoVDB.h:3849
__hostdev__ void setAvg(float avg)
Definition NanoVDB.h:3886
float mQuantum
Definition NanoVDB.h:3844
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:3841
uint16_t mAvg
Definition NanoVDB.h:3845
CoordT mBBoxMin
Definition NanoVDB.h:3838
uint8_t mBBoxDif[3]
Definition NanoVDB.h:3839
__hostdev__ void setOn(uint32_t offset)
Definition NanoVDB.h:3864
static __hostdev__ constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:3854
float mMinimum
Definition NanoVDB.h:3843
float FloatType
Definition NanoVDB.h:3836
__hostdev__ void setOrigin(const T &ijk)
Definition NanoVDB.h:3892
uint16_t mDev
Definition NanoVDB.h:3845
__hostdev__ void init(float min, float max, uint8_t bitWidth)
Definition NanoVDB.h:3858
__hostdev__ void setMin(float min)
Definition NanoVDB.h:3880
__hostdev__ void setMax(float max)
Definition NanoVDB.h:3883
__hostdev__ float getMin() const
return the quantized minimum of the active values in this node
Definition NanoVDB.h:3867
uint64_t mOffset
Definition NanoVDB.h:4177
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:4171
__hostdev__ const uint64_t & firstOffset() const
Definition NanoVDB.h:4185
__hostdev__ void setMin(const ValueType &)
Definition NanoVDB.h:4186
static __hostdev__ uint64_t memUsage()
Definition NanoVDB.h:4182
__hostdev__ void setDev(const FloatType &)
Definition NanoVDB.h:4189
uint64_t ValueType
Definition NanoVDB.h:4168
uint64_t FloatType
Definition NanoVDB.h:4169
uint8_t mFlags
Definition NanoVDB.h:4175
uint64_t mPrefixSum
Definition NanoVDB.h:4177
LeafIndexBase & operator=(const LeafIndexBase &)=default
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:4176
LeafIndexBase(const LeafIndexBase &)=default
CoordT mBBoxMin
Definition NanoVDB.h:4173
uint8_t mBBoxDif[3]
Definition NanoVDB.h:4174
__hostdev__ void setOn(uint32_t offset)
Definition NanoVDB.h:4190
static __hostdev__ constexpr uint32_t padding()
Definition NanoVDB.h:4178
__hostdev__ void setAvg(const FloatType &)
Definition NanoVDB.h:4188
__hostdev__ bool hasStats() const
Definition NanoVDB.h:4183
__hostdev__ void setOrigin(const T &ijk)
Definition NanoVDB.h:4192
LeafIndexBase()=default
This class should be used as an abstract class and only constructed or deleted via child classes.
__hostdev__ void setMax(const ValueType &)
Definition NanoVDB.h:4187
void ArrayType
Definition NanoVDB.h:4170
Definition NanoVDB.h:4328
static __hostdev__ uint32_t dim()
Definition NanoVDB.h:4331
static constexpr uint32_t DIM
Definition NanoVDB.h:4330
static constexpr uint32_t TOTAL
Definition NanoVDB.h:4329
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:1412
double mTaperD
Definition NanoVDB.h:1420
__hostdev__ constexpr Vec3T applyIJT(const Vec3T &xyz) const
Apply the transposed inverse 3x3 transformation to an input 3d vector using 64bit floating point arit...
Definition NanoVDB.h:1541
void set(const Mat4T &mat, const Mat4T &invMat, double taper=1.0)
Initialize the member data from 4x4 matrices.
Definition NanoVDB.h:1455
__hostdev__ constexpr Vec3T applyInverseMap(const Vec3T &xyz) const
Apply the inverse affine mapping to a vector using 64bit floating point arithmetics.
Definition NanoVDB.h:1500
__hostdev__ constexpr Vec3T applyJacobianF(const Vec3T &ijk) const
Apply the linear forward 3x3 transformation to an input 3d vector using 32bit floating point arithmet...
Definition NanoVDB.h:1492
__hostdev__ constexpr Vec3T applyIJTF(const Vec3T &xyz) const
Definition NanoVDB.h:1543
__hostdev__ constexpr Vec3T applyInverseMapF(const Vec3T &xyz) const
Apply the inverse affine mapping to a vector using 32bit floating point arithmetics.
Definition NanoVDB.h:1511
__hostdev__ constexpr Vec3T applyInverseJacobianF(const Vec3T &xyz) const
Apply the linear inverse 3x3 transformation to an input 3d vector using 32bit floating point arithmet...
Definition NanoVDB.h:1532
__hostdev__ constexpr Vec3d getVoxelSize() const
Return a voxels size in each coordinate direction, measured at the origin.
Definition NanoVDB.h:1546
double mVecD[3]
Definition NanoVDB.h:1419
float mInvMatF[9]
Definition NanoVDB.h:1414
__hostdev__ constexpr Map()
Default constructor for the identity map.
Definition NanoVDB.h:1423
__hostdev__ constexpr Vec3T applyMap(const Vec3T &ijk) const
Apply the forward affine transformation to a vector using 64bit floating point arithmetics.
Definition NanoVDB.h:1466
__hostdev__ constexpr Vec3T applyMapF(const Vec3T &ijk) const
Apply the forward affine transformation to a vector using 32bit floating point arithmetics.
Definition NanoVDB.h:1474
double mInvMatD[9]
Definition NanoVDB.h:1418
float mMatF[9]
Definition NanoVDB.h:1413
double mMatD[9]
Definition NanoVDB.h:1417
__hostdev__ constexpr Map(double s, const Vec3d &t=Vec3d(0.0, 0.0, 0.0))
Definition NanoVDB.h:1434
__hostdev__ constexpr Vec3T applyInverseJacobian(const Vec3T &xyz) const
Apply the linear inverse 3x3 transformation to an input 3d vector using 64bit floating point arithmet...
Definition NanoVDB.h:1523
float mTaperF
Definition NanoVDB.h:1416
float mVecF[3]
Definition NanoVDB.h:1415
__hostdev__ constexpr Vec3T applyJacobian(const Vec3T &ijk) const
Apply the linear forward 3x3 transformation to an input 3d vector using 64bit floating point arithmet...
Definition NanoVDB.h:1483
void set(const MatT &mat, const MatT &invMat, const Vec3T &translate, double taper=1.0)
Initialize the member data from 3x3 or 4x4 matrices.
Definition NanoVDB.h:1550
NanoLeaf< BuildT > type
Definition NanoVDB.h:4750
NanoLeaf< BuildT > Type
Definition NanoVDB.h:4749
NanoLower< BuildT > Type
Definition NanoVDB.h:4755
NanoLower< BuildT > type
Definition NanoVDB.h:4756
NanoUpper< BuildT > type
Definition NanoVDB.h:4762
NanoUpper< BuildT > Type
Definition NanoVDB.h:4761
NanoRoot< BuildT > type
Definition NanoVDB.h:4768
NanoRoot< BuildT > Type
Definition NanoVDB.h:4767
Trait to map from LEVEL to node type.
Definition NanoVDB.h:4743
typename GridOrTreeOrRootT::LeafNodeType type
Definition NanoVDB.h:1728
typename GridOrTreeOrRootT::LeafNodeType Type
Definition NanoVDB.h:1727
typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType Type
Definition NanoVDB.h:1742
typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType type
Definition NanoVDB.h:1743
typename GridOrTreeOrRootT::RootNodeType::ChildNodeType type
Definition NanoVDB.h:1757
typename GridOrTreeOrRootT::RootNodeType::ChildNodeType Type
Definition NanoVDB.h:1756
typename GridOrTreeOrRootT::RootNodeType type
Definition NanoVDB.h:1771
typename GridOrTreeOrRootT::RootNodeType Type
Definition NanoVDB.h:1770
const typename GridOrTreeOrRootT::LeafNodeType Type
Definition NanoVDB.h:1734
const typename GridOrTreeOrRootT::LeafNodeType type
Definition NanoVDB.h:1735
const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType type
Definition NanoVDB.h:1750
const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType::ChildNodeType Type
Definition NanoVDB.h:1749
const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType Type
Definition NanoVDB.h:1763
const typename GridOrTreeOrRootT::RootNodeType::ChildNodeType type
Definition NanoVDB.h:1764
const typename GridOrTreeOrRootT::RootNodeType type
Definition NanoVDB.h:1779
const typename GridOrTreeOrRootT::RootNodeType Type
Definition NanoVDB.h:1778
Struct to derive node type from its level in a given grid, tree or root while preserving constness.
Definition NanoVDB.h:1720
Implements Tree::probeLeaf(math::Coord)
Definition NanoVDB.h:6476
static __hostdev__ Type get(const NanoLeaf< BuildT > &leaf, uint32_t n, ValueT &v)
Definition NanoVDB.h:6500
bool Type
Definition NanoVDB.h:6477
static __hostdev__ Type get(const NanoLower< BuildT > &node, uint32_t n, ValueT &v)
Definition NanoVDB.h:6495
typename BuildToValueMap< BuildT >::Type ValueT
Definition NanoVDB.h:6479
static constexpr int LEVEL
Definition NanoVDB.h:6478
static __hostdev__ Type get(const NanoUpper< BuildT > &node, uint32_t n, ValueT &v)
Definition NanoVDB.h:6490
static __hostdev__ Type get(const typename NanoRoot< BuildT >::Tile &tile, ValueT &v)
Definition NanoVDB.h:6485
static __hostdev__ Type get(const NanoRoot< BuildT > &root, ValueT &v)
Definition NanoVDB.h:6480
Definition NanoVDB.h:2700
ValueT value
Definition NanoVDB.h:2723
uint32_t state
Definition NanoVDB.h:2722
__hostdev__ bool isChild() const
Definition NanoVDB.h:2716
KeyT key
Definition NanoVDB.h:2720
__hostdev__ CoordT origin() const
Definition NanoVDB.h:2719
__hostdev__ bool isValue() const
Definition NanoVDB.h:2717
int64_t child
Definition NanoVDB.h:2721
__hostdev__ void setChild(const CoordType &k, const void *ptr, const RootData *data)
Definition NanoVDB.h:2702
__hostdev__ void setValue(const CoordType &k, bool s, const ValueType &v)
Definition NanoVDB.h:2709
__hostdev__ bool isActive() const
Definition NanoVDB.h:2718
StatsT mAverage
Definition NanoVDB.h:2688
typename ChildT::CoordType CoordT
Definition NanoVDB.h:2654
RootData()=delete
This class cannot be constructed or deleted.
__hostdev__ void setMin(const ValueT &v)
Definition NanoVDB.h:2871
__hostdev__ const StatsT & average() const
Definition NanoVDB.h:2868
static constexpr bool FIXED_SIZE
Definition NanoVDB.h:2656
__hostdev__ const ValueT & getMin() const
Definition NanoVDB.h:2866
__hostdev__ Tile * probeTile(const CoordT &ijk)
Definition NanoVDB.h:2830
__hostdev__ TileIterator beginTile()
Definition NanoVDB.h:2811
ValueT mBackground
Definition NanoVDB.h:2685
__hostdev__ ConstTileIterator probe(const CoordT &ijk) const
Definition NanoVDB.h:2822
__hostdev__ const ValueT & getMax() const
Definition NanoVDB.h:2867
__hostdev__ ChildT * getChild(const Tile *tile)
Returns a const reference to the child node in the specified tile.
Definition NanoVDB.h:2855
__hostdev__ void setDev(const StatsT &v)
Definition NanoVDB.h:2874
uint32_t mTableSize
Definition NanoVDB.h:2683
math::BBox< CoordT > mBBox
Definition NanoVDB.h:2682
uint64_t KeyT
Return a key based on the coordinates of a voxel.
Definition NanoVDB.h:2660
__hostdev__ ConstTileIterator cbeginTile() const
Definition NanoVDB.h:2812
__hostdev__ ChildT * probeChild(const CoordT &ijk)
Definition NanoVDB.h:2841
typename ChildT::FloatType StatsT
Definition NanoVDB.h:2655
__hostdev__ void setAvg(const StatsT &v)
Definition NanoVDB.h:2873
__hostdev__ const Tile * tile(uint32_t n) const
Returns a pointer to the tile at the specified linear offset.
Definition NanoVDB.h:2729
__hostdev__ const Tile * probeTile(const CoordT &ijk) const
Definition NanoVDB.h:2836
typename ChildT::BuildType BuildT
Definition NanoVDB.h:2653
static __hostdev__ constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:2694
StatsT mStdDevi
Definition NanoVDB.h:2689
RootData(const RootData &)=delete
static __hostdev__ CoordT KeyToCoord(const KeyT &key)
Definition NanoVDB.h:2670
RootData & operator=(const RootData &)=delete
static __hostdev__ KeyT CoordToKey(const CoordType &ijk)
Definition NanoVDB.h:2662
__hostdev__ void setMax(const ValueT &v)
Definition NanoVDB.h:2872
ValueT mMaximum
Definition NanoVDB.h:2687
__hostdev__ TileIterator probe(const CoordT &ijk)
Definition NanoVDB.h:2814
__hostdev__ const StatsT & stdDeviation() const
Definition NanoVDB.h:2869
__hostdev__ Tile * tile(uint32_t n)
Definition NanoVDB.h:2734
typename ChildT::ValueType ValueT
Definition NanoVDB.h:2652
TileIter< const RootData > ConstTileIterator
Definition NanoVDB.h:2809
__hostdev__ const ChildT * probeChild(const CoordT &ijk) const
Definition NanoVDB.h:2847
__hostdev__ const ChildT * getChild(const Tile *tile) const
Definition NanoVDB.h:2860
TileIter< RootData > TileIterator
Definition NanoVDB.h:2808
ValueT mMinimum
Definition NanoVDB.h:2686
Definition NanoVDB.h:6370
static __hostdev__ void set(NanoLower< BuildT > &node, uint32_t n, const ValueT &v)
Definition NanoVDB.h:6377
static __hostdev__ void set(NanoRoot< BuildT > &, const ValueT &)
Definition NanoVDB.h:6374
static __hostdev__ void set(NanoUpper< BuildT > &node, uint32_t n, const ValueT &v)
Definition NanoVDB.h:6376
static constexpr int LEVEL
Definition NanoVDB.h:6373
static __hostdev__ void set(NanoLeaf< BuildT > &leaf, uint32_t n, const ValueT &v)
Definition NanoVDB.h:6378
typename NanoLeaf< BuildT >::ValueType ValueT
Definition NanoVDB.h:6372
static __hostdev__ void set(typename NanoRoot< BuildT >::Tile &tile, const ValueT &v)
Definition NanoVDB.h:6375
Definition NanoVDB.h:6383
static __hostdev__ void set(NanoLower< BuildT > &, uint32_t, const ValueT &)
Definition NanoVDB.h:6390
static __hostdev__ void set(NanoRoot< BuildT > &, const ValueT &)
Definition NanoVDB.h:6387
static __hostdev__ void set(NanoUpper< BuildT > &, uint32_t, const ValueT &)
Definition NanoVDB.h:6389
static constexpr int LEVEL
Definition NanoVDB.h:6386
static __hostdev__ void set(NanoLeaf< BuildT > &leaf, uint32_t n, const ValueT &v)
Definition NanoVDB.h:6391
static __hostdev__ void set(typename NanoRoot< BuildT >::Tile &, const ValueT &)
Definition NanoVDB.h:6388
typename NanoLeaf< BuildT >::ValueType ValueT
Definition NanoVDB.h:6385
T ElementType
Definition NanoVDB.h:785
static const int Rank
Definition NanoVDB.h:781
static const int Size
Definition NanoVDB.h:784
static T scalar(const T &s)
Definition NanoVDB.h:786
static const bool IsVector
Definition NanoVDB.h:783
static const bool IsScalar
Definition NanoVDB.h:782
static ElementType scalar(const T &v)
Definition NanoVDB.h:797
static const int Rank
Definition NanoVDB.h:792
static const int Size
Definition NanoVDB.h:795
typename T::ValueType ElementType
Definition NanoVDB.h:796
static const bool IsVector
Definition NanoVDB.h:794
static const bool IsScalar
Definition NanoVDB.h:793
Definition NanoVDB.h:776
Definition NanoVDB.h:2423
__hostdev__ const void * getRoot() const
Get a const void pointer to the root node (never NULL)
Definition NanoVDB.h:2439
__hostdev__ bool isEmpty() const
Return true if the root is empty, i.e. has not child nodes or constant tiles.
Definition NanoVDB.h:2445
int64_t mNodeOffset[4]
Definition NanoVDB.h:2424
__hostdev__ bool isRootNext() const
return true if RootData is layout out immediately after TreeData in memory
Definition NanoVDB.h:2451
TreeData & operator=(const TreeData &)=default
__hostdev__ void setRoot(const void *root)
Definition NanoVDB.h:2430
uint32_t mNodeCount[3]
Definition NanoVDB.h:2425
__hostdev__ void * getRoot()
Get a non-const void pointer to the root node (never NULL)
Definition NanoVDB.h:2436
uint32_t mTileCount[3]
Definition NanoVDB.h:2426
__hostdev__ void setFirstNode(const NodeT *node)
Definition NanoVDB.h:2442
__hostdev__ CoordBBox bbox() const
Return the index bounding box of all the active values in this tree, i.e. in all nodes of the tree.
Definition NanoVDB.h:2448
uint64_t mVoxelCount
Definition NanoVDB.h:2427
Data encoded at the head of each segment of a file or stream.
Definition NanoVDB.h:6048
uint16_t gridCount
Definition NanoVDB.h:6051
bool isValid() const
Definition NanoVDB.h:6053
Codec codec
Definition NanoVDB.h:6052
uint64_t magic
Definition NanoVDB.h:6049
Version version
Definition NanoVDB.h:6050
Definition NanoVDB.h:6074
uint16_t blindDataCount
Definition NanoVDB.h:6085
Vec3d voxelSize
Definition NanoVDB.h:6080
uint64_t nameKey
Definition NanoVDB.h:6075
uint64_t fileSize
Definition NanoVDB.h:6075
uint32_t tileCount[3]
Definition NanoVDB.h:6083
GridClass gridClass
Definition NanoVDB.h:6077
CoordBBox indexBBox
Definition NanoVDB.h:6079
uint32_t nodeCount[4]
Definition NanoVDB.h:6082
Codec codec
Definition NanoVDB.h:6084
uint64_t voxelCount
Definition NanoVDB.h:6075
Version version
Definition NanoVDB.h:6086
GridType gridType
Definition NanoVDB.h:6076
uint32_t nameSize
Definition NanoVDB.h:6081
uint64_t gridSize
Definition NanoVDB.h:6075
Vec3dBBox worldBBox
Definition NanoVDB.h:6078
Definition Math.h:2408
C++11 implementation of std::conditional.
Definition Util.h:429
C++11 implementation of std::enable_if.
Definition Util.h:379
static constexpr bool value
Definition Util.h:370
C++11 implementation of std::is_same.
Definition Util.h:353
static constexpr bool value
Definition Util.h:354
typename remove_const< T >::type type
Definition Util.h:499
T type
Definition Util.h:446
ValueT value
Definition NanoVDB.h:3238
Tile(const Tile &)=delete
Tile & operator=(const Tile &)=delete
Tile()=delete
This class cannot be constructed or deleted.
int64_t child
Definition NanoVDB.h:3239