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