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