OpenVDB: nanovdb/NanoVDB.h Source File

OpenVDB 10.1.0

Loading...
Searching...
No Matches
NanoVDB.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/*!
5 \file 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 openToNanoVDB
33 or the GridBuilder. This explains why none of the grid nodes defined below
34 have public constructors or destructors.
35
36 \details Please see the following paper for more details on the data structure:
37 K. Museth, “VDB: High-Resolution Sparse Volumes with Dynamic Topology”,
38 ACM Transactions on Graphics 32(3), 2013, which can be found here:
39 http://www.museth.org/Ken/Publications_files/Museth_TOG13.pdf
40
41 NanoVDB was first published there: https://dl.acm.org/doi/fullHtml/10.1145/3450623.3464653
42
43
44 Overview: This file implements the following fundamental class that when combined
45 forms the backbone of the VDB tree data structure:
46
47 Coord- a signed integer coordinate
48 Vec3 - a 3D vector
49 Vec4 - a 4D vector
50 BBox - a bounding box
51 Mask - a bitmask essential to the non-root tree nodes
52 Map - an affine coordinate transformation
53 Grid - contains a Tree and a map for world<->index transformations. Use
54 this class as the main API with client code!
55 Tree - contains a RootNode and getValue methods that should only be used for debugging
56 RootNode - the top-level node of the VDB data structure
57 InternalNode - the internal nodes of the VDB data structure
58 LeafNode - the lowest level tree nodes that encode voxel values and state
59 ReadAccessor - implements accelerated random access operations
60
61 Semantics: A VDB data structure encodes values and (binary) states associated with
62 signed integer coordinates. Values encoded at the leaf node level are
63 denoted voxel values, and values associated with other tree nodes are referred
64 to as tile values, which by design cover a larger coordinate index domain.
65
66
67 Memory layout:
68
69 It's important to emphasize that all the grid data (defined below) are explicitly 32 byte
70 aligned, which implies that any memory buffer that contains a NanoVDB grid must also be at
71 32 byte aligned. That is, the memory address of the beginning of a buffer (see ascii diagram below)
72 must be divisible by 32, i.e. uintptr_t(&buffer)%32 == 0! If this is not the case, the C++ standard
73 says the behaviour is undefined! Normally this is not a concerns on GPUs, because they use 256 byte
74 aligned allocations, but the same cannot be said about the CPU.
75
76 GridData is always at the very beginning of the buffer immediately followed by TreeData!
77 The remaining nodes and blind-data are allowed to be scattered throughout the buffer,
78 though in practice they are arranged as:
79
80 GridData: 672 bytes (e.g. magic, checksum, major, flags, index, count, size, name, map, world bbox, voxel size, class, type, offset, count)
81
82 TreeData: 64 bytes (node counts and byte offsets)
83
84 ... optional padding ...
85
86 RootData: size depends on ValueType (index bbox, voxel count, tile count, min/max/avg/standard deviation)
87
88 Array of: RootData::Tile
89
90 ... optional padding ...
91
92 Array of: Upper InternalNodes of size 32^3: bbox, two bit masks, 32768 tile values, and min/max/avg/standard deviation values
93
94 ... optional padding ...
95
96 Array of: Lower InternalNodes of size 16^3: bbox, two bit masks, 4096 tile values, and min/max/avg/standard deviation values
97
98 ... optional padding ...
99
100 Array of: LeafNodes of size 8^3: bbox, bit masks, 512 voxel values, and min/max/avg/standard deviation values
101
102
103 Notation: "]---[" implies it has optional padding, and "][" implies zero padding
104
105 [GridData(672B)][TreeData(64B)]---[RootData][N x Root::Tile]---[NodeData<5>]---[ModeData<4>]---[LeafData<3>]---[BLINDMETA...]---[BLIND0]---[BLIND1]---etc.
106 ^ ^ ^ ^ ^ ^
107 | | | | | |
108 +-- Start of 32B aligned buffer | | | | +-- Node0::DataType* leafData
109 GridType::DataType* gridData | | | |
110 | | | +-- Node1::DataType* lowerData
111 RootType::DataType* rootData --+ | |
112 | +-- Node2::DataType* upperData
113 |
114 +-- RootType::DataType::Tile* tile
115
116*/
117
118#ifndef NANOVDB_NANOVDB_H_HAS_BEEN_INCLUDED
119#define NANOVDB_NANOVDB_H_HAS_BEEN_INCLUDED
120
121#define NANOVDB_MAGIC_NUMBER 0x304244566f6e614eUL // "NanoVDB0" in hex - little endian (uint64_t)
122
123#define NANOVDB_MAJOR_VERSION_NUMBER 32 // reflects changes to the ABI and hence also the file format
124#define NANOVDB_MINOR_VERSION_NUMBER 4 // reflects changes to the API but not ABI
125#define NANOVDB_PATCH_VERSION_NUMBER 2 // reflects changes that does not affect the ABI or API
126
127// This replaces a Coord key at the root level with a single uint64_t
128#define USE_SINGLE_ROOT_KEY
129
130// This replaces three levels of Coord keys in the ReadAccessor with one Coord
131//#define USE_SINGLE_ACCESSOR_KEY
132
133//#define NANOVDB_USE_IOSTREAMS
134
135#define NANOVDB_FPN_BRANCHLESS
136
137#define NANOVDB_DATA_ALIGNMENT 32
138
139#if !defined(NANOVDB_ALIGN)
140#define NANOVDB_ALIGN(n) alignas(n)
141#endif // !defined(NANOVDB_ALIGN)
142
143#ifdef __CUDACC_RTC__
144
145typedef signed char int8_t;
146typedef short int16_t;
147typedef int int32_t;
148typedef long long int64_t;
149typedef unsigned char uint8_t;
150typedef unsigned int uint32_t;
151typedef unsigned short uint16_t;
152typedef unsigned long long uint64_t;
153
154#define NANOVDB_ASSERT(x)
155
156#define UINT64_C(x) (x ## ULL)
157
158#else // !__CUDACC_RTC__
159
160#include <stdlib.h> // for abs in clang7
161#include <stdint.h> // for types like int32_t etc
162#include <stddef.h> // for size_t type
163#include <cassert> // for assert
164#include <cstdio> // for snprintf
165#include <cmath> // for sqrt and fma
166#include <limits> // for numeric_limits
167#include <utility>// for std::move
168#ifdef NANOVDB_USE_IOSTREAMS
169#include <fstream>// for read/writeUncompressedGrids
170#endif
171// All asserts can be disabled here, even for debug builds
172#if 1
173#define NANOVDB_ASSERT(x) assert(x)
174#else
175#define NANOVDB_ASSERT(x)
176#endif
177
178#if defined(NANOVDB_USE_INTRINSICS) && defined(_MSC_VER)
179#include <intrin.h>
180#pragma intrinsic(_BitScanReverse)
181#pragma intrinsic(_BitScanForward)
182#pragma intrinsic(_BitScanReverse64)
183#pragma intrinsic(_BitScanForward64)
184#endif
185
186#endif // __CUDACC_RTC__
187
188#if defined(__CUDACC__) || defined(__HIP__)
189// Only define __hostdev__ when using NVIDIA CUDA or HIP compiler
190#define __hostdev__ __host__ __device__
191#else
192#define __hostdev__
193#endif
194
195// The following macro will suppress annoying warnings when nvcc
196// compiles functions that call (host) intrinsics (which is perfectly valid)
197#if defined(_MSC_VER) && defined(__CUDACC__)
198#define NANOVDB_HOSTDEV_DISABLE_WARNING __pragma("hd_warning_disable")
199#elif defined(__GNUC__) && defined(__CUDACC__)
200#define NANOVDB_HOSTDEV_DISABLE_WARNING _Pragma("hd_warning_disable")
201#else
202#define NANOVDB_HOSTDEV_DISABLE_WARNING
203#endif
204
205// A portable implementation of offsetof - unfortunately it doesn't work with static_assert
206#define NANOVDB_OFFSETOF(CLASS, MEMBER) ((int)(size_t)((char*)&((CLASS*)0)->MEMBER - (char*)0))
207
208 namespace nanovdb {
209
210// --------------------------> Build types <------------------------------------
211
212/// @brief Dummy type for a voxel whose value equals an offset into an external value array
213 class ValueIndex {};
214
215/// @brief Dummy type for a voxel whose value equals its binary active state
216 class ValueMask {};
217
218/// @brief Dummy type for a 16 bit floating point values
219 class Half {};
220
221/// @brief Dummy type for a 4bit quantization of float point values
222 class Fp4 {};
223
224/// @brief Dummy type for a 8bit quantization of float point values
225 class Fp8 {};
226
227/// @brief Dummy type for a 16bit quantization of float point values
228 class Fp16 {};
229
230/// @brief Dummy type for a variable bit quantization of floating point values
231 class FpN {};
232
233// --------------------------> GridType <------------------------------------
234
235/// @brief List of types that are currently supported by NanoVDB
236///
237/// @note To expand on this list do:
238/// 1) Add the new type between Unknown and End in the enum below
239/// 2) Add the new type to OpenToNanoVDB::processGrid that maps OpenVDB types to GridType
240/// 3) Verify that the ConvertTrait in NanoToOpenVDB.h works correctly with the new type
241/// 4) Add the new type to mapToGridType (defined below) that maps NanoVDB types to GridType
242/// 5) Add the new type to toStr (defined below)
243 enum class GridType : uint32_t { Unknown = 0,
244 Float = 1,// single precision floating point value
245 Double = 2,// double precision floating point value
246 Int16 = 3,// half precision signed integer value
247 Int32 = 4,// single precision signed integer value
248 Int64 = 5,// double precision signed integer value
249 Vec3f = 6,// single precision floating 3D vector
250 Vec3d = 7,// double precision floating 3D vector
251 Mask = 8,// no value, just the active state
252 Half = 9,// half precision floating point value
253 UInt32 = 10,// single precision unsigned integer value
254 Boolean = 11,// boolean value, encoded in bit array
255 RGBA8 = 12,// RGBA packed into 32bit word in reverse-order. R in low bits.
256 Fp4 = 13,// 4bit quantization of float point value
257 Fp8 = 14,// 8bit quantization of float point value
258 Fp16 = 15,// 16bit quantization of float point value
259 FpN = 16,// variable bit quantization of floating point value
260 Vec4f = 17,// single precision floating 4D vector
261 Vec4d = 18,// double precision floating 4D vector
262 Index = 19,// index into an external array of values
263 End = 20 };
264
265#ifndef __CUDACC_RTC__
266/// @brief Retuns a c-string used to describe a GridType
267 inline const char* toStr(GridType gridType)
268{
269 static const char * LUT[] = { "?", "float", "double" , "int16", "int32",
270 "int64", "Vec3f", "Vec3d", "Mask", "Half",
271 "uint32", "bool", "RGBA8", "Float4", "Float8",
272 "Float16", "FloatN", "Vec4f", "Vec4d", "Index", "End" };
273 static_assert( sizeof(LUT)/sizeof(char*) - 1 == int(GridType::End), "Unexpected size of LUT" );
274 return LUT[static_cast<int>(gridType)];
275}
276#endif
277
278// --------------------------> GridClass <------------------------------------
279
280/// @brief Classes (defined in OpenVDB) that are currently supported by NanoVDB
281 enum class GridClass : uint32_t { Unknown = 0,
282 LevelSet = 1, // narrow band level set, e.g. SDF
283 FogVolume = 2, // fog volume, e.g. density
284 Staggered = 3, // staggered MAC grid, e.g. velocity
285 PointIndex = 4, // point index grid
286 PointData = 5, // point data grid
287 Topology = 6, // grid with active states only (no values)
288 VoxelVolume = 7, // volume of geometric cubes, e.g. Minecraft
289 IndexGrid = 8,// grid whose values are offsets, e.g. into an external array
290 End = 9 };
291
292#ifndef __CUDACC_RTC__
293/// @brief Retuns a c-string used to describe a GridClass
294 inline const char* toStr(GridClass gridClass)
295{
296 static const char * LUT[] = { "?", "SDF", "FOG" , "MAC", "PNTIDX",
297 "PNTDAT", "TOPO", "VOX", "INDEX", "END" };
298 static_assert( sizeof(LUT)/sizeof(char*) - 1 == int(GridClass::End), "Unexpected size of LUT" );
299 return LUT[static_cast<int>(gridClass)];
300}
301#endif
302
303// --------------------------> GridFlags <------------------------------------
304
305/// @brief Grid flags which indicate what extra information is present in the grid buffer.
306 enum class GridFlags : uint32_t {
307 HasLongGridName = 1 << 0,// grid name is longer than 256 characters
308 HasBBox = 1 << 1,// nodes contain bounding-boxes of active values
309 HasMinMax = 1 << 2,// nodes contain min/max of active values
310 HasAverage = 1 << 3,// nodes contain averages of active values
311 HasStdDeviation = 1 << 4,// nodes contain standard deviations of active values
312 IsBreadthFirst = 1 << 5,// nodes are arranged breadth-first in memory
313 End = 1 << 6,
314};
315
316#ifndef __CUDACC_RTC__
317/// @brief Retuns a c-string used to describe a GridFlags
318 inline const char* toStr(GridFlags gridFlags)
319{
320 static const char * LUT[] = { "has long grid name",
321 "has bbox",
322 "has min/max",
323 "has average",
324 "has standard deviation",
325 "is breadth-first",
326 "end" };
327 static_assert( 1 << (sizeof(LUT)/sizeof(char*) - 1) == int(GridFlags::End), "Unexpected size of LUT" );
328 return LUT[static_cast<int>(gridFlags)];
329}
330#endif
331
332// --------------------------> GridBlindData enums <------------------------------------
333
334/// @brief Blind-data Classes that are currently supported by NanoVDB
335 enum class GridBlindDataClass : uint32_t { Unknown = 0,
336 IndexArray = 1,
337 AttributeArray = 2,
338 GridName = 3,
339 ChannelArray = 4,
340 End = 5 };
341
342/// @brief Blind-data Semantics that are currently understood by NanoVDB
343 enum class GridBlindDataSemantic : uint32_t { Unknown = 0,
344 PointPosition = 1,
345 PointColor = 2,
346 PointNormal = 3,
347 PointRadius = 4,
348 PointVelocity = 5,
349 PointId = 6,
350 End = 8 };
351
352// --------------------------> is_same <------------------------------------
353
354/// @brief C++11 implementation of std::is_same
355template<typename T1, typename T2>
356 struct is_same
357{
358 static constexpr bool value = false;
359};
360
361template<typename T>
362 struct is_same<T, T>
363{
364 static constexpr bool value = true;
365};
366
367// --------------------------> enable_if <------------------------------------
368
369/// @brief C++11 implementation of std::enable_if
370template <bool, typename T = void>
371 struct enable_if
372{
373};
374
375template <typename T>
376 struct enable_if<true, T>
377{
378 using type = T;
379};
380
381// --------------------------> is_const <------------------------------------
382
383template<typename T>
384 struct is_const
385{
386 static constexpr bool value = false;
387};
388
389template<typename T>
390 struct is_const<const T>
391{
392 static constexpr bool value = true;
393};
394
395// --------------------------> remove_const <------------------------------------
396
397template<typename T>
398 struct remove_const
399{
400 using type = T;
401};
402
403template<typename T>
404 struct remove_const<const T>
405{
406 using type = T;
407};
408
409// --------------------------> is_floating_point <------------------------------------
410
411/// @brief C++11 implementation of std::is_floating_point
412template<typename T>
413 struct is_floating_point
414{
415 static const bool value = is_same<T, float>::value || is_same<T, double>::value;
416};
417
418// --------------------------> is_specialization <------------------------------------
419
420/// @brief Metafunction used to determine if the first template
421/// parameter is a specialization of the class template
422/// given in the second template parameter.
423///
424/// @details is_specialization<Vec3<float>, Vec3>::value == true;
425template<typename AnyType, template<typename...> class TemplateType>
426 struct is_specialization
427{
428 static const bool value = false;
429};
430template<typename... Args, template<typename...> class TemplateType>
431 struct is_specialization<TemplateType<Args...>, TemplateType>
432{
433 static const bool value = true;
434};
435
436// --------------------------> Value Map <------------------------------------
437
438/// @brief Maps one type (e.g. the build types above) to other (actual) types
439template <typename T>
440 struct BuildToValueMap
441{
442 using Type = T;
443 using type = T;
444};
445
446template<>
447 struct BuildToValueMap<ValueIndex>
448{
449 using Type = uint64_t;
450 using type = uint64_t;
451};
452
453template<>
454 struct BuildToValueMap<ValueMask>
455{
456 using Type = bool;
457 using type = bool;
458};
459
460template<>
461 struct BuildToValueMap<Half>
462{
463 using Type = float;
464 using type = float;
465};
466
467template<>
468 struct BuildToValueMap<Fp4>
469{
470 using Type = float;
471 using type = float;
472};
473
474template<>
475 struct BuildToValueMap<Fp8>
476{
477 using Type = float;
478 using type = float;
479};
480
481template<>
482 struct BuildToValueMap<Fp16>
483{
484 using Type = float;
485 using type = float;
486};
487
488template<>
489 struct BuildToValueMap<FpN>
490{
491 using Type = float;
492 using type = float;
493};
494
495// --------------------------> utility functions related to alignment <------------------------------------
496
497/// @brief return true if the specified pointer is aligned
498 __hostdev__ inline static bool isAligned(const void* p)
499{
500 return uint64_t(p) % NANOVDB_DATA_ALIGNMENT == 0;
501}
502
503/// @brief return true if the specified pointer is aligned and not NULL
504 __hostdev__ inline static bool isValid(const void* p)
505{
506 return p != nullptr && uint64_t(p) % NANOVDB_DATA_ALIGNMENT == 0;
507}
508
509/// @brief return the smallest number of bytes that when added to the specified pointer results in an aligned pointer
510 __hostdev__ inline static uint64_t alignmentPadding(const void* p)
511{
512 NANOVDB_ASSERT(p);
513 return (NANOVDB_DATA_ALIGNMENT - (uint64_t(p) % NANOVDB_DATA_ALIGNMENT)) % NANOVDB_DATA_ALIGNMENT;
514}
515
516/// @brief offset the specified pointer so it is aligned.
517template <typename T>
518 __hostdev__ inline static T* alignPtr(T* p)
519{
520 NANOVDB_ASSERT(p);
521 return reinterpret_cast<T*>( (uint8_t*)p + alignmentPadding(p) );
522}
523
524/// @brief offset the specified pointer so it is aligned.
525template <typename T>
526 __hostdev__ inline static const T* alignPtr(const T* p)
527{
528 NANOVDB_ASSERT(p);
529 return reinterpret_cast<const T*>( (const uint8_t*)p + alignmentPadding(p) );
530}
531
532// --------------------------> PtrDiff PtrAdd <------------------------------------
533
534template <typename T1, typename T2>
535 __hostdev__ inline static int64_t PtrDiff(const T1* p, const T2* q)
536{
537 NANOVDB_ASSERT(p && q);
538 return reinterpret_cast<const char*>(p) - reinterpret_cast<const char*>(q);
539}
540
541template <typename DstT, typename SrcT>
542 __hostdev__ inline static DstT* PtrAdd(SrcT *p, int64_t offset)
543{
544 NANOVDB_ASSERT(p);
545 return reinterpret_cast<DstT*>(reinterpret_cast<char*>(p) + offset);
546}
547
548template <typename DstT, typename SrcT>
549 __hostdev__ inline static const DstT* PtrAdd(const SrcT *p, int64_t offset)
550{
551 NANOVDB_ASSERT(p);
552 return reinterpret_cast<const DstT*>(reinterpret_cast<const char*>(p) + offset);
553}
554
555// --------------------------> Rgba8 <------------------------------------
556
557/// @brief 8-bit red, green, blue, alpha packed into 32 bit unsigned int
558 class Rgba8
559{
560 union {
561 uint8_t c[4];// 4 color channels of red, green, blue and alpha components.
562 uint32_t packed;// 32 bit packed representation
563 } mData;
564public:
565 static const int SIZE = 4;
566 using ValueType = uint8_t;
567
568 Rgba8(const Rgba8&) = default;
569 Rgba8(Rgba8&&) = default;
570 Rgba8& operator=(Rgba8&&) = default;
571 Rgba8& operator=(const Rgba8&) = default;
572 __hostdev__ Rgba8() : mData{{0,0,0,0}} {static_assert(sizeof(uint32_t) == sizeof(Rgba8),"Unexpected sizeof");}
573 __hostdev__ Rgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255u) : mData{{r, g, b, a}} {}
574 explicit __hostdev__ Rgba8(uint8_t v) : Rgba8(v,v,v,v) {}
575 __hostdev__ Rgba8(float r, float g, float b, float a = 1.0f)
576 : mData{{(uint8_t(0.5f + r * 255.0f)), // round to nearest
577 (uint8_t(0.5f + g * 255.0f)), // round to nearest
578 (uint8_t(0.5f + b * 255.0f)), // round to nearest
579 (uint8_t(0.5f + a * 255.0f))}}// round to nearest
580 {
581 }
582 __hostdev__ bool operator<(const Rgba8& rhs) const { return mData.packed < rhs.mData.packed; }
583 __hostdev__ bool operator==(const Rgba8& rhs) const { return mData.packed == rhs.mData.packed; }
584 __hostdev__ float lengthSqr() const
585 {
586 return 0.0000153787005f*(float(mData.c[0])*mData.c[0] +
587 float(mData.c[1])*mData.c[1] +
588 float(mData.c[2])*mData.c[2]);//1/255^2
589 }
590 __hostdev__ float length() const { return sqrtf(this->lengthSqr() ); }
591 __hostdev__ const uint8_t& operator[](int n) const { return mData.c[n]; }
592 __hostdev__ uint8_t& operator[](int n) { return mData.c[n]; }
593 __hostdev__ const uint32_t& packed() const { return mData.packed; }
594 __hostdev__ uint32_t& packed() { return mData.packed; }
595 __hostdev__ const uint8_t& r() const { return mData.c[0]; }
596 __hostdev__ const uint8_t& g() const { return mData.c[1]; }
597 __hostdev__ const uint8_t& b() const { return mData.c[2]; }
598 __hostdev__ const uint8_t& a() const { return mData.c[3]; }
599 __hostdev__ uint8_t& r() { return mData.c[0]; }
600 __hostdev__ uint8_t& g() { return mData.c[1]; }
601 __hostdev__ uint8_t& b() { return mData.c[2]; }
602 __hostdev__ uint8_t& a() { return mData.c[3]; }
603};// Rgba8
604
605 using PackedRGBA8 = Rgba8;// for backwards compatibility
606
607// --------------------------> isValue(GridType, GridClass) <------------------------------------
608
609/// @brief return true if the GridType maps to a floating point value.
610 __hostdev__ inline bool isFloatingPoint(GridType gridType)
611{
612 return gridType == GridType::Float ||
613 gridType == GridType::Double ||
614 gridType == GridType::Fp4 ||
615 gridType == GridType::Fp8 ||
616 gridType == GridType::Fp16 ||
617 gridType == GridType::FpN;
618}
619
620// --------------------------> isValue(GridType, GridClass) <------------------------------------
621
622/// @brief return true if the combination of GridType and GridClass is valid.
623 __hostdev__ inline bool isValid(GridType gridType, GridClass gridClass)
624{
625 if (gridClass == GridClass::LevelSet || gridClass == GridClass::FogVolume) {
626 return isFloatingPoint(gridType);
627 } else if (gridClass == GridClass::Staggered) {
628 return gridType == GridType::Vec3f || gridType == GridType::Vec3d ||
629 gridType == GridType::Vec4f || gridType == GridType::Vec4d;
630 } else if (gridClass == GridClass::PointIndex || gridClass == GridClass::PointData) {
631 return gridType == GridType::UInt32;
632 } else if (gridClass == GridClass::Topology) {
633 return gridType == GridType::Mask;
634 } else if (gridClass == GridClass::IndexGrid) {
635 return gridType == GridType::Index;
636 } else if (gridClass == GridClass::VoxelVolume) {
637 return gridType == GridType::RGBA8 || gridType == GridType::Float || gridType == GridType::Double || gridType == GridType::Vec3f || gridType == GridType::Vec3d || gridType == GridType::UInt32;
638 }
639 return gridClass < GridClass::End && gridType < GridType::End;// any valid combination
640}
641
642// ----------------------------> Version class <-------------------------------------
643
644/// @brief Bit-compacted representation of all three version numbers
645///
646/// @details major is the top 11 bits, minor is the 11 middle bits and patch is the lower 10 bits
647 class Version
648{
649 uint32_t mData;// 11 + 11 + 10 bit packing of major + minor + patch
650public:
651 __hostdev__ Version() : mData( uint32_t(NANOVDB_MAJOR_VERSION_NUMBER) << 21 |
652 uint32_t(NANOVDB_MINOR_VERSION_NUMBER) << 10 |
653 uint32_t(NANOVDB_PATCH_VERSION_NUMBER) )
654 {
655 }
656 __hostdev__ Version(uint32_t major, uint32_t minor, uint32_t patch)
657 : mData( major << 21 | minor << 10 | patch )
658 {
659 NANOVDB_ASSERT(major < (1u << 11));// max value of major is 2047
660 NANOVDB_ASSERT(minor < (1u << 11));// max value of minor is 2047
661 NANOVDB_ASSERT(patch < (1u << 10));// max value of patch is 1023
662 }
663 __hostdev__ bool operator==(const Version &rhs) const {return mData == rhs.mData;}
664 __hostdev__ bool operator< (const Version &rhs) const {return mData < rhs.mData;}
665 __hostdev__ bool operator<=(const Version &rhs) const {return mData <= rhs.mData;}
666 __hostdev__ bool operator> (const Version &rhs) const {return mData > rhs.mData;}
667 __hostdev__ bool operator>=(const Version &rhs) const {return mData >= rhs.mData;}
668 __hostdev__ uint32_t id() const { return mData; }
669 __hostdev__ uint32_t getMajor() const { return (mData >> 21) & ((1u << 11) - 1);}
670 __hostdev__ uint32_t getMinor() const { return (mData >> 10) & ((1u << 11) - 1);}
671 __hostdev__ uint32_t getPatch() const { return mData & ((1u << 10) - 1);}
672
673#ifndef __CUDACC_RTC__
674 const char* c_str() const
675 {
676 char *buffer = (char*)malloc(4 + 1 + 4 + 1 + 4 + 1);// xxxx.xxxx.xxxx\0
677 snprintf(buffer, 4 + 1 + 4 + 1 + 4 + 1, "%d.%d.%d", this->getMajor(), this->getMinor(), this->getPatch()); // Prevents overflows by enforcing a fixed size of buffer
678 return buffer;
679 }
680#endif
681};// Version
682
683// ----------------------------> Various math functions <-------------------------------------
684
685//@{
686/// Tolerance for floating-point comparison
687template<typename T>
688 struct Tolerance;
689template<>
690 struct Tolerance<float>
691{
692 __hostdev__ static float value() { return 1e-8f; }
693};
694template<>
695 struct Tolerance<double>
696{
697 __hostdev__ static double value() { return 1e-15; }
698};
699//@}
700
701//@{
702/// Delta for small floating-point offsets
703template<typename T>
704 struct Delta;
705template<>
706 struct Delta<float>
707{
708 __hostdev__ static float value() { return 1e-5f; }
709};
710template<>
711 struct Delta<double>
712{
713 __hostdev__ static double value() { return 1e-9; }
714};
715//@}
716
717//@{
718/// Maximum floating-point values
719template<typename T>
720struct Maximum;
721#if defined(__CUDA_ARCH__) || defined(__HIP__)
722template<>
723struct Maximum<int>
724{
725 __hostdev__ static int value() { return 2147483647; }
726};
727template<>
728struct Maximum<uint32_t>
729{
730 __hostdev__ static uint32_t value() { return 4294967295; }
731};
732template<>
733struct Maximum<float>
734{
735 __hostdev__ static float value() { return 1e+38f; }
736};
737template<>
738struct Maximum<double>
739{
740 __hostdev__ static double value() { return 1e+308; }
741};
742#else
743template<typename T>
744 struct Maximum
745{
746 static T value() { return std::numeric_limits<T>::max(); }
747};
748#endif
749//@}
750
751template<typename Type>
752 __hostdev__ inline bool isApproxZero(const Type& x)
753{
754 return !(x > Tolerance<Type>::value()) && !(x < -Tolerance<Type>::value());
755}
756
757template<typename Type>
758 __hostdev__ inline Type Min(Type a, Type b)
759{
760 return (a < b) ? a : b;
761}
762 __hostdev__ inline int32_t Min(int32_t a, int32_t b)
763{
764 return int32_t(fminf(float(a), float(b)));
765}
766 __hostdev__ inline uint32_t Min(uint32_t a, uint32_t b)
767{
768 return uint32_t(fminf(float(a), float(b)));
769}
770 __hostdev__ inline float Min(float a, float b)
771{
772 return fminf(a, b);
773}
774 __hostdev__ inline double Min(double a, double b)
775{
776 return fmin(a, b);
777}
778template<typename Type>
779 __hostdev__ inline Type Max(Type a, Type b)
780{
781 return (a > b) ? a : b;
782}
783
784 __hostdev__ inline int32_t Max(int32_t a, int32_t b)
785{
786 return int32_t(fmaxf(float(a), float(b)));
787}
788 __hostdev__ inline uint32_t Max(uint32_t a, uint32_t b)
789{
790 return uint32_t(fmaxf(float(a), float(b)));
791}
792 __hostdev__ inline float Max(float a, float b)
793{
794 return fmaxf(a, b);
795}
796 __hostdev__ inline double Max(double a, double b)
797{
798 return fmax(a, b);
799}
800 __hostdev__ inline float Clamp(float x, float a, float b)
801{
802 return Max(Min(x, b), a);
803}
804 __hostdev__ inline double Clamp(double x, double a, double b)
805{
806 return Max(Min(x, b), a);
807}
808
809 __hostdev__ inline float Fract(float x)
810{
811 return x - floorf(x);
812}
813 __hostdev__ inline double Fract(double x)
814{
815 return x - floor(x);
816}
817
818 __hostdev__ inline int32_t Floor(float x)
819{
820 return int32_t(floorf(x));
821}
822 __hostdev__ inline int32_t Floor(double x)
823{
824 return int32_t(floor(x));
825}
826
827 __hostdev__ inline int32_t Ceil(float x)
828{
829 return int32_t(ceilf(x));
830}
831 __hostdev__ inline int32_t Ceil(double x)
832{
833 return int32_t(ceil(x));
834}
835
836template<typename T>
837 __hostdev__ inline T Pow2(T x)
838{
839 return x * x;
840}
841
842template<typename T>
843 __hostdev__ inline T Pow3(T x)
844{
845 return x * x * x;
846}
847
848template<typename T>
849 __hostdev__ inline T Pow4(T x)
850{
851 return Pow2(x * x);
852}
853template<typename T>
854 __hostdev__ inline T Abs(T x)
855{
856 return x < 0 ? -x : x;
857}
858
859template<>
860 __hostdev__ inline float Abs(float x)
861{
862 return fabs(x);
863}
864
865template<>
866 __hostdev__ inline double Abs(double x)
867{
868 return fabs(x);
869}
870
871template<>
872 __hostdev__ inline int Abs(int x)
873{
874 return abs(x);
875}
876
877template<typename CoordT, typename RealT, template<typename> class Vec3T>
878 __hostdev__ inline CoordT Round(const Vec3T<RealT>& xyz);
879
880template<typename CoordT, template<typename> class Vec3T>
881 __hostdev__ inline CoordT Round(const Vec3T<float>& xyz)
882{
883 return CoordT(int32_t(rintf(xyz[0])), int32_t(rintf(xyz[1])), int32_t(rintf(xyz[2])));
884 //return CoordT(int32_t(roundf(xyz[0])), int32_t(roundf(xyz[1])), int32_t(roundf(xyz[2])) );
885 //return CoordT(int32_t(floorf(xyz[0] + 0.5f)), int32_t(floorf(xyz[1] + 0.5f)), int32_t(floorf(xyz[2] + 0.5f)));
886}
887
888template<typename CoordT, template<typename> class Vec3T>
889 __hostdev__ inline CoordT Round(const Vec3T<double>& xyz)
890{
891 return CoordT(int32_t(floor(xyz[0] + 0.5)), int32_t(floor(xyz[1] + 0.5)), int32_t(floor(xyz[2] + 0.5)));
892}
893
894template<typename CoordT, typename RealT, template<typename> class Vec3T>
895 __hostdev__ inline CoordT RoundDown(const Vec3T<RealT>& xyz)
896{
897 return CoordT(Floor(xyz[0]), Floor(xyz[1]), Floor(xyz[2]));
898}
899
900//@{
901/// Return the square root of a floating-point value.
902 __hostdev__ inline float Sqrt(float x)
903{
904 return sqrtf(x);
905}
906 __hostdev__ inline double Sqrt(double x)
907{
908 return sqrt(x);
909}
910//@}
911
912/// Return the sign of the given value as an integer (either -1, 0 or 1).
913template <typename T>
914 __hostdev__ inline T Sign(const T &x) { return ((T(0) < x)?T(1):T(0)) - ((x < T(0))?T(1):T(0)); }
915
916template<typename Vec3T>
917 __hostdev__ inline int MinIndex(const Vec3T& v)
918{
919#if 0
920 static const int hashTable[8] = {2, 1, 9, 1, 2, 9, 0, 0}; //9 are dummy values
921 const int hashKey = ((v[0] < v[1]) << 2) + ((v[0] < v[2]) << 1) + (v[1] < v[2]); // ?*4+?*2+?*1
922 return hashTable[hashKey];
923#else
924 if (v[0] < v[1] && v[0] < v[2])
925 return 0;
926 if (v[1] < v[2])
927 return 1;
928 else
929 return 2;
930#endif
931}
932
933template<typename Vec3T>
934 __hostdev__ inline int MaxIndex(const Vec3T& v)
935{
936#if 0
937 static const int hashTable[8] = {2, 1, 9, 1, 2, 9, 0, 0}; //9 are dummy values
938 const int hashKey = ((v[0] > v[1]) << 2) + ((v[0] > v[2]) << 1) + (v[1] > v[2]); // ?*4+?*2+?*1
939 return hashTable[hashKey];
940#else
941 if (v[0] > v[1] && v[0] > v[2])
942 return 0;
943 if (v[1] > v[2])
944 return 1;
945 else
946 return 2;
947#endif
948}
949
950/// @brief round up byteSize to the nearest wordSize, e.g. to align to machine word: AlignUp<sizeof(size_t)(n)
951///
952/// @details both wordSize and byteSize are in byte units
953template<uint64_t wordSize>
954 __hostdev__ inline uint64_t AlignUp(uint64_t byteCount)
955{
956 const uint64_t r = byteCount % wordSize;
957 return r ? byteCount - r + wordSize : byteCount;
958}
959
960// ------------------------------> Coord <--------------------------------------
961
962// forward declaration so we can define Coord::asVec3s and Coord::asVec3d
963template<typename> class Vec3;
964
965/// @brief Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord
966 class Coord
967{
968 int32_t mVec[3]; // private member data - three signed index coordinates
969public:
970 using ValueType = int32_t;
971 using IndexType = uint32_t;
972
973 /// @brief Initialize all coordinates to zero.
974 __hostdev__ Coord()
975 : mVec{0, 0, 0}
976 {
977 }
978
979 /// @brief Initializes all coordinates to the given signed integer.
980 __hostdev__ explicit Coord(ValueType n)
981 : mVec{n, n, n}
982 {
983 }
984
985 /// @brief Initializes coordinate to the given signed integers.
986 __hostdev__ Coord(ValueType i, ValueType j, ValueType k)
987 : mVec{i, j, k}
988 {
989 }
990
991 __hostdev__ Coord(ValueType *ptr)
992 : mVec{ptr[0], ptr[1], ptr[2]}
993 {
994 }
995
996 __hostdev__ int32_t x() const { return mVec[0]; }
997 __hostdev__ int32_t y() const { return mVec[1]; }
998 __hostdev__ int32_t z() const { return mVec[2]; }
999
1000 __hostdev__ int32_t& x() { return mVec[0]; }
1001 __hostdev__ int32_t& y() { return mVec[1]; }
1002 __hostdev__ int32_t& z() { return mVec[2]; }
1003
1004 __hostdev__ static Coord max() { return Coord(int32_t((1u << 31) - 1)); }
1005
1006 __hostdev__ static Coord min() { return Coord(-int32_t((1u << 31) - 1) - 1); }
1007
1008 __hostdev__ static size_t memUsage() { return sizeof(Coord); }
1009
1010 /// @brief Return a const reference to the given Coord component.
1011 /// @warning The argument is assumed to be 0, 1, or 2.
1012 __hostdev__ const ValueType& operator[](IndexType i) const { return mVec[i]; }
1013
1014 /// @brief Return a non-const reference to the given Coord component.
1015 /// @warning The argument is assumed to be 0, 1, or 2.
1016 __hostdev__ ValueType& operator[](IndexType i) { return mVec[i]; }
1017
1018 /// @brief Assignment operator that works with openvdb::Coord
1019 template <typename CoordT>
1020 __hostdev__ Coord& operator=(const CoordT &other)
1021 {
1022 static_assert(sizeof(Coord) == sizeof(CoordT), "Mis-matched sizeof");
1023 mVec[0] = other[0];
1024 mVec[1] = other[1];
1025 mVec[2] = other[2];
1026 return *this;
1027 }
1028
1029 /// @brief Return a new instance with coordinates masked by the given unsigned integer.
1030 __hostdev__ Coord operator&(IndexType n) const { return Coord(mVec[0] & n, mVec[1] & n, mVec[2] & n); }
1031
1032 // @brief Return a new instance with coordinates left-shifted by the given unsigned integer.
1033 __hostdev__ Coord operator<<(IndexType n) const { return Coord(mVec[0] << n, mVec[1] << n, mVec[2] << n); }
1034
1035 // @brief Return a new instance with coordinates right-shifted by the given unsigned integer.
1036 __hostdev__ Coord operator>>(IndexType n) const { return Coord(mVec[0] >> n, mVec[1] >> n, mVec[2] >> n); }
1037
1038 /// @brief Return true if this Coord is lexicographically less than the given Coord.
1039 __hostdev__ bool operator<(const Coord& rhs) const
1040 {
1041 return mVec[0] < rhs[0] ? true : mVec[0] > rhs[0] ? false : mVec[1] < rhs[1] ? true : mVec[1] > rhs[1] ? false : mVec[2] < rhs[2] ? true : false;
1042 }
1043
1044 // @brief Return true if the Coord components are identical.
1045 __hostdev__ bool operator==(const Coord& rhs) const { return mVec[0] == rhs[0] && mVec[1] == rhs[1] && mVec[2] == rhs[2]; }
1046 __hostdev__ bool operator!=(const Coord& rhs) const { return mVec[0] != rhs[0] || mVec[1] != rhs[1] || mVec[2] != rhs[2]; }
1047 __hostdev__ Coord& operator&=(int n)
1048 {
1049 mVec[0] &= n;
1050 mVec[1] &= n;
1051 mVec[2] &= n;
1052 return *this;
1053 }
1054 __hostdev__ Coord& operator<<=(uint32_t n)
1055 {
1056 mVec[0] <<= n;
1057 mVec[1] <<= n;
1058 mVec[2] <<= n;
1059 return *this;
1060 }
1061 __hostdev__ Coord& operator>>=(uint32_t n)
1062 {
1063 mVec[0] >>= n;
1064 mVec[1] >>= n;
1065 mVec[2] >>= n;
1066 return *this;
1067 }
1068 __hostdev__ Coord& operator+=(int n)
1069 {
1070 mVec[0] += n;
1071 mVec[1] += n;
1072 mVec[2] += n;
1073 return *this;
1074 }
1075 __hostdev__ Coord operator+(const Coord& rhs) const { return Coord(mVec[0] + rhs[0], mVec[1] + rhs[1], mVec[2] + rhs[2]); }
1076 __hostdev__ Coord operator-(const Coord& rhs) const { return Coord(mVec[0] - rhs[0], mVec[1] - rhs[1], mVec[2] - rhs[2]); }
1077 __hostdev__ Coord& operator+=(const Coord& rhs)
1078 {
1079 mVec[0] += rhs[0];
1080 mVec[1] += rhs[1];
1081 mVec[2] += rhs[2];
1082 return *this;
1083 }
1084 __hostdev__ Coord& operator-=(const Coord& rhs)
1085 {
1086 mVec[0] -= rhs[0];
1087 mVec[1] -= rhs[1];
1088 mVec[2] -= rhs[2];
1089 return *this;
1090 }
1091
1092 /// @brief Perform a component-wise minimum with the other Coord.
1093 __hostdev__ Coord& minComponent(const Coord& other)
1094 {
1095 if (other[0] < mVec[0])
1096 mVec[0] = other[0];
1097 if (other[1] < mVec[1])
1098 mVec[1] = other[1];
1099 if (other[2] < mVec[2])
1100 mVec[2] = other[2];
1101 return *this;
1102 }
1103
1104 /// @brief Perform a component-wise maximum with the other Coord.
1105 __hostdev__ Coord& maxComponent(const Coord& other)
1106 {
1107 if (other[0] > mVec[0])
1108 mVec[0] = other[0];
1109 if (other[1] > mVec[1])
1110 mVec[1] = other[1];
1111 if (other[2] > mVec[2])
1112 mVec[2] = other[2];
1113 return *this;
1114 }
1115
1116 __hostdev__ Coord offsetBy(ValueType dx, ValueType dy, ValueType dz) const
1117 {
1118 return Coord(mVec[0] + dx, mVec[1] + dy, mVec[2] + dz);
1119 }
1120
1121 __hostdev__ Coord offsetBy(ValueType n) const { return this->offsetBy(n, n, n); }
1122
1123 /// Return true if any of the components of @a a are smaller than the
1124 /// corresponding components of @a b.
1125 __hostdev__ static inline bool lessThan(const Coord& a, const Coord& b)
1126 {
1127 return (a[0] < b[0] || a[1] < b[1] || a[2] < b[2]);
1128 }
1129
1130 /// @brief Return the largest integer coordinates that are not greater
1131 /// than @a xyz (node centered conversion).
1132 template<typename Vec3T>
1133 __hostdev__ static Coord Floor(const Vec3T& xyz) { return Coord(nanovdb::Floor(xyz[0]), nanovdb::Floor(xyz[1]), nanovdb::Floor(xyz[2])); }
1134
1135 /// @brief Return a hash key derived from the existing coordinates.
1136 /// @details For details on this hash function please see the VDB paper.
1137 /// The prime numbers are modified based on the ACM Transactions on Graphics paper:
1138 /// "Real-time 3D reconstruction at scale using voxel hashing"
1139 template<int Log2N = 3 + 4 + 5>
1140 __hostdev__ uint32_t hash() const { return ((1 << Log2N) - 1) & (mVec[0] * 73856093 ^ mVec[1] * 19349669 ^ mVec[2] * 83492791); }
1141
1142 /// @brief Return the octant of this Coord
1143 //__hostdev__ size_t octant() const { return (uint32_t(mVec[0])>>31) | ((uint32_t(mVec[1])>>31)<<1) | ((uint32_t(mVec[2])>>31)<<2); }
1144 __hostdev__ uint8_t octant() const { return uint8_t((uint8_t(bool(mVec[0] & (1u << 31)))) |
1145 (uint8_t(bool(mVec[1] & (1u << 31))) << 1) |
1146 (uint8_t(bool(mVec[2] & (1u << 31))) << 2)); }
1147
1148 /// @brief Return a single precision floating-point vector of this coordinate
1149 __hostdev__ inline Vec3<float> asVec3s() const;
1150
1151 /// @brief Return a double precision floating-point vector of this coordinate
1152 __hostdev__ inline Vec3<double> asVec3d() const;
1153}; // Coord class
1154
1155// ----------------------------> Vec3 <--------------------------------------
1156
1157/// @brief A simple vector class with three double components, similar to openvdb::math::Vec3
1158template<typename T>
1159 class Vec3
1160{
1161 T mVec[3];
1162
1163public:
1164 static const int SIZE = 3;
1165 using ValueType = T;
1166 Vec3() = default;
1167 __hostdev__ explicit Vec3(T x)
1168 : mVec{x, x, x}
1169 {
1170 }
1171 __hostdev__ Vec3(T x, T y, T z)
1172 : mVec{x, y, z}
1173 {
1174 }
1175 template<typename T2>
1176 __hostdev__ explicit Vec3(const Vec3<T2>& v)
1177 : mVec{T(v[0]), T(v[1]), T(v[2])}
1178 {
1179 }
1180 __hostdev__ explicit Vec3(const Coord& ijk)
1181 : mVec{T(ijk[0]), T(ijk[1]), T(ijk[2])}
1182 {
1183 }
1184 __hostdev__ bool operator==(const Vec3& rhs) const { return mVec[0] == rhs[0] && mVec[1] == rhs[1] && mVec[2] == rhs[2]; }
1185 __hostdev__ bool operator!=(const Vec3& rhs) const { return mVec[0] != rhs[0] || mVec[1] != rhs[1] || mVec[2] != rhs[2]; }
1186 template<typename Vec3T>
1187 __hostdev__ Vec3& operator=(const Vec3T& rhs)
1188 {
1189 mVec[0] = rhs[0];
1190 mVec[1] = rhs[1];
1191 mVec[2] = rhs[2];
1192 return *this;
1193 }
1194 __hostdev__ const T& operator[](int i) const { return mVec[i]; }
1195 __hostdev__ T& operator[](int i) { return mVec[i]; }
1196 template<typename Vec3T>
1197 __hostdev__ T dot(const Vec3T& v) const { return mVec[0] * v[0] + mVec[1] * v[1] + mVec[2] * v[2]; }
1198 template<typename Vec3T>
1199 __hostdev__ Vec3 cross(const Vec3T& v) const
1200 {
1201 return Vec3(mVec[1] * v[2] - mVec[2] * v[1],
1202 mVec[2] * v[0] - mVec[0] * v[2],
1203 mVec[0] * v[1] - mVec[1] * v[0]);
1204 }
1205 __hostdev__ T lengthSqr() const
1206 {
1207 return mVec[0] * mVec[0] + mVec[1] * mVec[1] + mVec[2] * mVec[2]; // 5 flops
1208 }
1209 __hostdev__ T length() const { return Sqrt(this->lengthSqr()); }
1210 __hostdev__ Vec3 operator-() const { return Vec3(-mVec[0], -mVec[1], -mVec[2]); }
1211 __hostdev__ Vec3 operator*(const Vec3& v) const { return Vec3(mVec[0] * v[0], mVec[1] * v[1], mVec[2] * v[2]); }
1212 __hostdev__ Vec3 operator/(const Vec3& v) const { return Vec3(mVec[0] / v[0], mVec[1] / v[1], mVec[2] / v[2]); }
1213 __hostdev__ Vec3 operator+(const Vec3& v) const { return Vec3(mVec[0] + v[0], mVec[1] + v[1], mVec[2] + v[2]); }
1214 __hostdev__ Vec3 operator-(const Vec3& v) const { return Vec3(mVec[0] - v[0], mVec[1] - v[1], mVec[2] - v[2]); }
1215 __hostdev__ Vec3 operator*(const T& s) const { return Vec3(s * mVec[0], s * mVec[1], s * mVec[2]); }
1216 __hostdev__ Vec3 operator/(const T& s) const { return (T(1) / s) * (*this); }
1217 __hostdev__ Vec3& operator+=(const Vec3& v)
1218 {
1219 mVec[0] += v[0];
1220 mVec[1] += v[1];
1221 mVec[2] += v[2];
1222 return *this;
1223 }
1224 __hostdev__ Vec3& operator-=(const Vec3& v)
1225 {
1226 mVec[0] -= v[0];
1227 mVec[1] -= v[1];
1228 mVec[2] -= v[2];
1229 return *this;
1230 }
1231 __hostdev__ Vec3& operator*=(const T& s)
1232 {
1233 mVec[0] *= s;
1234 mVec[1] *= s;
1235 mVec[2] *= s;
1236 return *this;
1237 }
1238 __hostdev__ Vec3& operator/=(const T& s) { return (*this) *= T(1) / s; }
1239 __hostdev__ Vec3& normalize() { return (*this) /= this->length(); }
1240 /// @brief Perform a component-wise minimum with the other Coord.
1241 __hostdev__ Vec3& minComponent(const Vec3& other)
1242 {
1243 if (other[0] < mVec[0])
1244 mVec[0] = other[0];
1245 if (other[1] < mVec[1])
1246 mVec[1] = other[1];
1247 if (other[2] < mVec[2])
1248 mVec[2] = other[2];
1249 return *this;
1250 }
1251
1252 /// @brief Perform a component-wise maximum with the other Coord.
1253 __hostdev__ Vec3& maxComponent(const Vec3& other)
1254 {
1255 if (other[0] > mVec[0])
1256 mVec[0] = other[0];
1257 if (other[1] > mVec[1])
1258 mVec[1] = other[1];
1259 if (other[2] > mVec[2])
1260 mVec[2] = other[2];
1261 return *this;
1262 }
1263 /// @brief Return the smallest vector component
1264 __hostdev__ ValueType min() const
1265 {
1266 return mVec[0] < mVec[1] ? (mVec[0] < mVec[2] ? mVec[0] : mVec[2]) : (mVec[1] < mVec[2] ? mVec[1] : mVec[2]);
1267 }
1268 /// @brief Return the largest vector component
1269 __hostdev__ ValueType max() const
1270 {
1271 return mVec[0] > mVec[1] ? (mVec[0] > mVec[2] ? mVec[0] : mVec[2]) : (mVec[1] > mVec[2] ? mVec[1] : mVec[2]);
1272 }
1273 __hostdev__ Coord floor() const { return Coord(Floor(mVec[0]), Floor(mVec[1]), Floor(mVec[2])); }
1274 __hostdev__ Coord ceil() const { return Coord(Ceil(mVec[0]), Ceil(mVec[1]), Ceil(mVec[2])); }
1275 __hostdev__ Coord round() const { return Coord(Floor(mVec[0] + 0.5), Floor(mVec[1] + 0.5), Floor(mVec[2] + 0.5)); }
1276}; // Vec3<T>
1277
1278template<typename T1, typename T2>
1279 __hostdev__ inline Vec3<T2> operator*(T1 scalar, const Vec3<T2>& vec)
1280{
1281 return Vec3<T2>(scalar * vec[0], scalar * vec[1], scalar * vec[2]);
1282}
1283template<typename T1, typename T2>
1284 __hostdev__ inline Vec3<T2> operator/(T1 scalar, const Vec3<T2>& vec)
1285{
1286 return Vec3<T2>(scalar / vec[0], scalar / vec[1], scalar / vec[2]);
1287}
1288
1289 using Vec3R = Vec3<double>;
1290 using Vec3d = Vec3<double>;
1291 using Vec3f = Vec3<float>;
1292 using Vec3i = Vec3<int>;
1293
1294/// @brief Return a single precision floating-point vector of this coordinate
1295 __hostdev__ inline Vec3f Coord::asVec3s() const { return Vec3f(float(mVec[0]), float(mVec[1]), float(mVec[2])); }
1296
1297/// @brief Return a double precision floating-point vector of this coordinate
1298 __hostdev__ inline Vec3d Coord::asVec3d() const { return Vec3d(double(mVec[0]), double(mVec[1]), double(mVec[2])); }
1299
1300// ----------------------------> Vec4 <--------------------------------------
1301
1302/// @brief A simple vector class with three double components, similar to openvdb::math::Vec4
1303template<typename T>
1304 class Vec4
1305{
1306 T mVec[4];
1307
1308public:
1309 static const int SIZE = 4;
1310 using ValueType = T;
1311 Vec4() = default;
1312 __hostdev__ explicit Vec4(T x)
1313 : mVec{x, x, x, x}
1314 {
1315 }
1316 __hostdev__ Vec4(T x, T y, T z, T w)
1317 : mVec{x, y, z, w}
1318 {
1319 }
1320 template<typename T2>
1321 __hostdev__ explicit Vec4(const Vec4<T2>& v)
1322 : mVec{T(v[0]), T(v[1]), T(v[2]), T(v[3])}
1323 {
1324 }
1325 __hostdev__ bool operator==(const Vec4& rhs) const { return mVec[0] == rhs[0] && mVec[1] == rhs[1] && mVec[2] == rhs[2] && mVec[3] == rhs[3]; }
1326 __hostdev__ bool operator!=(const Vec4& rhs) const { return mVec[0] != rhs[0] || mVec[1] != rhs[1] || mVec[2] != rhs[2] || mVec[3] != rhs[3]; }
1327 template<typename Vec4T>
1328 __hostdev__ Vec4& operator=(const Vec4T& rhs)
1329 {
1330 mVec[0] = rhs[0];
1331 mVec[1] = rhs[1];
1332 mVec[2] = rhs[2];
1333 mVec[3] = rhs[3];
1334 return *this;
1335 }
1336 __hostdev__ const T& operator[](int i) const { return mVec[i]; }
1337 __hostdev__ T& operator[](int i) { return mVec[i]; }
1338 template<typename Vec4T>
1339 __hostdev__ T dot(const Vec4T& v) const { return mVec[0] * v[0] + mVec[1] * v[1] + mVec[2] * v[2] + mVec[3] * v[3]; }
1340 __hostdev__ T lengthSqr() const
1341 {
1342 return mVec[0] * mVec[0] + mVec[1] * mVec[1] + mVec[2] * mVec[2] + mVec[3] * mVec[3]; // 7 flops
1343 }
1344 __hostdev__ T length() const { return Sqrt(this->lengthSqr()); }
1345 __hostdev__ Vec4 operator-() const { return Vec4(-mVec[0], -mVec[1], -mVec[2], -mVec[3]); }
1346 __hostdev__ Vec4 operator*(const Vec4& v) const { return Vec4(mVec[0] * v[0], mVec[1] * v[1], mVec[2] * v[2], mVec[3] * v[3]); }
1347 __hostdev__ Vec4 operator/(const Vec4& v) const { return Vec4(mVec[0] / v[0], mVec[1] / v[1], mVec[2] / v[2], mVec[3] / v[3]); }
1348 __hostdev__ Vec4 operator+(const Vec4& v) const { return Vec4(mVec[0] + v[0], mVec[1] + v[1], mVec[2] + v[2], mVec[3] + v[3]); }
1349 __hostdev__ Vec4 operator-(const Vec4& v) const { return Vec4(mVec[0] - v[0], mVec[1] - v[1], mVec[2] - v[2], mVec[3] - v[3]); }
1350 __hostdev__ Vec4 operator*(const T& s) const { return Vec4(s * mVec[0], s * mVec[1], s * mVec[2], s * mVec[3]); }
1351 __hostdev__ Vec4 operator/(const T& s) const { return (T(1) / s) * (*this); }
1352 __hostdev__ Vec4& operator+=(const Vec4& v)
1353 {
1354 mVec[0] += v[0];
1355 mVec[1] += v[1];
1356 mVec[2] += v[2];
1357 mVec[3] += v[3];
1358 return *this;
1359 }
1360 __hostdev__ Vec4& operator-=(const Vec4& v)
1361 {
1362 mVec[0] -= v[0];
1363 mVec[1] -= v[1];
1364 mVec[2] -= v[2];
1365 mVec[3] -= v[3];
1366 return *this;
1367 }
1368 __hostdev__ Vec4& operator*=(const T& s)
1369 {
1370 mVec[0] *= s;
1371 mVec[1] *= s;
1372 mVec[2] *= s;
1373 mVec[3] *= s;
1374 return *this;
1375 }
1376 __hostdev__ Vec4& operator/=(const T& s) { return (*this) *= T(1) / s; }
1377 __hostdev__ Vec4& normalize() { return (*this) /= this->length(); }
1378 /// @brief Perform a component-wise minimum with the other Coord.
1379 __hostdev__ Vec4& minComponent(const Vec4& other)
1380 {
1381 if (other[0] < mVec[0])
1382 mVec[0] = other[0];
1383 if (other[1] < mVec[1])
1384 mVec[1] = other[1];
1385 if (other[2] < mVec[2])
1386 mVec[2] = other[2];
1387 if (other[3] < mVec[3])
1388 mVec[3] = other[3];
1389 return *this;
1390 }
1391
1392 /// @brief Perform a component-wise maximum with the other Coord.
1393 __hostdev__ Vec4& maxComponent(const Vec4& other)
1394 {
1395 if (other[0] > mVec[0])
1396 mVec[0] = other[0];
1397 if (other[1] > mVec[1])
1398 mVec[1] = other[1];
1399 if (other[2] > mVec[2])
1400 mVec[2] = other[2];
1401 if (other[3] > mVec[3])
1402 mVec[3] = other[3];
1403 return *this;
1404 }
1405}; // Vec4<T>
1406
1407template<typename T1, typename T2>
1408 __hostdev__ inline Vec4<T2> operator*(T1 scalar, const Vec4<T2>& vec)
1409{
1410 return Vec4<T2>(scalar * vec[0], scalar * vec[1], scalar * vec[2], scalar * vec[3]);
1411}
1412template<typename T1, typename T2>
1413 __hostdev__ inline Vec4<T2> operator/(T1 scalar, const Vec3<T2>& vec)
1414{
1415 return Vec4<T2>(scalar / vec[0], scalar / vec[1], scalar / vec[2], scalar / vec[3]);
1416}
1417
1418 using Vec4R = Vec4<double>;
1419 using Vec4d = Vec4<double>;
1420 using Vec4f = Vec4<float>;
1421 using Vec4i = Vec4<int>;
1422
1423// ----------------------------> TensorTraits <--------------------------------------
1424
1425template<typename T, int Rank = (is_specialization<T, Vec3>::value ||
1426 is_specialization<T, Vec4>::value ||
1427 is_same<T, Rgba8>::value) ? 1 : 0>
1428 struct TensorTraits;
1429
1430template<typename T>
1431 struct TensorTraits<T, 0>
1432{
1433 static const int Rank = 0; // i.e. scalar
1434 static const bool IsScalar = true;
1435 static const bool IsVector = false;
1436 static const int Size = 1;
1437 using ElementType = T;
1438 static T scalar(const T& s) { return s; }
1439};
1440
1441template<typename T>
1442 struct TensorTraits<T, 1>
1443{
1444 static const int Rank = 1; // i.e. vector
1445 static const bool IsScalar = false;
1446 static const bool IsVector = true;
1447 static const int Size = T::SIZE;
1448 using ElementType = typename T::ValueType;
1449 static ElementType scalar(const T& v) { return v.length(); }
1450};
1451
1452// ----------------------------> FloatTraits <--------------------------------------
1453
1454template<typename T, int = sizeof(typename TensorTraits<T>::ElementType)>
1455 struct FloatTraits
1456{
1457 using FloatType = float;
1458};
1459
1460template<typename T>
1461 struct FloatTraits<T, 8>
1462{
1463 using FloatType = double;
1464};
1465
1466template<>
1467 struct FloatTraits<bool, 1>
1468{
1469 using FloatType = bool;
1470};
1471
1472template<>
1473 struct FloatTraits<ValueIndex, 1>// size of empty class in C++ is 1 byte and not 0 byte
1474{
1475 using FloatType = uint64_t;
1476};
1477
1478template<>
1479 struct FloatTraits<ValueMask, 1>// size of empty class in C++ is 1 byte and not 0 byte
1480{
1481 using FloatType = bool;
1482};
1483
1484// ----------------------------> mapping ValueType -> GridType <--------------------------------------
1485
1486/// @brief Maps from a templated value type to a GridType enum
1487template<typename BuildT>
1488 __hostdev__ inline GridType mapToGridType()
1489{
1490 if (is_same<BuildT, float>::value) { // resolved at compile-time
1491 return GridType::Float;
1492 } else if (is_same<BuildT, double>::value) {
1493 return GridType::Double;
1494 } else if (is_same<BuildT, int16_t>::value) {
1495 return GridType::Int16;
1496 } else if (is_same<BuildT, int32_t>::value) {
1497 return GridType::Int32;
1498 } else if (is_same<BuildT, int64_t>::value) {
1499 return GridType::Int64;
1500 } else if (is_same<BuildT, Vec3f>::value) {
1501 return GridType::Vec3f;
1502 } else if (is_same<BuildT, Vec3d>::value) {
1503 return GridType::Vec3d;
1504 } else if (is_same<BuildT, uint32_t>::value) {
1505 return GridType::UInt32;
1506 } else if (is_same<BuildT, ValueMask>::value) {
1507 return GridType::Mask;
1508 } else if (is_same<BuildT, ValueIndex>::value) {
1509 return GridType::Index;
1510 } else if (is_same<BuildT, bool>::value) {
1511 return GridType::Boolean;
1512 } else if (is_same<BuildT, Rgba8>::value) {
1513 return GridType::RGBA8;
1514 } else if (is_same<BuildT, Fp4>::value) {
1515 return GridType::Fp4;
1516 } else if (is_same<BuildT, Fp8>::value) {
1517 return GridType::Fp8;
1518 } else if (is_same<BuildT, Fp16>::value) {
1519 return GridType::Fp16;
1520 } else if (is_same<BuildT, FpN>::value) {
1521 return GridType::FpN;
1522 } else if (is_same<BuildT, Vec4f>::value) {
1523 return GridType::Vec4f;
1524 } else if (is_same<BuildT, Vec4d>::value) {
1525 return GridType::Vec4d;
1526 }
1527 return GridType::Unknown;
1528}
1529
1530// ----------------------------> matMult <--------------------------------------
1531
1532template<typename Vec3T>
1533 __hostdev__ inline Vec3T matMult(const float* mat, const Vec3T& xyz)
1534{
1535 return Vec3T(fmaf(xyz[0], mat[0], fmaf(xyz[1], mat[1], xyz[2] * mat[2])),
1536 fmaf(xyz[0], mat[3], fmaf(xyz[1], mat[4], xyz[2] * mat[5])),
1537 fmaf(xyz[0], mat[6], fmaf(xyz[1], mat[7], xyz[2] * mat[8]))); // 6 fmaf + 3 mult = 9 flops
1538}
1539
1540template<typename Vec3T>
1541 __hostdev__ inline Vec3T matMult(const double* mat, const Vec3T& xyz)
1542{
1543 return Vec3T(fma(static_cast<double>(xyz[0]), mat[0], fma(static_cast<double>(xyz[1]), mat[1], static_cast<double>(xyz[2]) * mat[2])),
1544 fma(static_cast<double>(xyz[0]), mat[3], fma(static_cast<double>(xyz[1]), mat[4], static_cast<double>(xyz[2]) * mat[5])),
1545 fma(static_cast<double>(xyz[0]), mat[6], fma(static_cast<double>(xyz[1]), mat[7], static_cast<double>(xyz[2]) * mat[8]))); // 6 fmaf + 3 mult = 9 flops
1546}
1547
1548template<typename Vec3T>
1549 __hostdev__ inline Vec3T matMult(const float* mat, const float* vec, const Vec3T& xyz)
1550{
1551 return Vec3T(fmaf(xyz[0], mat[0], fmaf(xyz[1], mat[1], fmaf(xyz[2], mat[2], vec[0]))),
1552 fmaf(xyz[0], mat[3], fmaf(xyz[1], mat[4], fmaf(xyz[2], mat[5], vec[1]))),
1553 fmaf(xyz[0], mat[6], fmaf(xyz[1], mat[7], fmaf(xyz[2], mat[8], vec[2])))); // 9 fmaf = 9 flops
1554}
1555
1556template<typename Vec3T>
1557 __hostdev__ inline Vec3T matMult(const double* mat, const double* vec, const Vec3T& xyz)
1558{
1559 return Vec3T(fma(static_cast<double>(xyz[0]), mat[0], fma(static_cast<double>(xyz[1]), mat[1], fma(static_cast<double>(xyz[2]), mat[2], vec[0]))),
1560 fma(static_cast<double>(xyz[0]), mat[3], fma(static_cast<double>(xyz[1]), mat[4], fma(static_cast<double>(xyz[2]), mat[5], vec[1]))),
1561 fma(static_cast<double>(xyz[0]), mat[6], fma(static_cast<double>(xyz[1]), mat[7], fma(static_cast<double>(xyz[2]), mat[8], vec[2])))); // 9 fma = 9 flops
1562}
1563
1564// matMultT: Multiply with the transpose:
1565
1566template<typename Vec3T>
1567 __hostdev__ inline Vec3T matMultT(const float* mat, const Vec3T& xyz)
1568{
1569 return Vec3T(fmaf(xyz[0], mat[0], fmaf(xyz[1], mat[3], xyz[2] * mat[6])),
1570 fmaf(xyz[0], mat[1], fmaf(xyz[1], mat[4], xyz[2] * mat[7])),
1571 fmaf(xyz[0], mat[2], fmaf(xyz[1], mat[5], xyz[2] * mat[8]))); // 6 fmaf + 3 mult = 9 flops
1572}
1573
1574template<typename Vec3T>
1575 __hostdev__ inline Vec3T matMultT(const double* mat, const Vec3T& xyz)
1576{
1577 return Vec3T(fma(static_cast<double>(xyz[0]), mat[0], fma(static_cast<double>(xyz[1]), mat[3], static_cast<double>(xyz[2]) * mat[6])),
1578 fma(static_cast<double>(xyz[0]), mat[1], fma(static_cast<double>(xyz[1]), mat[4], static_cast<double>(xyz[2]) * mat[7])),
1579 fma(static_cast<double>(xyz[0]), mat[2], fma(static_cast<double>(xyz[1]), mat[5], static_cast<double>(xyz[2]) * mat[8]))); // 6 fmaf + 3 mult = 9 flops
1580}
1581
1582template<typename Vec3T>
1583 __hostdev__ inline Vec3T matMultT(const float* mat, const float* vec, const Vec3T& xyz)
1584{
1585 return Vec3T(fmaf(xyz[0], mat[0], fmaf(xyz[1], mat[3], fmaf(xyz[2], mat[6], vec[0]))),
1586 fmaf(xyz[0], mat[1], fmaf(xyz[1], mat[4], fmaf(xyz[2], mat[7], vec[1]))),
1587 fmaf(xyz[0], mat[2], fmaf(xyz[1], mat[5], fmaf(xyz[2], mat[8], vec[2])))); // 9 fmaf = 9 flops
1588}
1589
1590template<typename Vec3T>
1591 __hostdev__ inline Vec3T matMultT(const double* mat, const double* vec, const Vec3T& xyz)
1592{
1593 return Vec3T(fma(static_cast<double>(xyz[0]), mat[0], fma(static_cast<double>(xyz[1]), mat[3], fma(static_cast<double>(xyz[2]), mat[6], vec[0]))),
1594 fma(static_cast<double>(xyz[0]), mat[1], fma(static_cast<double>(xyz[1]), mat[4], fma(static_cast<double>(xyz[2]), mat[7], vec[1]))),
1595 fma(static_cast<double>(xyz[0]), mat[2], fma(static_cast<double>(xyz[1]), mat[5], fma(static_cast<double>(xyz[2]), mat[8], vec[2])))); // 9 fma = 9 flops
1596}
1597
1598// ----------------------------> BBox <-------------------------------------
1599
1600// Base-class for static polymorphism (cannot be constructed directly)
1601template<typename Vec3T>
1602 struct BaseBBox
1603{
1604 Vec3T mCoord[2];
1605 __hostdev__ bool operator==(const BaseBBox& rhs) const { return mCoord[0] == rhs.mCoord[0] && mCoord[1] == rhs.mCoord[1]; };
1606 __hostdev__ bool operator!=(const BaseBBox& rhs) const { return mCoord[0] != rhs.mCoord[0] || mCoord[1] != rhs.mCoord[1]; };
1607 __hostdev__ const Vec3T& operator[](int i) const { return mCoord[i]; }
1608 __hostdev__ Vec3T& operator[](int i) { return mCoord[i]; }
1609 __hostdev__ Vec3T& min() { return mCoord[0]; }
1610 __hostdev__ Vec3T& max() { return mCoord[1]; }
1611 __hostdev__ const Vec3T& min() const { return mCoord[0]; }
1612 __hostdev__ const Vec3T& max() const { return mCoord[1]; }
1613 __hostdev__ Coord& translate(const Vec3T& xyz)
1614 {
1615 mCoord[0] += xyz;
1616 mCoord[1] += xyz;
1617 return *this;
1618 }
1619 // @brief Expand this bounding box to enclose point (i, j, k).
1620 __hostdev__ BaseBBox& expand(const Vec3T& xyz)
1621 {
1622 mCoord[0].minComponent(xyz);
1623 mCoord[1].maxComponent(xyz);
1624 return *this;
1625 }
1626
1627 /// @brief Intersect this bounding box with the given bounding box.
1628 __hostdev__ BaseBBox& intersect(const BaseBBox& bbox)
1629 {
1630 mCoord[0].maxComponent(bbox.min());
1631 mCoord[1].minComponent(bbox.max());
1632 return *this;
1633 }
1634
1635 //__hostdev__ BaseBBox expandBy(typename Vec3T::ValueType padding) const
1636 //{
1637 // return BaseBBox(mCoord[0].offsetBy(-padding),mCoord[1].offsetBy(padding));
1638 //}
1639 __hostdev__ bool isInside(const Vec3T& xyz)
1640 {
1641 if (xyz[0] < mCoord[0][0] || xyz[1] < mCoord[0][1] || xyz[2] < mCoord[0][2])
1642 return false;
1643 if (xyz[0] > mCoord[1][0] || xyz[1] > mCoord[1][1] || xyz[2] > mCoord[1][2])
1644 return false;
1645 return true;
1646 }
1647
1648protected:
1649 __hostdev__ BaseBBox() {}
1650 __hostdev__ BaseBBox(const Vec3T& min, const Vec3T& max)
1651 : mCoord{min, max}
1652 {
1653 }
1654}; // BaseBBox
1655
1656template<typename Vec3T, bool = is_floating_point<typename Vec3T::ValueType>::value>
1657 struct BBox;
1658
1659/// @brief Partial template specialization for floating point coordinate types.
1660///
1661/// @note Min is inclusive and max is exclusive. If min = max the dimension of
1662/// the bounding box is zero and therefore it is also empty.
1663template<typename Vec3T>
1664 struct BBox<Vec3T, true> : public BaseBBox<Vec3T>
1665{
1666 using Vec3Type = Vec3T;
1667 using ValueType = typename Vec3T::ValueType;
1668 static_assert(is_floating_point<ValueType>::value, "Expected a floating point coordinate type");
1669 using BaseT = BaseBBox<Vec3T>;
1670 using BaseT::mCoord;
1671 __hostdev__ BBox()
1672 : BaseT(Vec3T( Maximum<typename Vec3T::ValueType>::value()),
1673 Vec3T(-Maximum<typename Vec3T::ValueType>::value()))
1674 {
1675 }
1676 __hostdev__ BBox(const Vec3T& min, const Vec3T& max)
1677 : BaseT(min, max)
1678 {
1679 }
1680 __hostdev__ BBox(const Coord& min, const Coord& max)
1681 : BaseT(Vec3T(ValueType(min[0]), ValueType(min[1]), ValueType(min[2])),
1682 Vec3T(ValueType(max[0] + 1), ValueType(max[1] + 1), ValueType(max[2] + 1)))
1683 {
1684 }
1685 __hostdev__ static BBox createCube(const Coord& min, typename Coord::ValueType dim)
1686 {
1687 return BBox(min, min.offsetBy(dim));
1688 }
1689
1690 __hostdev__ BBox(const BaseBBox<Coord>& bbox) : BBox(bbox[0], bbox[1]) {}
1691 __hostdev__ bool empty() const { return mCoord[0][0] >= mCoord[1][0] ||
1692 mCoord[0][1] >= mCoord[1][1] ||
1693 mCoord[0][2] >= mCoord[1][2]; }
1694 __hostdev__ Vec3T dim() const { return this->empty() ? Vec3T(0) : this->max() - this->min(); }
1695 __hostdev__ bool isInside(const Vec3T& p) const
1696 {
1697 return p[0] > mCoord[0][0] && p[1] > mCoord[0][1] && p[2] > mCoord[0][2] &&
1698 p[0] < mCoord[1][0] && p[1] < mCoord[1][1] && p[2] < mCoord[1][2];
1699 }
1700
1701};// BBox<Vec3T, true>
1702
1703/// @brief Partial template specialization for integer coordinate types
1704///
1705/// @note Both min and max are INCLUDED in the bbox so dim = max - min + 1. So,
1706/// if min = max the bounding box contains exactly one point and dim = 1!
1707template<typename CoordT>
1708 struct BBox<CoordT, false> : public BaseBBox<CoordT>
1709{
1710 static_assert(is_same<int, typename CoordT::ValueType>::value, "Expected \"int\" coordinate type");
1711 using BaseT = BaseBBox<CoordT>;
1712 using BaseT::mCoord;
1713 /// @brief Iterator over the domain covered by a BBox
1714 /// @details z is the fastest-moving coordinate.
1715 class Iterator
1716 {
1717 const BBox& mBBox;
1718 CoordT mPos;
1719 public:
1720 __hostdev__ Iterator(const BBox& b)
1721 : mBBox(b)
1722 , mPos(b.min())
1723 {
1724 }
1725 __hostdev__ Iterator& operator++()
1726 {
1727 if (mPos[2] < mBBox[1][2]) {// this is the most common case
1728 ++mPos[2];
1729 } else if (mPos[1] < mBBox[1][1]) {
1730 mPos[2] = mBBox[0][2];
1731 ++mPos[1];
1732 } else if (mPos[0] <= mBBox[1][0]) {
1733 mPos[2] = mBBox[0][2];
1734 mPos[1] = mBBox[0][1];
1735 ++mPos[0];
1736 }
1737 return *this;
1738 }
1739 __hostdev__ Iterator operator++(int)
1740 {
1741 auto tmp = *this;
1742 ++(*this);
1743 return tmp;
1744 }
1745 /// @brief Return @c true if the iterator still points to a valid coordinate.
1746 __hostdev__ operator bool() const { return mPos[0] <= mBBox[1][0]; }
1747 __hostdev__ const CoordT& operator*() const { return mPos; }
1748 }; // Iterator
1749 __hostdev__ Iterator begin() const { return Iterator{*this}; }
1750 __hostdev__ BBox()
1751 : BaseT(CoordT::max(), CoordT::min())
1752 {
1753 }
1754 __hostdev__ BBox(const CoordT& min, const CoordT& max)
1755 : BaseT(min, max)
1756 {
1757 }
1758
1759 template<typename SplitT>
1760 __hostdev__ BBox(BBox& other, const SplitT&)
1761 : BaseT(other.mCoord[0], other.mCoord[1])
1762 {
1763 NANOVDB_ASSERT(this->is_divisible());
1764 const int n = MaxIndex(this->dim());
1765 mCoord[1][n] = (mCoord[0][n] + mCoord[1][n]) >> 1;
1766 other.mCoord[0][n] = mCoord[1][n] + 1;
1767 }
1768
1769 __hostdev__ static BBox createCube(const CoordT& min, typename CoordT::ValueType dim)
1770 {
1771 return BBox(min, min.offsetBy(dim - 1));
1772 }
1773
1774 __hostdev__ bool is_divisible() const { return mCoord[0][0] < mCoord[1][0] &&
1775 mCoord[0][1] < mCoord[1][1] &&
1776 mCoord[0][2] < mCoord[1][2]; }
1777 /// @brief Return true if this bounding box is empty, i.e. uninitialized
1778 __hostdev__ bool empty() const { return mCoord[0][0] > mCoord[1][0] ||
1779 mCoord[0][1] > mCoord[1][1] ||
1780 mCoord[0][2] > mCoord[1][2]; }
1781 __hostdev__ CoordT dim() const { return this->empty() ? Coord(0) : this->max() - this->min() + Coord(1); }
1782 __hostdev__ uint64_t volume() const { auto d = this->dim(); return uint64_t(d[0])*uint64_t(d[1])*uint64_t(d[2]); }
1783 __hostdev__ bool isInside(const CoordT& p) const { return !(CoordT::lessThan(p, this->min()) || CoordT::lessThan(this->max(), p)); }
1784 /// @brief Return @c true if the given bounding box is inside this bounding box.
1785 __hostdev__ bool isInside(const BBox& b) const
1786 {
1787 return !(CoordT::lessThan(b.min(), this->min()) || CoordT::lessThan(this->max(), b.max()));
1788 }
1789
1790 /// @brief Return @c true if the given bounding box overlaps with this bounding box.
1791 __hostdev__ bool hasOverlap(const BBox& b) const
1792 {
1793 return !(CoordT::lessThan(this->max(), b.min()) || CoordT::lessThan(b.max(), this->min()));
1794 }
1795
1796 /// @warning This converts a CoordBBox into a floating-point bounding box which implies that max += 1 !
1797 template<typename RealT>
1798 __hostdev__ BBox<Vec3<RealT>> asReal() const
1799 {
1800 static_assert(is_floating_point<RealT>::value, "CoordBBox::asReal: Expected a floating point coordinate");
1801 return BBox<Vec3<RealT>>(Vec3<RealT>(RealT(mCoord[0][0]), RealT(mCoord[0][1]), RealT(mCoord[0][2])),
1802 Vec3<RealT>(RealT(mCoord[1][0] + 1), RealT(mCoord[1][1] + 1), RealT(mCoord[1][2] + 1)));
1803 }
1804 /// @brief Return a new instance that is expanded by the specified padding.
1805 __hostdev__ BBox expandBy(typename CoordT::ValueType padding) const
1806 {
1807 return BBox(mCoord[0].offsetBy(-padding), mCoord[1].offsetBy(padding));
1808 }
1809};// BBox<CoordT, false>
1810
1811 using CoordBBox = BBox<Coord>;
1812 using BBoxR = BBox<Vec3R>;
1813
1814// -------------------> Find lowest and highest bit in a word <----------------------------
1815
1816/// @brief Returns the index of the lowest, i.e. least significant, on bit in the specified 32 bit word
1817///
1818/// @warning Assumes that at least one bit is set in the word, i.e. @a v != uint32_t(0)!
1819 NANOVDB_HOSTDEV_DISABLE_WARNING
1820 __hostdev__ static inline uint32_t FindLowestOn(uint32_t v)
1821{
1822 NANOVDB_ASSERT(v);
1823#if (defined(__CUDA_ARCH__) || defined(__HIP__)) && defined(NANOVDB_USE_INTRINSICS)
1824 return __ffs(v);
1825#elif defined(_MSC_VER) && defined(NANOVDB_USE_INTRINSICS)
1826 unsigned long index;
1827 _BitScanForward(&index, v);
1828 return static_cast<uint32_t>(index);
1829#elif (defined(__GNUC__) || defined(__clang__)) && defined(NANOVDB_USE_INTRINSICS)
1830 return static_cast<uint32_t>(__builtin_ctzl(v));
1831#else
1832//#warning Using software implementation for FindLowestOn(uint32_t)
1833 static const unsigned char DeBruijn[32] = {
1834 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
1835// disable unary minus on unsigned warning
1836#if defined(_MSC_VER) && !defined(__NVCC__)
1837#pragma warning(push)
1838#pragma warning(disable : 4146)
1839#endif
1840 return DeBruijn[uint32_t((v & -v) * 0x077CB531U) >> 27];
1841#if defined(_MSC_VER) && !defined(__NVCC__)
1842#pragma warning(pop)
1843#endif
1844
1845#endif
1846}
1847
1848/// @brief Returns the index of the highest, i.e. most significant, on bit in the specified 32 bit word
1849///
1850/// @warning Assumes that at least one bit is set in the word, i.e. @a v != uint32_t(0)!
1851 NANOVDB_HOSTDEV_DISABLE_WARNING
1852 __hostdev__ static inline uint32_t FindHighestOn(uint32_t v)
1853{
1854 NANOVDB_ASSERT(v);
1855#if defined(_MSC_VER) && defined(NANOVDB_USE_INTRINSICS)
1856 unsigned long index;
1857 _BitScanReverse(&index, v);
1858 return static_cast<uint32_t>(index);
1859#elif (defined(__GNUC__) || defined(__clang__)) && defined(NANOVDB_USE_INTRINSICS)
1860 return sizeof(unsigned long) * 8 - 1 - __builtin_clzl(v);
1861#else
1862//#warning Using software implementation for FindHighestOn(uint32_t)
1863 static const unsigned char DeBruijn[32] = {
1864 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31};
1865 v |= v >> 1; // first round down to one less than a power of 2
1866 v |= v >> 2;
1867 v |= v >> 4;
1868 v |= v >> 8;
1869 v |= v >> 16;
1870 return DeBruijn[uint32_t(v * 0x07C4ACDDU) >> 27];
1871#endif
1872}
1873
1874/// @brief Returns the index of the lowest, i.e. least significant, on bit in the specified 64 bit word
1875///
1876/// @warning Assumes that at least one bit is set in the word, i.e. @a v != uint32_t(0)!
1877 NANOVDB_HOSTDEV_DISABLE_WARNING
1878 __hostdev__ static inline uint32_t FindLowestOn(uint64_t v)
1879{
1880 NANOVDB_ASSERT(v);
1881#if (defined(__CUDA_ARCH__) || defined(__HIP__)) && defined(NANOVDB_USE_INTRINSICS)
1882 return __ffsll(static_cast<unsigned long long int>(v));
1883#elif defined(_MSC_VER) && defined(NANOVDB_USE_INTRINSICS)
1884 unsigned long index;
1885 _BitScanForward64(&index, v);
1886 return static_cast<uint32_t>(index);
1887#elif (defined(__GNUC__) || defined(__clang__)) && defined(NANOVDB_USE_INTRINSICS)
1888 return static_cast<uint32_t>(__builtin_ctzll(v));
1889#else
1890//#warning Using software implementation for FindLowestOn(uint64_t)
1891 static const unsigned char DeBruijn[64] = {
1892 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
1893 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
1894 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
1895 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12,
1896 };
1897// disable unary minus on unsigned warning
1898#if defined(_MSC_VER) && !defined(__NVCC__)
1899#pragma warning(push)
1900#pragma warning(disable : 4146)
1901#endif
1902 return DeBruijn[uint64_t((v & -v) * UINT64_C(0x022FDD63CC95386D)) >> 58];
1903#if defined(_MSC_VER) && !defined(__NVCC__)
1904#pragma warning(pop)
1905#endif
1906
1907#endif
1908}
1909
1910/// @brief Returns the index of the highest, i.e. most significant, on bit in the specified 64 bit word
1911///
1912/// @warning Assumes that at least one bit is set in the word, i.e. @a v != uint32_t(0)!
1913 NANOVDB_HOSTDEV_DISABLE_WARNING
1914 __hostdev__ static inline uint32_t FindHighestOn(uint64_t v)
1915{
1916 NANOVDB_ASSERT(v);
1917#if defined(_MSC_VER) && defined(NANOVDB_USE_INTRINSICS)
1918 unsigned long index;
1919 _BitScanReverse64(&index, v);
1920 return static_cast<uint32_t>(index);
1921#elif (defined(__GNUC__) || defined(__clang__)) && defined(NANOVDB_USE_INTRINSICS)
1922 return sizeof(unsigned long) * 8 - 1 - __builtin_clzll(v);
1923#else
1924 const uint32_t* p = reinterpret_cast<const uint32_t*>(&v);
1925 return p[1] ? 32u + FindHighestOn(p[1]) : FindHighestOn(p[0]);
1926#endif
1927}
1928
1929// ----------------------------> CountOn <--------------------------------------
1930
1931/// @return Number of bits that are on in the specified 64-bit word
1932 NANOVDB_HOSTDEV_DISABLE_WARNING
1933 __hostdev__ inline uint32_t CountOn(uint64_t v)
1934{
1935#if (defined(__CUDA_ARCH__) || defined(__HIP__)) && defined(NANOVDB_USE_INTRINSICS)
1936//#warning Using popcll for CountOn
1937 return __popcll(v);
1938// __popcnt64 intrinsic support was added in VS 2019 16.8
1939#elif defined(_MSC_VER) && defined(_M_X64) && (_MSC_VER >= 1928) && defined(NANOVDB_USE_INTRINSICS)
1940//#warning Using popcnt64 for CountOn
1941 return __popcnt64(v);
1942#elif (defined(__GNUC__) || defined(__clang__)) && defined(NANOVDB_USE_INTRINSICS)
1943//#warning Using builtin_popcountll for CountOn
1944 return __builtin_popcountll(v);
1945#else// use software implementation
1946//#warning Using software implementation for CountOn
1947 v = v - ((v >> 1) & uint64_t(0x5555555555555555));
1948 v = (v & uint64_t(0x3333333333333333)) + ((v >> 2) & uint64_t(0x3333333333333333));
1949 return (((v + (v >> 4)) & uint64_t(0xF0F0F0F0F0F0F0F)) * uint64_t(0x101010101010101)) >> 56;
1950#endif
1951}
1952
1953// ----------------------------> Mask <--------------------------------------
1954
1955/// @brief Bit-mask to encode active states and facilitate sequential iterators
1956/// and a fast codec for I/O compression.
1957template<uint32_t LOG2DIM>
1958 class Mask
1959{
1960 static constexpr uint32_t SIZE = 1U << (3 * LOG2DIM); // Number of bits in mask
1961 static constexpr uint32_t WORD_COUNT = SIZE >> 6; // Number of 64 bit words
1962 uint64_t mWords[WORD_COUNT];
1963
1964public:
1965 /// @brief Return the memory footprint in bytes of this Mask
1966 __hostdev__ static size_t memUsage() { return sizeof(Mask); }
1967
1968 /// @brief Return the number of bits available in this Mask
1969 __hostdev__ static uint32_t bitCount() { return SIZE; }
1970
1971 /// @brief Return the number of machine words used by this Mask
1972 __hostdev__ static uint32_t wordCount() { return WORD_COUNT; }
1973
1974 /// @brief Return the total number of set bits in this Mask
1975 __hostdev__ uint32_t countOn() const
1976 {
1977 uint32_t sum = 0, n = WORD_COUNT;
1978 for (const uint64_t* w = mWords; n--; ++w)
1979 sum += CountOn(*w);
1980 return sum;
1981 }
1982
1983 /// @brief Return the number of lower set bits in mask up to but excluding the i'th bit
1984 inline __hostdev__ uint32_t countOn(uint32_t i) const
1985 {
1986 uint32_t n = i >> 6, sum = CountOn( mWords[n] & ((uint64_t(1) << (i & 63u))-1u) );
1987 for (const uint64_t* w = mWords; n--; ++w) sum += CountOn(*w);
1988 return sum;
1989 }
1990
1991 template <bool On>
1992 class Iterator
1993 {
1994 public:
1995 __hostdev__ Iterator() : mPos(Mask::SIZE), mParent(nullptr){}
1996 __hostdev__ Iterator(uint32_t pos, const Mask* parent) : mPos(pos), mParent(parent){}
1997 Iterator& operator=(const Iterator&) = default;
1998 __hostdev__ uint32_t operator*() const { return mPos; }
1999 __hostdev__ uint32_t pos() const { return mPos; }
2000 __hostdev__ operator bool() const { return mPos != Mask::SIZE; }
2001 __hostdev__ Iterator& operator++()
2002 {
2003 mPos = mParent->findNext<On>(mPos + 1);
2004 return *this;
2005 }
2006 __hostdev__ Iterator operator++(int)
2007 {
2008 auto tmp = *this;
2009 ++(*this);
2010 return tmp;
2011 }
2012
2013 private:
2014 uint32_t mPos;
2015 const Mask* mParent;
2016 }; // Member class Iterator
2017
2018 using OnIterator = Iterator<true>;
2019 using OffIterator = Iterator<false>;
2020
2021 __hostdev__ OnIterator beginOn() const { return OnIterator(this->findFirst<true>(), this); }
2022
2023 __hostdev__ OffIterator beginOff() const { return OffIterator(this->findFirst<false>(), this); }
2024
2025 /// @brief Initialize all bits to zero.
2026 __hostdev__ Mask()
2027 {
2028 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2029 mWords[i] = 0;
2030 }
2031 __hostdev__ Mask(bool on)
2032 {
2033 const uint64_t v = on ? ~uint64_t(0) : uint64_t(0);
2034 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2035 mWords[i] = v;
2036 }
2037
2038 /// @brief Copy constructor
2039 __hostdev__ Mask(const Mask& other)
2040 {
2041 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2042 mWords[i] = other.mWords[i];
2043 }
2044
2045 /// @brief Return a const reference to the <i>n</i>th word of the bit mask, for a word of arbitrary size.
2046 template<typename WordT>
2047 __hostdev__ const WordT& getWord(int n) const
2048 {
2049 NANOVDB_ASSERT(n * 8 * sizeof(WordT) < SIZE);
2050 return reinterpret_cast<const WordT*>(mWords)[n];
2051 }
2052
2053 /// @brief Return a reference to the <i>n</i>th word of the bit mask, for a word of arbitrary size.
2054 template<typename WordT>
2055 __hostdev__ WordT& getWord(int n)
2056 {
2057 NANOVDB_ASSERT(n * 8 * sizeof(WordT) < SIZE);
2058 return reinterpret_cast<WordT*>(mWords)[n];
2059 }
2060
2061 /// @brief Assignment operator that works with openvdb::util::NodeMask
2062 template<typename MaskT>
2063 __hostdev__ Mask& operator=(const MaskT& other)
2064 {
2065 static_assert(sizeof(Mask) == sizeof(MaskT), "Mismatching sizeof");
2066 static_assert(WORD_COUNT == MaskT::WORD_COUNT, "Mismatching word count");
2067 static_assert(LOG2DIM == MaskT::LOG2DIM, "Mismatching LOG2DIM");
2068 auto *src = reinterpret_cast<const uint64_t*>(&other);
2069 uint64_t *dst = mWords;
2070 for (uint32_t i = 0; i < WORD_COUNT; ++i) {
2071 *dst++ = *src++;
2072 }
2073 return *this;
2074 }
2075
2076 __hostdev__ bool operator==(const Mask& other) const
2077 {
2078 for (uint32_t i = 0; i < WORD_COUNT; ++i) {
2079 if (mWords[i] != other.mWords[i]) return false;
2080 }
2081 return true;
2082 }
2083
2084 __hostdev__ bool operator!=(const Mask& other) const { return !((*this) == other); }
2085
2086 /// @brief Return true if the given bit is set.
2087 __hostdev__ bool isOn(uint32_t n) const { return 0 != (mWords[n >> 6] & (uint64_t(1) << (n & 63))); }
2088
2089 /// @brief Return true if the given bit is NOT set.
2090 __hostdev__ bool isOff(uint32_t n) const { return 0 == (mWords[n >> 6] & (uint64_t(1) << (n & 63))); }
2091
2092 /// @brief Return true if all the bits are set in this Mask.
2093 __hostdev__ bool isOn() const
2094 {
2095 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2096 if (mWords[i] != ~uint64_t(0))
2097 return false;
2098 return true;
2099 }
2100
2101 /// @brief Return true if none of the bits are set in this Mask.
2102 __hostdev__ bool isOff() const
2103 {
2104 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2105 if (mWords[i] != uint64_t(0))
2106 return false;
2107 return true;
2108 }
2109
2110 /// @brief Set the specified bit on.
2111 __hostdev__ void setOn(uint32_t n) { mWords[n >> 6] |= uint64_t(1) << (n & 63); }
2112
2113 /// @brief Set the specified bit off.
2114 __hostdev__ void setOff(uint32_t n) { mWords[n >> 6] &= ~(uint64_t(1) << (n & 63)); }
2115
2116 /// @brief Set the specified bit on or off.
2117 __hostdev__ void set(uint32_t n, bool On)
2118 {
2119#if 1 // switch between branchless
2120 auto &word = mWords[n >> 6];
2121 n &= 63;
2122 word &= ~(uint64_t(1) << n);
2123 word |= uint64_t(On) << n;
2124#else
2125 On ? this->setOn(n) : this->setOff(n);
2126#endif
2127 }
2128
2129 /// @brief Set all bits on
2130 __hostdev__ void setOn()
2131 {
2132 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2133 mWords[i] = ~uint64_t(0);
2134 }
2135
2136 /// @brief Set all bits off
2137 __hostdev__ void setOff()
2138 {
2139 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2140 mWords[i] = uint64_t(0);
2141 }
2142
2143 /// @brief Set all bits off
2144 __hostdev__ void set(bool on)
2145 {
2146 const uint64_t v = on ? ~uint64_t(0) : uint64_t(0);
2147 for (uint32_t i = 0; i < WORD_COUNT; ++i)
2148 mWords[i] = v;
2149 }
2150 /// brief Toggle the state of all bits in the mask
2151 __hostdev__ void toggle()
2152 {
2153 uint32_t n = WORD_COUNT;
2154 for (auto* w = mWords; n--; ++w)
2155 *w = ~*w;
2156 }
2157 __hostdev__ void toggle(uint32_t n) { mWords[n >> 6] ^= uint64_t(1) << (n & 63); }
2158
2159 /// @brief Bitwise intersection
2160 __hostdev__ Mask& operator&=(const Mask& other)
2161 {
2162 uint64_t *w1 = mWords;
2163 const uint64_t *w2 = other.mWords;
2164 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 &= *w2;
2165 return *this;
2166 }
2167 /// @brief Bitwise union
2168 __hostdev__ Mask& operator|=(const Mask& other)
2169 {
2170 uint64_t *w1 = mWords;
2171 const uint64_t *w2 = other.mWords;
2172 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 |= *w2;
2173 return *this;
2174 }
2175 /// @brief Bitwise difference
2176 __hostdev__ Mask& operator-=(const Mask& other)
2177 {
2178 uint64_t *w1 = mWords;
2179 const uint64_t *w2 = other.mWords;
2180 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 &= ~*w2;
2181 return *this;
2182 }
2183 /// @brief Bitwise XOR
2184 __hostdev__ Mask& operator^=(const Mask& other)
2185 {
2186 uint64_t *w1 = mWords;
2187 const uint64_t *w2 = other.mWords;
2188 for (uint32_t n = WORD_COUNT; n--; ++w1, ++w2) *w1 ^= *w2;
2189 return *this;
2190 }
2191
2192private:
2193
2194 NANOVDB_HOSTDEV_DISABLE_WARNING
2195 template <bool On>
2196 __hostdev__ uint32_t findFirst() const
2197 {
2198 uint32_t n = 0;
2199 const uint64_t* w = mWords;
2200 for (; n<WORD_COUNT && !(On ? *w : ~*w); ++w, ++n);
2201 return n==WORD_COUNT ? SIZE : (n << 6) + FindLowestOn(On ? *w : ~*w);
2202 }
2203
2204 NANOVDB_HOSTDEV_DISABLE_WARNING
2205 template <bool On>
2206 __hostdev__ uint32_t findNext(uint32_t start) const
2207 {
2208 uint32_t n = start >> 6; // initiate
2209 if (n >= WORD_COUNT)
2210 return SIZE; // check for out of bounds
2211 uint32_t m = start & 63;
2212 uint64_t b = On ? mWords[n] : ~mWords[n];
2213 if (b & (uint64_t(1) << m))
2214 return start; // simple case: start is on
2215 b &= ~uint64_t(0) << m; // mask out lower bits
2216 while (!b && ++n < WORD_COUNT)
2217 b = On ? mWords[n] : ~mWords[n]; // find next non-zero word
2218 return (!b ? SIZE : (n << 6) + FindLowestOn(b)); // catch last word=0
2219 }
2220}; // Mask class
2221
2222// ----------------------------> Map <--------------------------------------
2223
2224/// @brief Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation
2225 struct Map
2226{
2227 float mMatF[9]; // 9*4B <- 3x3 matrix
2228 float mInvMatF[9]; // 9*4B <- 3x3 matrix
2229 float mVecF[3]; // 3*4B <- translation
2230 float mTaperF; // 4B, placeholder for taper value
2231 double mMatD[9]; // 9*8B <- 3x3 matrix
2232 double mInvMatD[9]; // 9*8B <- 3x3 matrix
2233 double mVecD[3]; // 3*8B <- translation
2234 double mTaperD; // 8B, placeholder for taper value
2235
2236 /// @brief Initialize the member data
2237 template<typename Mat3T, typename Vec3T>
2238 __hostdev__ void set(const Mat3T& mat, const Mat3T& invMat, const Vec3T& translate, double taper);
2239
2240 /// @brief Initialize the member data
2241 /// @note The last (4th) row of invMat is actually ignored.
2242 template<typename Mat4T>
2243 __hostdev__ void set(const Mat4T& mat, const Mat4T& invMat, double taper) {this->set(mat, invMat, mat[3], taper);}
2244
2245 template<typename Vec3T>
2246 __hostdev__ void set(double scale, const Vec3T &translation, double taper);
2247
2248 template<typename Vec3T>
2249 __hostdev__ Vec3T applyMap(const Vec3T& xyz) const { return matMult(mMatD, mVecD, xyz); }
2250 template<typename Vec3T>
2251 __hostdev__ Vec3T applyMapF(const Vec3T& xyz) const { return matMult(mMatF, mVecF, xyz); }
2252
2253 template<typename Vec3T>
2254 __hostdev__ Vec3T applyJacobian(const Vec3T& xyz) const { return matMult(mMatD, xyz); }
2255 template<typename Vec3T>
2256 __hostdev__ Vec3T applyJacobianF(const Vec3T& xyz) const { return matMult(mMatF, xyz); }
2257
2258 template<typename Vec3T>
2259 __hostdev__ Vec3T applyInverseMap(const Vec3T& xyz) const
2260 {
2261 return matMult(mInvMatD, Vec3T(xyz[0] - mVecD[0], xyz[1] - mVecD[1], xyz[2] - mVecD[2]));
2262 }
2263 template<typename Vec3T>
2264 __hostdev__ Vec3T applyInverseMapF(const Vec3T& xyz) const
2265 {
2266 return matMult(mInvMatF, Vec3T(xyz[0] - mVecF[0], xyz[1] - mVecF[1], xyz[2] - mVecF[2]));
2267 }
2268
2269 template<typename Vec3T>
2270 __hostdev__ Vec3T applyInverseJacobian(const Vec3T& xyz) const { return matMult(mInvMatD, xyz); }
2271 template<typename Vec3T>
2272 __hostdev__ Vec3T applyInverseJacobianF(const Vec3T& xyz) const { return matMult(mInvMatF, xyz); }
2273
2274 template<typename Vec3T>
2275 __hostdev__ Vec3T applyIJT(const Vec3T& xyz) const { return matMultT(mInvMatD, xyz); }
2276 template<typename Vec3T>
2277 __hostdev__ Vec3T applyIJTF(const Vec3T& xyz) const { return matMultT(mInvMatF, xyz); }
2278}; // Map
2279
2280template<typename Mat3T, typename Vec3T>
2281 __hostdev__ inline void Map::set(const Mat3T& mat, const Mat3T& invMat, const Vec3T& translate, double taper)
2282{
2283 float *mf = mMatF, *vf = mVecF, *mif = mInvMatF;
2284 double *md = mMatD, *vd = mVecD, *mid = mInvMatD;
2285 mTaperF = static_cast<float>(taper);
2286 mTaperD = taper;
2287 for (int i = 0; i < 3; ++i) {
2288 *vd++ = translate[i]; //translation
2289 *vf++ = static_cast<float>(translate[i]);
2290 for (int j = 0; j < 3; ++j) {
2291 *md++ = mat[j][i]; //transposed
2292 *mid++ = invMat[j][i];
2293 *mf++ = static_cast<float>(mat[j][i]);
2294 *mif++ = static_cast<float>(invMat[j][i]);
2295 }
2296 }
2297}
2298
2299template<typename Vec3T>
2300 __hostdev__ inline void Map::set(double dx, const Vec3T &trans, double taper)
2301{
2302 const double mat[3][3] = {
2303 {dx, 0.0, 0.0}, // row 0
2304 {0.0, dx, 0.0}, // row 1
2305 {0.0, 0.0, dx}, // row 2
2306 }, idx = 1.0/dx, invMat[3][3] = {
2307 {idx, 0.0, 0.0}, // row 0
2308 {0.0, idx, 0.0}, // row 1
2309 {0.0, 0.0, idx}, // row 2
2310 };
2311 this->set(mat, invMat, trans, taper);
2312}
2313
2314// ----------------------------> GridBlindMetaData <--------------------------------------
2315
2316 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) GridBlindMetaData
2317{
2318 static const int MaxNameSize = 256;// due to NULL termination the maximum length is one less!
2319 int64_t mByteOffset; // byte offset to the blind data, relative to the GridData.
2320 uint64_t mElementCount; // number of elements, e.g. point count
2321 uint32_t mFlags; // flags
2322 GridBlindDataSemantic mSemantic; // semantic meaning of the data.
2323 GridBlindDataClass mDataClass; // 4 bytes
2324 GridType mDataType; // 4 bytes
2325 char mName[MaxNameSize];// note this include the NULL termination
2326
2327 /// @brief return memory usage in bytes for the class (note this computes for all blindMetaData structures.)
2328 __hostdev__ static uint64_t memUsage(uint64_t blindDataCount = 0)
2329 {
2330 return blindDataCount * sizeof(GridBlindMetaData);
2331 }
2332
2333 __hostdev__ void setBlindData(void *ptr) { mByteOffset = PtrDiff(ptr, this); }
2334
2335 template <typename T>
2336 __hostdev__ const T* getBlindData() const { return PtrAdd<T>(this, mByteOffset); }
2337
2338}; // GridBlindMetaData
2339
2340// ----------------------------> NodeTrait <--------------------------------------
2341
2342/// @brief Struct to derive node type from its level in a given
2343/// grid, tree or root while preserving constness
2344template<typename GridOrTreeOrRootT, int LEVEL>
2345 struct NodeTrait;
2346
2347// Partial template specialization of above Node struct
2348template<typename GridOrTreeOrRootT>
2349 struct NodeTrait<GridOrTreeOrRootT, 0>
2350{
2351 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2352 using Type = typename GridOrTreeOrRootT::LeafNodeType;
2353 using type = typename GridOrTreeOrRootT::LeafNodeType;
2354};
2355template<typename GridOrTreeOrRootT>
2356 struct NodeTrait<const GridOrTreeOrRootT, 0>
2357{
2358 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2359 using Type = const typename GridOrTreeOrRootT::LeafNodeType;
2360 using type = const typename GridOrTreeOrRootT::LeafNodeType;
2361};
2362
2363template<typename GridOrTreeOrRootT>
2364 struct NodeTrait<GridOrTreeOrRootT, 1>
2365{
2366 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2367 using Type = typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType;
2368 using type = typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType;
2369};
2370template<typename GridOrTreeOrRootT>
2371 struct NodeTrait<const GridOrTreeOrRootT, 1>
2372{
2373 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2374 using Type = const typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType;
2375 using type = const typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType;
2376};
2377template<typename GridOrTreeOrRootT>
2378 struct NodeTrait<GridOrTreeOrRootT, 2>
2379{
2380 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2381 using Type = typename GridOrTreeOrRootT::RootType::ChildNodeType;
2382 using type = typename GridOrTreeOrRootT::RootType::ChildNodeType;
2383};
2384template<typename GridOrTreeOrRootT>
2385 struct NodeTrait<const GridOrTreeOrRootT, 2>
2386{
2387 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2388 using Type = const typename GridOrTreeOrRootT::RootType::ChildNodeType;
2389 using type = const typename GridOrTreeOrRootT::RootType::ChildNodeType;
2390};
2391template<typename GridOrTreeOrRootT>
2392 struct NodeTrait<GridOrTreeOrRootT, 3>
2393{
2394 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2395 using Type = typename GridOrTreeOrRootT::RootType;
2396 using type = typename GridOrTreeOrRootT::RootType;
2397};
2398
2399template<typename GridOrTreeOrRootT>
2400 struct NodeTrait<const GridOrTreeOrRootT, 3>
2401{
2402 static_assert(GridOrTreeOrRootT::RootType::LEVEL == 3, "Tree depth is not supported");
2403 using Type = const typename GridOrTreeOrRootT::RootType;
2404 using type = const typename GridOrTreeOrRootT::RootType;
2405};
2406
2407// ----------------------------> Grid <--------------------------------------
2408
2409/*
2410 The following class and comment is for internal use only
2411
2412 Memory layout:
2413
2414 Grid -> 39 x double (world bbox and affine transformation)
2415 Tree -> Root 3 x ValueType + int32_t + N x Tiles (background,min,max,tileCount + tileCount x Tiles)
2416
2417 N2 upper InternalNodes each with 2 bit masks, N2 tiles, and min/max values
2418
2419 N1 lower InternalNodes each with 2 bit masks, N1 tiles, and min/max values
2420
2421 N0 LeafNodes each with a bit mask, N0 ValueTypes and min/max
2422
2423 Example layout: ("---" implies it has a custom offset, "..." implies zero or more)
2424 [GridData][TreeData]---[RootData][ROOT TILES...]---[NodeData<5>]---[ModeData<4>]---[LeafData<3>]---[BLINDMETA...]---[BLIND0]---[BLIND1]---etc.
2425*/
2426
2427/// @brief Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
2428///
2429/// @note The transform is assumed to be affine (so linear) and have uniform scale! So frustum transforms
2430/// and non-uniform scaling are not supported (primarily because they complicate ray-tracing in index space)
2431///
2432/// @note No client code should (or can) interface with this struct so it can safely be ignored!
2433 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) GridData
2434{// sizeof(GridData) = 672B
2435 static const int MaxNameSize = 256;// due to NULL termination the maximum length is one less
2436 uint64_t mMagic; // 8B (0) magic to validate it is valid grid data.
2437 uint64_t mChecksum; // 8B (8). Checksum of grid buffer.
2438 Version mVersion;// 4B (16) major, minor, and patch version numbers
2439 uint32_t mFlags; // 4B (20). flags for grid.
2440 uint32_t mGridIndex; // 4B (24). Index of this grid in the buffer
2441 uint32_t mGridCount; // 4B (28). Total number of grids in the buffer
2442 uint64_t mGridSize; // 8B (32). byte count of this entire grid occupied in the buffer.
2443 char mGridName[MaxNameSize]; // 256B (40)
2444 Map mMap; // 264B (296). affine transformation between index and world space in both single and double precision
2445 BBox<Vec3R> mWorldBBox; // 48B (560). floating-point AABB of active values in WORLD SPACE (2 x 3 doubles)
2446 Vec3R mVoxelSize; // 24B (608). size of a voxel in world units
2447 GridClass mGridClass; // 4B (632).
2448 GridType mGridType; // 4B (636).
2449 int64_t mBlindMetadataOffset; // 8B (640). offset of GridBlindMetaData structures that follow this grid.
2450 uint32_t mBlindMetadataCount; // 4B (648). count of GridBlindMetaData structures that follow this grid.
2451 uint32_t mData0;// 4B (652)
2452 uint64_t mData1, mData2;// 2x8B (656) padding to 32 B alignment. mData1 is use for the total number of values indexed by an IndexGrid
2453
2454 // Set and unset various bit flags
2455 __hostdev__ void setFlagsOff() { mFlags = uint32_t(0); }
2456 __hostdev__ void setMinMaxOn(bool on = true)
2457 {
2458 if (on) {
2459 mFlags |= static_cast<uint32_t>(GridFlags::HasMinMax);
2460 } else {
2461 mFlags &= ~static_cast<uint32_t>(GridFlags::HasMinMax);
2462 }
2463 }
2464 __hostdev__ void setBBoxOn(bool on = true)
2465 {
2466 if (on) {
2467 mFlags |= static_cast<uint32_t>(GridFlags::HasBBox);
2468 } else {
2469 mFlags &= ~static_cast<uint32_t>(GridFlags::HasBBox);
2470 }
2471 }
2472 __hostdev__ void setLongGridNameOn(bool on = true)
2473 {
2474 if (on) {
2475 mFlags |= static_cast<uint32_t>(GridFlags::HasLongGridName);
2476 } else {
2477 mFlags &= ~static_cast<uint32_t>(GridFlags::HasLongGridName);
2478 }
2479 }
2480 __hostdev__ void setAverageOn(bool on = true)
2481 {
2482 if (on) {
2483 mFlags |= static_cast<uint32_t>(GridFlags::HasAverage);
2484 } else {
2485 mFlags &= ~static_cast<uint32_t>(GridFlags::HasAverage);
2486 }
2487 }
2488 __hostdev__ void setStdDeviationOn(bool on = true)
2489 {
2490 if (on) {
2491 mFlags |= static_cast<uint32_t>(GridFlags::HasStdDeviation);
2492 } else {
2493 mFlags &= ~static_cast<uint32_t>(GridFlags::HasStdDeviation);
2494 }
2495 }
2496 __hostdev__ void setBreadthFirstOn(bool on = true)
2497 {
2498 if (on) {
2499 mFlags |= static_cast<uint32_t>(GridFlags::IsBreadthFirst);
2500 } else {
2501 mFlags &= ~static_cast<uint32_t>(GridFlags::IsBreadthFirst);
2502 }
2503 }
2504
2505 // Affine transformations based on double precision
2506 template<typename Vec3T>
2507 __hostdev__ Vec3T applyMap(const Vec3T& xyz) const { return mMap.applyMap(xyz); } // Pos: index -> world
2508 template<typename Vec3T>
2509 __hostdev__ Vec3T applyInverseMap(const Vec3T& xyz) const { return mMap.applyInverseMap(xyz); } // Pos: world -> index
2510 template<typename Vec3T>
2511 __hostdev__ Vec3T applyJacobian(const Vec3T& xyz) const { return mMap.applyJacobian(xyz); } // Dir: index -> world
2512 template<typename Vec3T>
2513 __hostdev__ Vec3T applyInverseJacobian(const Vec3T& xyz) const { return mMap.applyInverseJacobian(xyz); } // Dir: world -> index
2514 template<typename Vec3T>
2515 __hostdev__ Vec3T applyIJT(const Vec3T& xyz) const { return mMap.applyIJT(xyz); }
2516 // Affine transformations based on single precision
2517 template<typename Vec3T>
2518 __hostdev__ Vec3T applyMapF(const Vec3T& xyz) const { return mMap.applyMapF(xyz); } // Pos: index -> world
2519 template<typename Vec3T>
2520 __hostdev__ Vec3T applyInverseMapF(const Vec3T& xyz) const { return mMap.applyInverseMapF(xyz); } // Pos: world -> index
2521 template<typename Vec3T>
2522 __hostdev__ Vec3T applyJacobianF(const Vec3T& xyz) const { return mMap.applyJacobianF(xyz); } // Dir: index -> world
2523 template<typename Vec3T>
2524 __hostdev__ Vec3T applyInverseJacobianF(const Vec3T& xyz) const { return mMap.applyInverseJacobianF(xyz); } // Dir: world -> index
2525 template<typename Vec3T>
2526 __hostdev__ Vec3T applyIJTF(const Vec3T& xyz) const { return mMap.applyIJTF(xyz); }
2527
2528 // @brief Return a non-const void pointer to the tree
2529 __hostdev__ void* treePtr() { return this + 1; }
2530
2531 // @brief Return a const void pointer to the tree
2532 __hostdev__ const void* treePtr() const { return this + 1; }
2533
2534 /// @brief Returns a const reference to the blindMetaData at the specified linear offset.
2535 ///
2536 /// @warning The linear offset is assumed to be in the valid range
2537 __hostdev__ const GridBlindMetaData* blindMetaData(uint32_t n) const
2538 {
2539 NANOVDB_ASSERT(n < mBlindMetadataCount);
2540 return PtrAdd<GridBlindMetaData>(this, mBlindMetadataOffset) + n;
2541 }
2542
2543}; // GridData
2544
2545// Forward declaration of accelerated random access class
2546template <typename BuildT, int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1>
2547 class ReadAccessor;
2548
2549template <typename BuildT>
2550 using DefaultReadAccessor = ReadAccessor<BuildT, 0, 1, 2>;
2551
2552/// @brief Highest level of the data structure. Contains a tree and a world->index
2553/// transform (that currently only supports uniform scaling and translation).
2554///
2555/// @note This the API of this class to interface with client code
2556template<typename TreeT>
2557 class Grid : private GridData
2558{
2559public:
2560 using TreeType = TreeT;
2561 using RootType = typename TreeT::RootType;
2562 using DataType = GridData;
2563 using ValueType = typename TreeT::ValueType;
2564 using BuildType = typename TreeT::BuildType;// in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
2565 using CoordType = typename TreeT::CoordType;
2566 using AccessorType = DefaultReadAccessor<BuildType>;
2567
2568 /// @brief Disallow constructions, copy and assignment
2569 ///
2570 /// @note Only a Serializer, defined elsewhere, can instantiate this class
2571 Grid(const Grid&) = delete;
2572 Grid& operator=(const Grid&) = delete;
2573 ~Grid() = delete;
2574
2575 __hostdev__ Version version() const { return DataType::mVersion; }
2576
2577 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
2578
2579 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
2580
2581 /// @brief Return memory usage in bytes for this class only.
2582 __hostdev__ static uint64_t memUsage() { return sizeof(GridData); }
2583
2584 /// @brief Return the memory footprint of the entire grid, i.e. including all nodes and blind data
2585 __hostdev__ uint64_t gridSize() const { return DataType::mGridSize; }
2586
2587 /// @brief Return index of this grid in the buffer
2588 __hostdev__ uint32_t gridIndex() const { return DataType::mGridIndex; }
2589
2590 /// @brief Return total number of grids in the buffer
2591 __hostdev__ uint32_t gridCount() const { return DataType::mGridCount; }
2592
2593 /// @brief @brief Return the total number of values indexed by this IndexGrid
2594 ///
2595 /// @note This method is only defined for IndexGrid = NanoGrid<ValueIndex>
2596 template <typename T = BuildType>
2597 __hostdev__ typename enable_if<is_same<T, ValueIndex>::value, const uint64_t&>::type valueCount() const {return DataType::mData1;}
2598
2599 /// @brief Return a const reference to the tree
2600 __hostdev__ const TreeT& tree() const { return *reinterpret_cast<const TreeT*>(this->treePtr()); }
2601
2602 /// @brief Return a non-const reference to the tree
2603 __hostdev__ TreeT& tree() { return *reinterpret_cast<TreeT*>(this->treePtr()); }
2604
2605 /// @brief Return a new instance of a ReadAccessor used to access values in this grid
2606 __hostdev__ AccessorType getAccessor() const { return AccessorType(this->tree().root()); }
2607
2608 /// @brief Return a const reference to the size of a voxel in world units
2609 __hostdev__ const Vec3R& voxelSize() const { return DataType::mVoxelSize; }
2610
2611 /// @brief Return a const reference to the Map for this grid
2612 __hostdev__ const Map& map() const { return DataType::mMap; }
2613
2614 /// @brief world to index space transformation
2615 template<typename Vec3T>
2616 __hostdev__ Vec3T worldToIndex(const Vec3T& xyz) const { return this->applyInverseMap(xyz); }
2617
2618 /// @brief index to world space transformation
2619 template<typename Vec3T>
2620 __hostdev__ Vec3T indexToWorld(const Vec3T& xyz) const { return this->applyMap(xyz); }
2621
2622 /// @brief transformation from index space direction to world space direction
2623 /// @warning assumes dir to be normalized
2624 template<typename Vec3T>
2625 __hostdev__ Vec3T indexToWorldDir(const Vec3T& dir) const { return this->applyJacobian(dir); }
2626
2627 /// @brief transformation from world space direction to index space direction
2628 /// @warning assumes dir to be normalized
2629 template<typename Vec3T>
2630 __hostdev__ Vec3T worldToIndexDir(const Vec3T& dir) const { return this->applyInverseJacobian(dir); }
2631
2632 /// @brief transform the gradient from index space to world space.
2633 /// @details Applies the inverse jacobian transform map.
2634 template<typename Vec3T>
2635 __hostdev__ Vec3T indexToWorldGrad(const Vec3T& grad) const { return this->applyIJT(grad); }
2636
2637 /// @brief world to index space transformation
2638 template<typename Vec3T>
2639 __hostdev__ Vec3T worldToIndexF(const Vec3T& xyz) const { return this->applyInverseMapF(xyz); }
2640
2641 /// @brief index to world space transformation
2642 template<typename Vec3T>
2643 __hostdev__ Vec3T indexToWorldF(const Vec3T& xyz) const { return this->applyMapF(xyz); }
2644
2645 /// @brief transformation from index space direction to world space direction
2646 /// @warning assumes dir to be normalized
2647 template<typename Vec3T>
2648 __hostdev__ Vec3T indexToWorldDirF(const Vec3T& dir) const { return this->applyJacobianF(dir); }
2649
2650 /// @brief transformation from world space direction to index space direction
2651 /// @warning assumes dir to be normalized
2652 template<typename Vec3T>
2653 __hostdev__ Vec3T worldToIndexDirF(const Vec3T& dir) const { return this->applyInverseJacobianF(dir); }
2654
2655 /// @brief Transforms the gradient from index space to world space.
2656 /// @details Applies the inverse jacobian transform map.
2657 template<typename Vec3T>
2658 __hostdev__ Vec3T indexToWorldGradF(const Vec3T& grad) const { return DataType::applyIJTF(grad); }
2659
2660 /// @brief Computes a AABB of active values in world space
2661 __hostdev__ const BBox<Vec3R>& worldBBox() const { return DataType::mWorldBBox; }
2662
2663 /// @brief Computes a AABB of active values in index space
2664 ///
2665 /// @note This method is returning a floating point bounding box and not a CoordBBox. This makes
2666 /// it more useful for clipping rays.
2667 __hostdev__ const BBox<CoordType>& indexBBox() const { return this->tree().bbox(); }
2668
2669 /// @brief Return the total number of active voxels in this tree.
2670 __hostdev__ uint64_t activeVoxelCount() const { return this->tree().activeVoxelCount(); }
2671
2672 /// @brief Methods related to the classification of this grid
2673 __hostdev__ bool isValid() const { return DataType::mMagic == NANOVDB_MAGIC_NUMBER; }
2674 __hostdev__ const GridType& gridType() const { return DataType::mGridType; }
2675 __hostdev__ const GridClass& gridClass() const { return DataType::mGridClass; }
2676 __hostdev__ bool isLevelSet() const { return DataType::mGridClass == GridClass::LevelSet; }
2677 __hostdev__ bool isFogVolume() const { return DataType::mGridClass == GridClass::FogVolume; }
2678 __hostdev__ bool isStaggered() const { return DataType::mGridClass == GridClass::Staggered; }
2679 __hostdev__ bool isPointIndex() const { return DataType::mGridClass == GridClass::PointIndex; }
2680 __hostdev__ bool isGridIndex() const { return DataType::mGridClass == GridClass::IndexGrid; }
2681 __hostdev__ bool isPointData() const { return DataType::mGridClass == GridClass::PointData; }
2682 __hostdev__ bool isMask() const { return DataType::mGridClass == GridClass::Topology; }
2683 __hostdev__ bool isUnknown() const { return DataType::mGridClass == GridClass::Unknown; }
2684 __hostdev__ bool hasMinMax() const { return DataType::mFlags & static_cast<uint32_t>(GridFlags::HasMinMax); }
2685 __hostdev__ bool hasBBox() const { return DataType::mFlags & static_cast<uint32_t>(GridFlags::HasBBox); }
2686 __hostdev__ bool hasLongGridName() const { return DataType::mFlags & static_cast<uint32_t>(GridFlags::HasLongGridName); }
2687 __hostdev__ bool hasAverage() const { return DataType::mFlags & static_cast<uint32_t>(GridFlags::HasAverage); }
2688 __hostdev__ bool hasStdDeviation() const { return DataType::mFlags & static_cast<uint32_t>(GridFlags::HasStdDeviation); }
2689 __hostdev__ bool isBreadthFirst() const { return DataType::mFlags & static_cast<uint32_t>(GridFlags::IsBreadthFirst); }
2690
2691 /// @brief return true if the specified node type is layed out breadth-first in memory and has a fixed size.
2692 /// This allows for sequential access to the nodes.
2693 template <typename NodeT>
2694 __hostdev__ bool isSequential() const { return NodeT::FIXED_SIZE && this->isBreadthFirst(); }
2695
2696 /// @brief return true if the specified node level is layed out breadth-first in memory and has a fixed size.
2697 /// This allows for sequential access to the nodes.
2698 template <int LEVEL>
2699 __hostdev__ bool isSequential() const { return NodeTrait<TreeT,LEVEL>::type::FIXED_SIZE && this->isBreadthFirst(); }
2700
2701 /// @brief Return a c-string with the name of this grid
2702 __hostdev__ const char* gridName() const
2703 {
2704 if (this->hasLongGridName()) {
2705 NANOVDB_ASSERT(DataType::mBlindMetadataCount>0);
2706 const auto &metaData = this->blindMetaData(DataType::mBlindMetadataCount-1);// always the last
2707 NANOVDB_ASSERT(metaData.mDataClass == GridBlindDataClass::GridName);
2708 return metaData.template getBlindData<const char>();
2709 }
2710 return DataType::mGridName;
2711 }
2712
2713 /// @brief Return a c-string with the name of this grid, truncated to 255 characters
2714 __hostdev__ const char* shortGridName() const { return DataType::mGridName; }
2715
2716 /// @brief Return checksum of the grid buffer.
2717 __hostdev__ uint64_t checksum() const { return DataType::mChecksum; }
2718
2719 /// @brief Return true if this grid is empty, i.e. contains no values or nodes.
2720 __hostdev__ bool isEmpty() const { return this->tree().isEmpty(); }
2721
2722 /// @brief Return the count of blind-data encoded in this grid
2723 __hostdev__ uint32_t blindDataCount() const { return DataType::mBlindMetadataCount; }
2724
2725 /// @brief Return the index of the blind data with specified semantic if found, otherwise -1.
2726 __hostdev__ int findBlindDataForSemantic(GridBlindDataSemantic semantic) const;
2727
2728 /// @brief Returns a const pointer to the blindData at the specified linear offset.
2729 ///
2730 /// @warning Point might be NULL and the linear offset is assumed to be in the valid range
2731 __hostdev__ const void* blindData(uint32_t n) const
2732 {
2733 if (DataType::mBlindMetadataCount == 0u) {
2734 return nullptr;
2735 }
2736 NANOVDB_ASSERT(n < DataType::mBlindMetadataCount);
2737 return this->blindMetaData(n).template getBlindData<void>();
2738 }
2739
2740 __hostdev__ const GridBlindMetaData& blindMetaData(uint32_t n) const { return *DataType::blindMetaData(n); }
2741
2742private:
2743 static_assert(sizeof(GridData) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(GridData) is misaligned");
2744}; // Class Grid
2745
2746template<typename TreeT>
2747 __hostdev__ int Grid<TreeT>::findBlindDataForSemantic(GridBlindDataSemantic semantic) const
2748{
2749 for (uint32_t i = 0, n = this->blindDataCount(); i < n; ++i)
2750 if (this->blindMetaData(i).mSemantic == semantic)
2751 return int(i);
2752 return -1;
2753}
2754
2755// ----------------------------> Tree <--------------------------------------
2756
2757template<int ROOT_LEVEL = 3>
2758 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) TreeData
2759{// sizeof(TreeData<3>) == 64B
2760 static_assert(ROOT_LEVEL == 3, "Root level is assumed to be three");
2761 uint64_t mNodeOffset[4];//32B, byte offset from this tree to first leaf, lower, upper and root node
2762 uint32_t mNodeCount[3];// 12B, total number of nodes of type: leaf, lower internal, upper internal
2763 uint32_t mTileCount[3];// 12B, total number of active tile values at the lower internal, upper internal and root node levels
2764 uint64_t mVoxelCount;// 8B, total number of active voxels in the root and all its child nodes.
2765 // No padding since it's always 32B aligned
2766 template <typename RootT>
2767 __hostdev__ void setRoot(const RootT* root) { mNodeOffset[3] = PtrDiff(root, this); }
2768 template <typename RootT>
2769 __hostdev__ RootT* getRoot() { return PtrAdd<RootT>(this, mNodeOffset[3]); }
2770 template <typename RootT>
2771 __hostdev__ const RootT* getRoot() const { return PtrAdd<RootT>(this, mNodeOffset[3]); }
2772
2773 template <typename NodeT>
2774 __hostdev__ void setFirstNode(const NodeT* node)
2775 {
2776 mNodeOffset[NodeT::LEVEL] = node ? PtrDiff(node, this) : 0;
2777 }
2778};
2779
2780// ----------------------------> GridTree <--------------------------------------
2781
2782/// @brief defines a tree type from a grid type while preserving constness
2783template<typename GridT>
2784 struct GridTree
2785{
2786 using Type = typename GridT::TreeType;
2787 using type = typename GridT::TreeType;
2788};
2789template<typename GridT>
2790 struct GridTree<const GridT>
2791{
2792 using Type = const typename GridT::TreeType;
2793 using type = const typename GridT::TreeType;
2794};
2795
2796// ----------------------------> Tree <--------------------------------------
2797
2798/// @brief VDB Tree, which is a thin wrapper around a RootNode.
2799template<typename RootT>
2800 class Tree : private TreeData<RootT::LEVEL>
2801{
2802 static_assert(RootT::LEVEL == 3, "Tree depth is not supported");
2803 static_assert(RootT::ChildNodeType::LOG2DIM == 5, "Tree configuration is not supported");
2804 static_assert(RootT::ChildNodeType::ChildNodeType::LOG2DIM == 4, "Tree configuration is not supported");
2805 static_assert(RootT::LeafNodeType::LOG2DIM == 3, "Tree configuration is not supported");
2806
2807public:
2808 using DataType = TreeData<RootT::LEVEL>;
2809 using RootType = RootT;
2810 using LeafNodeType = typename RootT::LeafNodeType;
2811 using ValueType = typename RootT::ValueType;
2812 using BuildType = typename RootT::BuildType;// in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
2813 using CoordType = typename RootT::CoordType;
2814 using AccessorType = DefaultReadAccessor<BuildType>;
2815
2816 using Node3 = RootT;
2817 using Node2 = typename RootT::ChildNodeType;
2818 using Node1 = typename Node2::ChildNodeType;
2819 using Node0 = LeafNodeType;
2820
2821 /// @brief This class cannot be constructed or deleted
2822 Tree() = delete;
2823 Tree(const Tree&) = delete;
2824 Tree& operator=(const Tree&) = delete;
2825 ~Tree() = delete;
2826
2827 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
2828
2829 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
2830
2831 /// @brief return memory usage in bytes for the class
2832 __hostdev__ static uint64_t memUsage() { return sizeof(DataType); }
2833
2834 __hostdev__ RootT& root() { return *DataType::template getRoot<RootT>(); }
2835
2836 __hostdev__ const RootT& root() const { return *DataType::template getRoot<RootT>(); }
2837
2838 __hostdev__ AccessorType getAccessor() const { return AccessorType(this->root()); }
2839
2840 /// @brief Return the value of the given voxel (regardless of state or location in the tree.)
2841 __hostdev__ ValueType getValue(const CoordType& ijk) const { return this->root().getValue(ijk); }
2842
2843 /// @brief Return the active state of the given voxel (regardless of state or location in the tree.)
2844 __hostdev__ bool isActive(const CoordType& ijk) const { return this->root().isActive(ijk); }
2845
2846 /// @brief Return true if this tree is empty, i.e. contains no values or nodes
2847 __hostdev__ bool isEmpty() const { return this->root().isEmpty(); }
2848
2849 /// @brief Combines the previous two methods in a single call
2850 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const { return this->root().probeValue(ijk, v); }
2851
2852 /// @brief Return a const reference to the background value.
2853 __hostdev__ const ValueType& background() const { return this->root().background(); }
2854
2855 /// @brief Sets the extrema values of all the active values in this tree, i.e. in all nodes of the tree
2856 __hostdev__ void extrema(ValueType& min, ValueType& max) const;
2857
2858 /// @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
2859 __hostdev__ const BBox<CoordType>& bbox() const { return this->root().bbox(); }
2860
2861 /// @brief Return the total number of active voxels in this tree.
2862 __hostdev__ uint64_t activeVoxelCount() const { return DataType::mVoxelCount; }
2863
2864 /// @brief Return the total number of active tiles at the specified level of the tree.
2865 ///
2866 /// @details level = 1,2,3 corresponds to active tile count in lower internal nodes, upper
2867 /// internal nodes, and the root level. Note active values at the leaf level are
2868 /// referred to as active voxels (see activeVoxelCount defined above).
2869 __hostdev__ const uint32_t& activeTileCount(uint32_t level) const
2870 {
2871 NANOVDB_ASSERT(level > 0 && level <= 3);// 1, 2, or 3
2872 return DataType::mTileCount[level - 1];
2873 }
2874
2875 template<typename NodeT>
2876 __hostdev__ uint32_t nodeCount() const
2877 {
2878 static_assert(NodeT::LEVEL < 3, "Invalid NodeT");
2879 return DataType::mNodeCount[NodeT::LEVEL];
2880 }
2881
2882 __hostdev__ uint32_t nodeCount(int level) const
2883 {
2884 NANOVDB_ASSERT(level < 3);
2885 return DataType::mNodeCount[level];
2886 }
2887
2888 /// @brief return a pointer to the first node of the specified type
2889 ///
2890 /// @warning Note it may return NULL if no nodes exist
2891 template <typename NodeT>
2892 __hostdev__ NodeT* getFirstNode()
2893 {
2894 const uint64_t offset = DataType::mNodeOffset[NodeT::LEVEL];
2895 return offset>0 ? PtrAdd<NodeT>(this, offset) : nullptr;
2896 }
2897
2898 /// @brief return a const pointer to the first node of the specified type
2899 ///
2900 /// @warning Note it may return NULL if no nodes exist
2901 template <typename NodeT>
2902 __hostdev__ const NodeT* getFirstNode() const
2903 {
2904 const uint64_t offset = DataType::mNodeOffset[NodeT::LEVEL];
2905 return offset>0 ? PtrAdd<NodeT>(this, offset) : nullptr;
2906 }
2907
2908 /// @brief return a pointer to the first node at the specified level
2909 ///
2910 /// @warning Note it may return NULL if no nodes exist
2911 template <int LEVEL>
2912 __hostdev__ typename NodeTrait<RootT, LEVEL>::type*
2913 getFirstNode()
2914 {
2915 return this->template getFirstNode<typename NodeTrait<RootT,LEVEL>::type>();
2916 }
2917
2918 /// @brief return a const pointer to the first node of the specified level
2919 ///
2920 /// @warning Note it may return NULL if no nodes exist
2921 template <int LEVEL>
2922 __hostdev__ const typename NodeTrait<RootT, LEVEL>::type*
2923 getFirstNode() const
2924 {
2925 return this->template getFirstNode<typename NodeTrait<RootT,LEVEL>::type>();
2926 }
2927
2928 /// @brief Template specializations of getFirstNode
2929 __hostdev__ LeafNodeType* getFirstLeaf() {return this->getFirstNode<LeafNodeType>();}
2930 __hostdev__ const LeafNodeType* getFirstLeaf() const {return this->getFirstNode<LeafNodeType>();}
2931 __hostdev__ typename NodeTrait<RootT, 1>::type* getFirstLower() {return this->getFirstNode<1>();}
2932 __hostdev__ const typename NodeTrait<RootT, 1>::type* getFirstLower() const {return this->getFirstNode<1>();}
2933 __hostdev__ typename NodeTrait<RootT, 2>::type* getFirstUpper() {return this->getFirstNode<2>();}
2934 __hostdev__ const typename NodeTrait<RootT, 2>::type* getFirstUpper() const {return this->getFirstNode<2>();}
2935
2936private:
2937 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(TreeData) is misaligned");
2938
2939}; // Tree class
2940
2941template<typename RootT>
2942 __hostdev__ void Tree<RootT>::extrema(ValueType& min, ValueType& max) const
2943{
2944 min = this->root().minimum();
2945 max = this->root().maximum();
2946}
2947
2948// --------------------------> RootNode <------------------------------------
2949
2950/// @brief Struct with all the member data of the RootNode (useful during serialization of an openvdb RootNode)
2951///
2952/// @note No client code should (or can) interface with this struct so it can safely be ignored!
2953template<typename ChildT>
2954 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) RootData
2955{
2956 using ValueT = typename ChildT::ValueType;
2957 using BuildT = typename ChildT::BuildType;// in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
2958 using CoordT = typename ChildT::CoordType;
2959 using StatsT = typename ChildT::FloatType;
2960 static constexpr bool FIXED_SIZE = false;
2961
2962 /// @brief Return a key based on the coordinates of a voxel
2963#ifdef USE_SINGLE_ROOT_KEY
2964 using KeyT = uint64_t;
2965 template <typename CoordType>
2966 __hostdev__ static KeyT CoordToKey(const CoordType& ijk)
2967 {
2968 static_assert(sizeof(CoordT) == sizeof(CoordType), "Mismatching sizeof");
2969 static_assert(32 - ChildT::TOTAL <= 21, "Cannot use 64 bit root keys");
2970 return (KeyT(uint32_t(ijk[2]) >> ChildT::TOTAL)) | // z is the lower 21 bits
2971 (KeyT(uint32_t(ijk[1]) >> ChildT::TOTAL) << 21) | // y is the middle 21 bits
2972 (KeyT(uint32_t(ijk[0]) >> ChildT::TOTAL) << 42); // x is the upper 21 bits
2973 }
2974 __hostdev__ static CoordT KeyToCoord(const KeyT& key)
2975 {
2976 static constexpr uint64_t MASK = (1u << 21) - 1;
2977 return CoordT(((key >> 42) & MASK) << ChildT::TOTAL,
2978 ((key >> 21) & MASK) << ChildT::TOTAL,
2979 (key & MASK) << ChildT::TOTAL);
2980 }
2981#else
2982 using KeyT = CoordT;
2983 __hostdev__ static KeyT CoordToKey(const CoordT& ijk) { return ijk & ~ChildT::MASK; }
2984 __hostdev__ static CoordT KeyToCoord(const KeyT& key) { return key; }
2985#endif
2986 BBox<CoordT> mBBox; // 24B. AABB of active values in index space.
2987 uint32_t mTableSize; // 4B. number of tiles and child pointers in the root node
2988
2989 ValueT mBackground; // background value, i.e. value of any unset voxel
2990 ValueT mMinimum; // typically 4B, minimum of all the active values
2991 ValueT mMaximum; // typically 4B, maximum of all the active values
2992 StatsT mAverage; // typically 4B, average of all the active values in this node and its child nodes
2993 StatsT mStdDevi; // typically 4B, standard deviation of all the active values in this node and its child nodes
2994
2995 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
2996 ///
2997 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
2998 __hostdev__ static constexpr uint32_t padding() {
2999 return sizeof(RootData) - (24 + 4 + 3*sizeof(ValueT) + 2*sizeof(StatsT));
3000 }
3001
3002 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) Tile
3003 {
3004 template <typename CoordType>
3005 __hostdev__ void setChild(const CoordType& k, const ChildT *ptr, const RootData *data)
3006 {
3007 key = CoordToKey(k);
3008 child = PtrDiff(ptr, data);
3009 }
3010 template <typename CoordType, typename ValueType>
3011 __hostdev__ void setValue(const CoordType& k, bool s, const ValueType &v)
3012 {
3013 key = CoordToKey(k);
3014 state = s;
3015 value = v;
3016 child = 0;
3017 }
3018 __hostdev__ bool isChild() const { return child!=0; }
3019 __hostdev__ bool isValue() const { return child==0; }
3020 __hostdev__ bool isActive() const { return child==0 && state; }
3021 __hostdev__ CoordT origin() const { return KeyToCoord(key); }
3022 KeyT key; // USE_SINGLE_ROOT_KEY ? 8B : 12B
3023 int64_t child; // 8B. signed byte offset from this node to the child node. 0 means it is a constant tile, so use value.
3024 uint32_t state; // 4B. state of tile value
3025 ValueT value; // value of tile (i.e. no child node)
3026 }; // Tile
3027
3028 /// @brief Returns a non-const reference to the tile at the specified linear offset.
3029 ///
3030 /// @warning The linear offset is assumed to be in the valid range
3031 __hostdev__ const Tile* tile(uint32_t n) const
3032 {
3033 NANOVDB_ASSERT(n < mTableSize);
3034 return reinterpret_cast<const Tile*>(this + 1) + n;
3035 }
3036 __hostdev__ Tile* tile(uint32_t n)
3037 {
3038 NANOVDB_ASSERT(n < mTableSize);
3039 return reinterpret_cast<Tile*>(this + 1) + n;
3040 }
3041
3042 /// @brief Returns a const reference to the child node in the specified tile.
3043 ///
3044 /// @warning A child node is assumed to exist in the specified tile
3045 __hostdev__ ChildT* getChild(const Tile* tile)
3046 {
3047 NANOVDB_ASSERT(tile->child);
3048 return PtrAdd<ChildT>(this, tile->child);
3049 }
3050 __hostdev__ const ChildT* getChild(const Tile* tile) const
3051 {
3052 NANOVDB_ASSERT(tile->child);
3053 return PtrAdd<ChildT>(this, tile->child);
3054 }
3055
3056 __hostdev__ const ValueT& getMin() const { return mMinimum; }
3057 __hostdev__ const ValueT& getMax() const { return mMaximum; }
3058 __hostdev__ const StatsT& average() const { return mAverage; }
3059 __hostdev__ const StatsT& stdDeviation() const { return mStdDevi; }
3060
3061 __hostdev__ void setMin(const ValueT& v) { mMinimum = v; }
3062 __hostdev__ void setMax(const ValueT& v) { mMaximum = v; }
3063 __hostdev__ void setAvg(const StatsT& v) { mAverage = v; }
3064 __hostdev__ void setDev(const StatsT& v) { mStdDevi = v; }
3065
3066 /// @brief This class cannot be constructed or deleted
3067 RootData() = delete;
3068 RootData(const RootData&) = delete;
3069 RootData& operator=(const RootData&) = delete;
3070 ~RootData() = delete;
3071}; // RootData
3072
3073/// @brief Top-most node of the VDB tree structure.
3074template<typename ChildT>
3075 class RootNode : private RootData<ChildT>
3076{
3077public:
3078 using DataType = RootData<ChildT>;
3079 using LeafNodeType = typename ChildT::LeafNodeType;
3080 using ChildNodeType = ChildT;
3081 using RootType = RootNode<ChildT>;// this allows RootNode to behave like a Tree
3082
3083 using ValueType = typename DataType::ValueT;
3084 using FloatType = typename DataType::StatsT;
3085 using BuildType = typename DataType::BuildT;// in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
3086
3087 using CoordType = typename ChildT::CoordType;
3088 using BBoxType = BBox<CoordType>;
3089 using AccessorType = DefaultReadAccessor<BuildType>;
3090 using Tile = typename DataType::Tile;
3091 static constexpr bool FIXED_SIZE = DataType::FIXED_SIZE;
3092
3093 static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
3094
3095 class ChildIterator
3096 {
3097 const DataType *mParent;
3098 uint32_t mPos, mSize;
3099 public:
3100 __hostdev__ ChildIterator() : mParent(nullptr), mPos(0), mSize(0) {}
3101 __hostdev__ ChildIterator(const RootNode *parent) : mParent(parent->data()), mPos(0), mSize(parent->tileCount()) {
3102 NANOVDB_ASSERT(mParent);
3103 while (mPos<mSize && !mParent->tile(mPos)->isChild()) ++mPos;
3104 }
3105 ChildIterator& operator=(const ChildIterator&) = default;
3106 __hostdev__ const ChildT& operator*() const {NANOVDB_ASSERT(*this); return *mParent->getChild(mParent->tile(mPos));}
3107 __hostdev__ const ChildT* operator->() const {NANOVDB_ASSERT(*this); return mParent->getChild(mParent->tile(mPos));}
3108 __hostdev__ CoordType getOrigin() const { NANOVDB_ASSERT(*this); mParent->tile(mPos)->origin();}
3109 __hostdev__ operator bool() const {return mPos < mSize;}
3110 __hostdev__ uint32_t pos() const {return mPos;}
3111 __hostdev__ ChildIterator& operator++() {
3112 NANOVDB_ASSERT(mParent);
3113 ++mPos;
3114 while (mPos < mSize && mParent->tile(mPos)->isValue()) ++mPos;
3115 return *this;
3116 }
3117 __hostdev__ ChildIterator operator++(int) {
3118 auto tmp = *this;
3119 ++(*this);
3120 return tmp;
3121 }
3122 }; // Member class ChildIterator
3123
3124 ChildIterator beginChild() const {return ChildIterator(this);}
3125
3126 class ValueIterator
3127 {
3128 const DataType *mParent;
3129 uint32_t mPos, mSize;
3130 public:
3131 __hostdev__ ValueIterator() : mParent(nullptr), mPos(0), mSize(0) {}
3132 __hostdev__ ValueIterator(const RootNode *parent) : mParent(parent->data()), mPos(0), mSize(parent->tileCount()){
3133 NANOVDB_ASSERT(mParent);
3134 while (mPos < mSize && mParent->tile(mPos)->isChild()) ++mPos;
3135 }
3136 ValueIterator& operator=(const ValueIterator&) = default;
3137 __hostdev__ ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->tile(mPos)->value;}
3138 __hostdev__ bool isActive() const {NANOVDB_ASSERT(*this); return mParent->tile(mPos)->state;}
3139 __hostdev__ operator bool() const {return mPos < mSize;}
3140 __hostdev__ uint32_t pos() const {return mPos;}
3141 __hostdev__ CoordType getOrigin() const { NANOVDB_ASSERT(*this); mParent->tile(mPos)->origin();}
3142 __hostdev__ ValueIterator& operator++() {
3143 NANOVDB_ASSERT(mParent);
3144 ++mPos;
3145 while (mPos < mSize && mParent->tile(mPos)->isChild()) ++mPos;
3146 return *this;
3147 }
3148 __hostdev__ ValueIterator operator++(int) {
3149 auto tmp = *this;
3150 ++(*this);
3151 return tmp;
3152 }
3153 }; // Member class ValueIterator
3154
3155 ValueIterator beginValue() const {return ValueIterator(this);}
3156
3157 class ValueOnIterator
3158 {
3159 const DataType *mParent;
3160 uint32_t mPos, mSize;
3161 public:
3162 __hostdev__ ValueOnIterator() : mParent(nullptr), mPos(0), mSize(0) {}
3163 __hostdev__ ValueOnIterator(const RootNode *parent) : mParent(parent->data()), mPos(0), mSize(parent->tileCount()){
3164 NANOVDB_ASSERT(mParent);
3165 while (mPos < mSize && !mParent->tile(mPos)->isActive()) ++mPos;
3166 }
3167 ValueOnIterator& operator=(const ValueOnIterator&) = default;
3168 __hostdev__ ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->tile(mPos)->value;}
3169 __hostdev__ operator bool() const {return mPos < mSize;}
3170 __hostdev__ uint32_t pos() const {return mPos;}
3171 __hostdev__ CoordType getOrigin() const { NANOVDB_ASSERT(*this); mParent->tile(mPos)->origin();}
3172 __hostdev__ ValueOnIterator& operator++() {
3173 NANOVDB_ASSERT(mParent);
3174 ++mPos;
3175 while (mPos < mSize && !mParent->tile(mPos)->isActive()) ++mPos;
3176 return *this;
3177 }
3178 __hostdev__ ValueOnIterator operator++(int) {
3179 auto tmp = *this;
3180 ++(*this);
3181 return tmp;
3182 }
3183 }; // Member class ValueOnIterator
3184
3185 ValueOnIterator beginValueOn() const {return ValueOnIterator(this);}
3186
3187 /// @brief This class cannot be constructed or deleted
3188 RootNode() = delete;
3189 RootNode(const RootNode&) = delete;
3190 RootNode& operator=(const RootNode&) = delete;
3191 ~RootNode() = delete;
3192
3193 __hostdev__ AccessorType getAccessor() const { return AccessorType(*this); }
3194
3195 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
3196
3197 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
3198
3199 /// @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
3200 __hostdev__ const BBoxType& bbox() const { return DataType::mBBox; }
3201
3202 /// @brief Return the total number of active voxels in the root and all its child nodes.
3203
3204 /// @brief Return a const reference to the background value, i.e. the value associated with
3205 /// any coordinate location that has not been set explicitly.
3206 __hostdev__ const ValueType& background() const { return DataType::mBackground; }
3207
3208 /// @brief Return the number of tiles encoded in this root node
3209 __hostdev__ const uint32_t& tileCount() const { return DataType::mTableSize; }
3210
3211 /// @brief Return a const reference to the minimum active value encoded in this root node and any of its child nodes
3212 __hostdev__ const ValueType& minimum() const { return this->getMin(); }
3213
3214 /// @brief Return a const reference to the maximum active value encoded in this root node and any of its child nodes
3215 __hostdev__ const ValueType& maximum() const { return this->getMax(); }
3216
3217 /// @brief Return a const reference to the average of all the active values encoded in this root node and any of its child nodes
3218 __hostdev__ const FloatType& average() const { return DataType::mAverage; }
3219
3220 /// @brief Return the variance of all the active values encoded in this root node and any of its child nodes
3221 __hostdev__ FloatType variance() const { return DataType::mStdDevi * DataType::mStdDevi; }
3222
3223 /// @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
3224 __hostdev__ const FloatType& stdDeviation() const { return DataType::mStdDevi; }
3225
3226 /// @brief Return the expected memory footprint in bytes with the specified number of tiles
3227 __hostdev__ static uint64_t memUsage(uint32_t tableSize) { return sizeof(RootNode) + tableSize * sizeof(Tile); }
3228
3229 /// @brief Return the actual memory footprint of this root node
3230 __hostdev__ uint64_t memUsage() const { return sizeof(RootNode) + DataType::mTableSize * sizeof(Tile); }
3231
3232 /// @brief Return the value of the given voxel
3233 __hostdev__ ValueType getValue(const CoordType& ijk) const
3234 {
3235 if (const Tile* tile = this->probeTile(ijk)) {
3236 return tile->isChild() ? this->getChild(tile)->getValue(ijk) : tile->value;
3237 }
3238 return DataType::mBackground;
3239 }
3240
3241 __hostdev__ bool isActive(const CoordType& ijk) const
3242 {
3243 if (const Tile* tile = this->probeTile(ijk)) {
3244 return tile->isChild() ? this->getChild(tile)->isActive(ijk) : tile->state;
3245 }
3246 return false;
3247 }
3248
3249 /// @brief Return true if this RootNode is empty, i.e. contains no values or nodes
3250 __hostdev__ bool isEmpty() const { return DataType::mTableSize == uint32_t(0); }
3251
3252 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const
3253 {
3254 if (const Tile* tile = this->probeTile(ijk)) {
3255 if (tile->isChild()) {
3256 const auto *child = this->getChild(tile);
3257 return child->probeValue(ijk, v);
3258 }
3259 v = tile->value;
3260 return tile->state;
3261 }
3262 v = DataType::mBackground;
3263 return false;
3264 }
3265
3266 __hostdev__ const LeafNodeType* probeLeaf(const CoordType& ijk) const
3267 {
3268 const Tile* tile = this->probeTile(ijk);
3269 if (tile && tile->isChild()) {
3270 const auto *child = this->getChild(tile);
3271 return child->probeLeaf(ijk);
3272 }
3273 return nullptr;
3274 }
3275
3276 __hostdev__ const ChildNodeType* probeChild(const CoordType& ijk) const
3277 {
3278 const Tile* tile = this->probeTile(ijk);
3279 if (tile && tile->isChild()) {
3280 return this->getChild(tile);
3281 }
3282 return nullptr;
3283 }
3284
3285 /// @brief Find and return a Tile of this root node
3286 __hostdev__ const Tile* probeTile(const CoordType& ijk) const
3287 {
3288 const Tile* tiles = reinterpret_cast<const Tile*>(this + 1);
3289 const auto key = DataType::CoordToKey(ijk);
3290#if 1 // switch between linear and binary seach
3291 for (uint32_t i = 0; i < DataType::mTableSize; ++i) {
3292 if (tiles[i].key == key) return &tiles[i];
3293 }
3294#else// do not enable binary search if tiles are not guaranteed to be sorted!!!!!!
3295 // binary-search of pre-sorted elements
3296 int32_t low = 0, high = DataType::mTableSize; // low is inclusive and high is exclusive
3297 while (low != high) {
3298 int mid = low + ((high - low) >> 1);
3299 const Tile* tile = &tiles[mid];
3300 if (tile->key == key) {
3301 return tile;
3302 } else if (tile->key < key) {
3303 low = mid + 1;
3304 } else {
3305 high = mid;
3306 }
3307 }
3308#endif
3309 return nullptr;
3310 }
3311
3312private:
3313 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(RootData) is misaligned");
3314 static_assert(sizeof(typename DataType::Tile) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(RootData::Tile) is misaligned");
3315
3316 template<typename, int, int, int>
3317 friend class ReadAccessor;
3318
3319 template<typename>
3320 friend class Tree;
3321
3322 /// @brief Private method to return node information and update a ReadAccessor
3323 template<typename AccT>
3324 __hostdev__ typename AccT::NodeInfo getNodeInfoAndCache(const CoordType& ijk, const AccT& acc) const
3325 {
3326 using NodeInfoT = typename AccT::NodeInfo;
3327 if (const Tile* tile = this->probeTile(ijk)) {
3328 if (tile->isChild()) {
3329 const auto *child = this->getChild(tile);
3330 acc.insert(ijk, child);
3331 return child->getNodeInfoAndCache(ijk, acc);
3332 }
3333 return NodeInfoT{LEVEL, ChildT::dim(), tile->value, tile->value, tile->value,
3334 0, tile->origin(), tile->origin() + CoordType(ChildT::DIM)};
3335 }
3336 return NodeInfoT{LEVEL, ChildT::dim(), this->minimum(), this->maximum(),
3337 this->average(), this->stdDeviation(), this->bbox()[0], this->bbox()[1]};
3338 }
3339
3340 /// @brief Private method to return a voxel value and update a ReadAccessor
3341 template<typename AccT>
3342 __hostdev__ ValueType getValueAndCache(const CoordType& ijk, const AccT& acc) const
3343 {
3344 if (const Tile* tile = this->probeTile(ijk)) {
3345 if (tile->isChild()) {
3346 const auto *child = this->getChild(tile);
3347 acc.insert(ijk, child);
3348 return child->getValueAndCache(ijk, acc);
3349 }
3350 return tile->value;
3351 }
3352 return DataType::mBackground;
3353 }
3354
3355 template<typename AccT>
3356 __hostdev__ bool isActiveAndCache(const CoordType& ijk, const AccT& acc) const
3357 {
3358 const Tile* tile = this->probeTile(ijk);
3359 if (tile && tile->isChild()) {
3360 const auto *child = this->getChild(tile);
3361 acc.insert(ijk, child);
3362 return child->isActiveAndCache(ijk, acc);
3363 }
3364 return false;
3365 }
3366
3367 template<typename AccT>
3368 __hostdev__ bool probeValueAndCache(const CoordType& ijk, ValueType& v, const AccT& acc) const
3369 {
3370 if (const Tile* tile = this->probeTile(ijk)) {
3371 if (tile->isChild()) {
3372 const auto *child = this->getChild(tile);
3373 acc.insert(ijk, child);
3374 return child->probeValueAndCache(ijk, v, acc);
3375 }
3376 v = tile->value;
3377 return tile->state;
3378 }
3379 v = DataType::mBackground;
3380 return false;
3381 }
3382
3383 template<typename AccT>
3384 __hostdev__ const LeafNodeType* probeLeafAndCache(const CoordType& ijk, const AccT& acc) const
3385 {
3386 const Tile* tile = this->probeTile(ijk);
3387 if (tile && tile->isChild()) {
3388 const auto *child = this->getChild(tile);
3389 acc.insert(ijk, child);
3390 return child->probeLeafAndCache(ijk, acc);
3391 }
3392 return nullptr;
3393 }
3394
3395 template<typename RayT, typename AccT>
3396 __hostdev__ uint32_t getDimAndCache(const CoordType& ijk, const RayT& ray, const AccT& acc) const
3397 {
3398 if (const Tile* tile = this->probeTile(ijk)) {
3399 if (tile->isChild()) {
3400 const auto *child = this->getChild(tile);
3401 acc.insert(ijk, child);
3402 return child->getDimAndCache(ijk, ray, acc);
3403 }
3404 return 1 << ChildT::TOTAL; //tile value
3405 }
3406 return ChildNodeType::dim(); // background
3407 }
3408
3409}; // RootNode class
3410
3411// After the RootNode the memory layout is assumed to be the sorted Tiles
3412
3413// --------------------------> InternalNode <------------------------------------
3414
3415/// @brief Struct with all the member data of the InternalNode (useful during serialization of an openvdb InternalNode)
3416///
3417/// @note No client code should (or can) interface with this struct so it can safely be ignored!
3418template<typename ChildT, uint32_t LOG2DIM>
3419 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) InternalData
3420{
3421 using ValueT = typename ChildT::ValueType;
3422 using BuildT = typename ChildT::BuildType;// in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
3423 using StatsT = typename ChildT::FloatType;
3424 using CoordT = typename ChildT::CoordType;
3425 using MaskT = typename ChildT::template MaskType<LOG2DIM>;
3426 static constexpr bool FIXED_SIZE = true;
3427
3428 union Tile
3429 {
3430 ValueT value;
3431 int64_t child;//signed 64 bit byte offset relative to the InternalData!!
3432 /// @brief This class cannot be constructed or deleted
3433 Tile() = delete;
3434 Tile(const Tile&) = delete;
3435 Tile& operator=(const Tile&) = delete;
3436 ~Tile() = delete;
3437 };
3438
3439 BBox<CoordT> mBBox; // 24B. node bounding box. |
3440 uint64_t mFlags; // 8B. node flags. | 32B aligned
3441 MaskT mValueMask; // LOG2DIM(5): 4096B, LOG2DIM(4): 512B | 32B aligned
3442 MaskT mChildMask; // LOG2DIM(5): 4096B, LOG2DIM(4): 512B | 32B aligned
3443
3444 ValueT mMinimum; // typically 4B
3445 ValueT mMaximum; // typically 4B
3446 StatsT mAverage; // typically 4B, average of all the active values in this node and its child nodes
3447 StatsT mStdDevi; // typically 4B, standard deviation of all the active values in this node and its child nodes
3448 // possible padding, e.g. 28 byte padding when ValueType = bool
3449
3450 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
3451 ///
3452 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
3453 __hostdev__ static constexpr uint32_t padding() {
3454 return sizeof(InternalData) - (24u + 8u + 2*(sizeof(MaskT) + sizeof(ValueT) + sizeof(StatsT))
3455 + (1u << (3 * LOG2DIM))*(sizeof(ValueT) > 8u ? sizeof(ValueT) : 8u));
3456 }
3457 alignas(32) Tile mTable[1u << (3 * LOG2DIM)]; // sizeof(ValueT) x (16*16*16 or 32*32*32)
3458
3459 __hostdev__ static uint64_t memUsage() { return sizeof(InternalData); }
3460
3461 __hostdev__ void setChild(uint32_t n, const void *ptr)
3462 {
3463 NANOVDB_ASSERT(mChildMask.isOn(n));
3464 mTable[n].child = PtrDiff(ptr, this);
3465 }
3466
3467 template <typename ValueT>
3468 __hostdev__ void setValue(uint32_t n, const ValueT &v)
3469 {
3470 NANOVDB_ASSERT(!mChildMask.isOn(n));
3471 mTable[n].value = v;
3472 }
3473
3474 /// @brief Returns a pointer to the child node at the specifed linear offset.
3475 __hostdev__ ChildT* getChild(uint32_t n)
3476 {
3477 NANOVDB_ASSERT(mChildMask.isOn(n));
3478 return PtrAdd<ChildT>(this, mTable[n].child);
3479 }
3480 __hostdev__ const ChildT* getChild(uint32_t n) const
3481 {
3482 NANOVDB_ASSERT(mChildMask.isOn(n));
3483 return PtrAdd<ChildT>(this, mTable[n].child);
3484 }
3485
3486 __hostdev__ ValueT getValue(uint32_t n) const
3487 {
3488 NANOVDB_ASSERT(!mChildMask.isOn(n));
3489 return mTable[n].value;
3490 }
3491
3492 __hostdev__ bool isActive(uint32_t n) const
3493 {
3494 NANOVDB_ASSERT(!mChildMask.isOn(n));
3495 return mValueMask.isOn(n);
3496 }
3497
3498 __hostdev__ bool isChild(uint32_t n) const {return mChildMask.isOn(n);}
3499
3500 template <typename T>
3501 __hostdev__ void setOrigin(const T& ijk) { mBBox[0] = ijk; }
3502
3503 __hostdev__ const ValueT& getMin() const { return mMinimum; }
3504 __hostdev__ const ValueT& getMax() const { return mMaximum; }
3505 __hostdev__ const StatsT& average() const { return mAverage; }
3506 __hostdev__ const StatsT& stdDeviation() const { return mStdDevi; }
3507
3508 __hostdev__ void setMin(const ValueT& v) { mMinimum = v; }
3509 __hostdev__ void setMax(const ValueT& v) { mMaximum = v; }
3510 __hostdev__ void setAvg(const StatsT& v) { mAverage = v; }
3511 __hostdev__ void setDev(const StatsT& v) { mStdDevi = v; }
3512
3513 /// @brief This class cannot be constructed or deleted
3514 InternalData() = delete;
3515 InternalData(const InternalData&) = delete;
3516 InternalData& operator=(const InternalData&) = delete;
3517 ~InternalData() = delete;
3518}; // InternalData
3519
3520/// @brief Internal nodes of a VDB treedim(),
3521template<typename ChildT, uint32_t Log2Dim = ChildT::LOG2DIM + 1>
3522 class InternalNode : private InternalData<ChildT, Log2Dim>
3523{
3524public:
3525 using DataType = InternalData<ChildT, Log2Dim>;
3526 using ValueType = typename DataType::ValueT;
3527 using FloatType = typename DataType::StatsT;
3528 using BuildType = typename DataType::BuildT; // in rare cases BuildType != ValueType, e.g. then BuildType = ValueMask and ValueType = bool
3529 using LeafNodeType = typename ChildT::LeafNodeType;
3530 using ChildNodeType = ChildT;
3531 using CoordType = typename ChildT::CoordType;
3532 static constexpr bool FIXED_SIZE = DataType::FIXED_SIZE;
3533 template<uint32_t LOG2>
3534 using MaskType = typename ChildT::template MaskType<LOG2>;
3535 template<bool On>
3536 using MaskIterT = typename Mask<Log2Dim>::template Iterator<On>;
3537
3538 static constexpr uint32_t LOG2DIM = Log2Dim;
3539 static constexpr uint32_t TOTAL = LOG2DIM + ChildT::TOTAL; // dimension in index space
3540 static constexpr uint32_t DIM = 1u << TOTAL; // number of voxels along each axis of this node
3541 static constexpr uint32_t SIZE = 1u << (3 * LOG2DIM); // number of tile values (or child pointers)
3542 static constexpr uint32_t MASK = (1u << TOTAL) - 1u;
3543 static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
3544 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
3545
3546 /// @brief Visits child nodes of this node only
3547 class ChildIterator : public MaskIterT<true>
3548 {
3549 using BaseT = MaskIterT<true>;
3550 const DataType *mParent;
3551 public:
3552 __hostdev__ ChildIterator() : BaseT(), mParent(nullptr) {}
3553 __hostdev__ ChildIterator(const InternalNode* parent) : BaseT(parent->data()->mChildMask.beginOn()), mParent(parent->data()) {}
3554 ChildIterator& operator=(const ChildIterator&) = default;
3555 __hostdev__ const ChildT& operator*() const {NANOVDB_ASSERT(*this); return *mParent->getChild(BaseT::pos());}
3556 __hostdev__ const ChildT* operator->() const {NANOVDB_ASSERT(*this); return mParent->getChild(BaseT::pos());}
3557 __hostdev__ CoordType getOrigin() const { NANOVDB_ASSERT(*this); return (*this)->origin();}
3558 }; // Member class ChildIterator
3559
3560 ChildIterator beginChild() const {return ChildIterator(this);}
3561
3562 /// @brief Visits all tile values in this node, i.e. both inactive and active tiles
3563 class ValueIterator : public MaskIterT<false>
3564 {
3565 using BaseT = MaskIterT<false>;
3566 const InternalNode *mParent;
3567 public:
3568 __hostdev__ ValueIterator() : BaseT(), mParent(nullptr) {}
3569 __hostdev__ ValueIterator(const InternalNode* parent) : BaseT(parent->data()->mChildMask.beginOff()), mParent(parent) {}
3570 ValueIterator& operator=(const ValueIterator&) = default;
3571 __hostdev__ ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->data()->getValue(BaseT::pos());}
3572 __hostdev__ CoordType getOrigin() const { NANOVDB_ASSERT(*this); return mParent->localToGlobalCoord(BaseT::pos());}
3573 __hostdev__ bool isActive() const { NANOVDB_ASSERT(*this); return mParent->data()->isActive(BaseT::mPos);}
3574 }; // Member class ValueIterator
3575
3576 ValueIterator beginValue() const {return ValueIterator(this);}
3577
3578 /// @brief Visits active tile values of this node only
3579 class ValueOnIterator : public MaskIterT<true>
3580 {
3581 using BaseT = MaskIterT<true>;
3582 const InternalNode *mParent;
3583 public:
3584 __hostdev__ ValueOnIterator() : BaseT(), mParent(nullptr) {}
3585 __hostdev__ ValueOnIterator(const InternalNode* parent) : BaseT(parent->data()->mValueMask.beginOn()), mParent(parent) {}
3586 ValueOnIterator& operator=(const ValueOnIterator&) = default;
3587 __hostdev__ ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->data()->getValue(BaseT::pos());}
3588 __hostdev__ CoordType getOrigin() const { NANOVDB_ASSERT(*this); return mParent->localToGlobalCoord(BaseT::pos());}
3589 }; // Member class ValueOnIterator
3590
3591 ValueOnIterator beginValueOn() const {return ValueOnIterator(this);}
3592
3593 /// @brief This class cannot be constructed or deleted
3594 InternalNode() = delete;
3595 InternalNode(const InternalNode&) = delete;
3596 InternalNode& operator=(const InternalNode&) = delete;
3597 ~InternalNode() = delete;
3598
3599 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
3600
3601 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
3602
3603 /// @brief Return the dimension, in voxel units, of this internal node (typically 8*16 or 8*16*32)
3604 __hostdev__ static uint32_t dim() { return 1u << TOTAL; }
3605
3606 /// @brief Return memory usage in bytes for the class
3607 __hostdev__ static size_t memUsage() { return DataType::memUsage(); }
3608
3609 /// @brief Return a const reference to the bit mask of active voxels in this internal node
3610 __hostdev__ const MaskType<LOG2DIM>& valueMask() const { return DataType::mValueMask; }
3611
3612 /// @brief Return a const reference to the bit mask of child nodes in this internal node
3613 __hostdev__ const MaskType<LOG2DIM>& childMask() const { return DataType::mChildMask; }
3614
3615 /// @brief Return the origin in index space of this leaf node
3616 __hostdev__ CoordType origin() const { return DataType::mBBox.min() & ~MASK; }
3617
3618 /// @brief Return a const reference to the minimum active value encoded in this internal node and any of its child nodes
3619 __hostdev__ const ValueType& minimum() const { return this->getMin(); }
3620
3621 /// @brief Return a const reference to the maximum active value encoded in this internal node and any of its child nodes
3622 __hostdev__ const ValueType& maximum() const { return this->getMax(); }
3623
3624 /// @brief Return a const reference to the average of all the active values encoded in this internal node and any of its child nodes
3625 __hostdev__ const FloatType& average() const { return DataType::mAverage; }
3626
3627 /// @brief Return the variance of all the active values encoded in this internal node and any of its child nodes
3628 __hostdev__ FloatType variance() const { return DataType::mStdDevi*DataType::mStdDevi; }
3629
3630 /// @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
3631 __hostdev__ const FloatType& stdDeviation() const { return DataType::mStdDevi; }
3632
3633 /// @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
3634 __hostdev__ const BBox<CoordType>& bbox() const { return DataType::mBBox; }
3635
3636 /// @brief Return the value of the given voxel
3637 __hostdev__ ValueType getValue(const CoordType& ijk) const
3638 {
3639 const uint32_t n = CoordToOffset(ijk);
3640 return DataType::mChildMask.isOn(n) ? this->getChild(n)->getValue(ijk) : DataType::getValue(n);
3641 }
3642
3643 __hostdev__ bool isActive(const CoordType& ijk) const
3644 {
3645 const uint32_t n = CoordToOffset(ijk);
3646 return DataType::mChildMask.isOn(n) ? this->getChild(n)->isActive(ijk) : DataType::isActive(n);
3647 }
3648
3649 /// @brief return the state and updates the value of the specified voxel
3650 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const
3651 {
3652 const uint32_t n = CoordToOffset(ijk);
3653 if (DataType::mChildMask.isOn(n))
3654 return this->getChild(n)->probeValue(ijk, v);
3655 v = DataType::getValue(n);
3656 return DataType::isActive(n);
3657 }
3658
3659 __hostdev__ const LeafNodeType* probeLeaf(const CoordType& ijk) const
3660 {
3661 const uint32_t n = CoordToOffset(ijk);
3662 if (DataType::mChildMask.isOn(n))
3663 return this->getChild(n)->probeLeaf(ijk);
3664 return nullptr;
3665 }
3666
3667 __hostdev__ const ChildNodeType* probeChild(const CoordType& ijk) const
3668 {
3669 const uint32_t n = CoordToOffset(ijk);
3670 return DataType::mChildMask.isOn(n) ? this->getChild(n) : nullptr;
3671 }
3672
3673 /// @brief Return the linear offset corresponding to the given coordinate
3674 __hostdev__ static uint32_t CoordToOffset(const CoordType& ijk)
3675 {
3676#if 0
3677 return (((ijk[0] & MASK) >> ChildT::TOTAL) << (2 * LOG2DIM)) +
3678 (((ijk[1] & MASK) >> ChildT::TOTAL) << (LOG2DIM)) +
3679 ((ijk[2] & MASK) >> ChildT::TOTAL);
3680#else
3681 return (((ijk[0] & MASK) >> ChildT::TOTAL) << (2 * LOG2DIM)) |
3682 (((ijk[1] & MASK) >> ChildT::TOTAL) << (LOG2DIM)) |
3683 ((ijk[2] & MASK) >> ChildT::TOTAL);
3684#endif
3685 }
3686
3687 /// @return the local coordinate of the n'th tile or child node
3688 __hostdev__ static Coord OffsetToLocalCoord(uint32_t n)
3689 {
3690 NANOVDB_ASSERT(n < SIZE);
3691 const uint32_t m = n & ((1 << 2 * LOG2DIM) - 1);
3692 return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & ((1 << LOG2DIM) - 1));
3693 }
3694
3695 /// @brief modifies local coordinates to global coordinates of a tile or child node
3696 __hostdev__ void localToGlobalCoord(Coord& ijk) const
3697 {
3698 ijk <<= ChildT::TOTAL;
3699 ijk += this->origin();
3700 }
3701
3702 __hostdev__ Coord offsetToGlobalCoord(uint32_t n) const
3703 {
3704 Coord ijk = InternalNode::OffsetToLocalCoord(n);
3705 this->localToGlobalCoord(ijk);
3706 return ijk;
3707 }
3708
3709 /// @brief Return true if this node or any of its child nodes contain active values
3710 __hostdev__ bool isActive() const
3711 {
3712 return DataType::mFlags & uint32_t(2);
3713 }
3714
3715private:
3716 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(InternalData) is misaligned");
3717 //static_assert(offsetof(DataType, mTable) % 32 == 0, "InternalData::mTable is misaligned");
3718
3719 template<typename, int, int, int>
3720 friend class ReadAccessor;
3721
3722 template<typename>
3723 friend class RootNode;
3724 template<typename, uint32_t>
3725 friend class InternalNode;
3726
3727 /// @brief Private read access method used by the ReadAccessor
3728 template<typename AccT>
3729 __hostdev__ ValueType getValueAndCache(const CoordType& ijk, const AccT& acc) const
3730 {
3731 const uint32_t n = CoordToOffset(ijk);
3732 if (!DataType::mChildMask.isOn(n))
3733 return DataType::getValue(n);
3734 const ChildT* child = this->getChild(n);
3735 acc.insert(ijk, child);
3736 return child->getValueAndCache(ijk, acc);
3737 }
3738
3739 template<typename AccT>
3740 __hostdev__ typename AccT::NodeInfo getNodeInfoAndCache(const CoordType& ijk, const AccT& acc) const
3741 {
3742 using NodeInfoT = typename AccT::NodeInfo;
3743 const uint32_t n = CoordToOffset(ijk);
3744 if (!DataType::mChildMask.isOn(n)) {
3745 return NodeInfoT{LEVEL, this->dim(), this->minimum(), this->maximum(), this->average(),
3746 this->stdDeviation(), this->bbox()[0], this->bbox()[1]};
3747 }
3748 const ChildT* child = this->getChild(n);
3749 acc.insert(ijk, child);
3750 return child->getNodeInfoAndCache(ijk, acc);
3751 }
3752
3753 template<typename AccT>
3754 __hostdev__ bool isActiveAndCache(const CoordType& ijk, const AccT& acc) const
3755 {
3756 const uint32_t n = CoordToOffset(ijk);
3757 if (!DataType::mChildMask.isOn(n))
3758 return DataType::isActive(n);
3759 const ChildT* child = this->getChild(n);
3760 acc.insert(ijk, child);
3761 return child->isActiveAndCache(ijk, acc);
3762 }
3763
3764 template<typename AccT>
3765 __hostdev__ bool probeValueAndCache(const CoordType& ijk, ValueType& v, const AccT& acc) const
3766 {
3767 const uint32_t n = CoordToOffset(ijk);
3768 if (!DataType::mChildMask.isOn(n)) {
3769 v = DataType::getValue(n);
3770 return DataType::isActive(n);
3771 }
3772 const ChildT* child = this->getChild(n);
3773 acc.insert(ijk, child);
3774 return child->probeValueAndCache(ijk, v, acc);
3775 }
3776
3777 template<typename AccT>
3778 __hostdev__ const LeafNodeType* probeLeafAndCache(const CoordType& ijk, const AccT& acc) const
3779 {
3780 const uint32_t n = CoordToOffset(ijk);
3781 if (!DataType::mChildMask.isOn(n))
3782 return nullptr;
3783 const ChildT* child = this->getChild(n);
3784 acc.insert(ijk, child);
3785 return child->probeLeafAndCache(ijk, acc);
3786 }
3787
3788 template<typename RayT, typename AccT>
3789 __hostdev__ uint32_t getDimAndCache(const CoordType& ijk, const RayT& ray, const AccT& acc) const
3790 {
3791 if (DataType::mFlags & uint32_t(1u)) return this->dim(); // skip this node if the 1st bit is set
3792 //if (!ray.intersects( this->bbox() )) return 1<<TOTAL;
3793
3794 const uint32_t n = CoordToOffset(ijk);
3795 if (DataType::mChildMask.isOn(n)) {
3796 const ChildT* child = this->getChild(n);
3797 acc.insert(ijk, child);
3798 return child->getDimAndCache(ijk, ray, acc);
3799 }
3800 return ChildNodeType::dim(); // tile value
3801 }
3802
3803}; // InternalNode class
3804
3805// --------------------------> LeafNode <------------------------------------
3806
3807/// @brief Stuct with all the member data of the LeafNode (useful during serialization of an openvdb LeafNode)
3808///
3809/// @note No client code should (or can) interface with this struct so it can safely be ignored!
3810template<typename ValueT, typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3811 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData
3812{
3813 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
3814 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
3815 using ValueType = ValueT;
3816 using BuildType = ValueT;
3817 using FloatType = typename FloatTraits<ValueT>::FloatType;
3818 using ArrayType = ValueT;// type used for the internal mValue array
3819 static constexpr bool FIXED_SIZE = true;
3820
3821 CoordT mBBoxMin; // 12B.
3822 uint8_t mBBoxDif[3]; // 3B.
3823 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: is sparse ValueIndex, bits5,6,7: bit-width for FpN
3824 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
3825
3826 ValueType mMinimum; // typically 4B
3827 ValueType mMaximum; // typically 4B
3828 FloatType mAverage; // typically 4B, average of all the active values in this node and its child nodes
3829 FloatType mStdDevi; // typically 4B, standard deviation of all the active values in this node and its child nodes
3830 alignas(32) ValueType mValues[1u << 3 * LOG2DIM];
3831
3832 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
3833 ///
3834 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
3835 __hostdev__ static constexpr uint32_t padding() {
3836 return sizeof(LeafData) - (12 + 3 + 1 + sizeof(MaskT<LOG2DIM>)
3837 + 2*(sizeof(ValueT) + sizeof(FloatType))
3838 + (1u << (3 * LOG2DIM))*sizeof(ValueT));
3839 }
3840 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
3841
3842 //__hostdev__ const ValueType* values() const { return mValues; }
3843 __hostdev__ ValueType getValue(uint32_t i) const { return mValues[i]; }
3844 __hostdev__ void setValueOnly(uint32_t offset, const ValueType& value) { mValues[offset] = value; }
3845 __hostdev__ void setValue(uint32_t offset, const ValueType& value)
3846 {
3847 mValueMask.setOn(offset);
3848 mValues[offset] = value;
3849 }
3850
3851 __hostdev__ ValueType getMin() const { return mMinimum; }
3852 __hostdev__ ValueType getMax() const { return mMaximum; }
3853 __hostdev__ FloatType getAvg() const { return mAverage; }
3854 __hostdev__ FloatType getDev() const { return mStdDevi; }
3855
3856 __hostdev__ void setMin(const ValueType& v) { mMinimum = v; }
3857 __hostdev__ void setMax(const ValueType& v) { mMaximum = v; }
3858 __hostdev__ void setAvg(const FloatType& v) { mAverage = v; }
3859 __hostdev__ void setDev(const FloatType& v) { mStdDevi = v; }
3860
3861 template <typename T>
3862 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
3863
3864 /// @brief This class cannot be constructed or deleted
3865 LeafData() = delete;
3866 LeafData(const LeafData&) = delete;
3867 LeafData& operator=(const LeafData&) = delete;
3868 ~LeafData() = delete;
3869}; // LeafData<ValueT>
3870
3871/// @brief Base-class for quantized float leaf nodes
3872template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3873 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafFnBase
3874{
3875 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
3876 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
3877 using ValueType = float;
3878 using FloatType = float;
3879
3880 CoordT mBBoxMin; // 12B.
3881 uint8_t mBBoxDif[3]; // 3B.
3882 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: is sparse ValueIndex, bits5,6,7: bit-width for FpN
3883 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
3884
3885 float mMinimum; // 4B - minimum of ALL values in this node
3886 float mQuantum; // = (max - min)/15 4B
3887 uint16_t mMin, mMax, mAvg, mDev;// quantized representations of statistics of active values
3888 // no padding since it's always 32B aligned
3889 __hostdev__ static uint64_t memUsage() { return sizeof(LeafFnBase); }
3890
3891 /// @brief Return padding of this class in bytes, due to aliasing and 32B alignment
3892 ///
3893 /// @note The extra bytes are not necessarily at the end, but can come from aliasing of individual data members.
3894 __hostdev__ static constexpr uint32_t padding() {
3895 return sizeof(LeafFnBase) - (12 + 3 + 1 + sizeof(MaskT<LOG2DIM>) + 2*4 + 4*2);
3896 }
3897 __hostdev__ void init(float min, float max, uint8_t bitWidth)
3898 {
3899 mMinimum = min;
3900 mQuantum = (max - min)/float((1 << bitWidth)-1);
3901 }
3902
3903 /// @brief return the quantized minimum of the active values in this node
3904 __hostdev__ float getMin() const { return mMin*mQuantum + mMinimum; }
3905
3906 /// @brief return the quantized maximum of the active values in this node
3907 __hostdev__ float getMax() const { return mMax*mQuantum + mMinimum; }
3908
3909 /// @brief return the quantized average of the active values in this node
3910 __hostdev__ float getAvg() const { return mAvg*mQuantum + mMinimum; }
3911 /// @brief return the quantized standard deviation of the active values in this node
3912
3913 /// @note 0 <= StdDev <= max-min or 0 <= StdDev/(max-min) <= 1
3914 __hostdev__ float getDev() const { return mDev*mQuantum; }
3915
3916 /// @note min <= X <= max or 0 <= (X-min)/(min-max) <= 1
3917 __hostdev__ void setMin(float min) { mMin = uint16_t((min - mMinimum)/mQuantum + 0.5f); }
3918
3919 /// @note min <= X <= max or 0 <= (X-min)/(min-max) <= 1
3920 __hostdev__ void setMax(float max) { mMax = uint16_t((max - mMinimum)/mQuantum + 0.5f); }
3921
3922 /// @note min <= avg <= max or 0 <= (avg-min)/(min-max) <= 1
3923 __hostdev__ void setAvg(float avg) { mAvg = uint16_t((avg - mMinimum)/mQuantum + 0.5f); }
3924
3925 /// @note 0 <= StdDev <= max-min or 0 <= StdDev/(max-min) <= 1
3926 __hostdev__ void setDev(float dev) { mDev = uint16_t(dev/mQuantum + 0.5f); }
3927
3928 template <typename T>
3929 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
3930};// LeafFnBase
3931
3932/// @brief Stuct with all the member data of the LeafNode (useful during serialization of an openvdb LeafNode)
3933///
3934/// @note No client code should (or can) interface with this struct so it can safely be ignored!
3935template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3936 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<Fp4, CoordT, MaskT, LOG2DIM>
3937 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
3938{
3939 using BaseT = LeafFnBase<CoordT, MaskT, LOG2DIM>;
3940 using BuildType = Fp4;
3941 using ArrayType = uint8_t;// type used for the internal mValue array
3942 static constexpr bool FIXED_SIZE = true;
3943 alignas(32) uint8_t mCode[1u << (3 * LOG2DIM - 1)];// LeafFnBase is 32B aligned and so is mCode
3944
3945 __hostdev__ static constexpr uint64_t memUsage() { return sizeof(LeafData); }
3946 __hostdev__ static constexpr uint32_t padding() {
3947 static_assert(BaseT::padding()==0, "expected no padding in LeafFnBase");
3948 return sizeof(LeafData) - sizeof(BaseT) - (1u << (3 * LOG2DIM - 1));
3949 }
3950
3951 __hostdev__ static constexpr uint8_t bitWidth() { return 4u; }
3952 __hostdev__ float getValue(uint32_t i) const
3953 {
3954#if 0
3955 const uint8_t c = mCode[i>>1];
3956 return ( (i&1) ? c >> 4 : c & uint8_t(15) )*BaseT::mQuantum + BaseT::mMinimum;
3957#else
3958 return ((mCode[i>>1] >> ((i&1)<<2)) & uint8_t(15))*BaseT::mQuantum + BaseT::mMinimum;
3959#endif
3960 }
3961
3962 /// @brief This class cannot be constructed or deleted
3963 LeafData() = delete;
3964 LeafData(const LeafData&) = delete;
3965 LeafData& operator=(const LeafData&) = delete;
3966 ~LeafData() = delete;
3967}; // LeafData<Fp4>
3968
3969template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3970 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<Fp8, CoordT, MaskT, LOG2DIM>
3971 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
3972{
3973 using BaseT = LeafFnBase<CoordT, MaskT, LOG2DIM>;
3974 using BuildType = Fp8;
3975 using ArrayType = uint8_t;// type used for the internal mValue array
3976 static constexpr bool FIXED_SIZE = true;
3977 alignas(32) uint8_t mCode[1u << 3 * LOG2DIM];
3978 __hostdev__ static constexpr int64_t memUsage() { return sizeof(LeafData); }
3979 __hostdev__ static constexpr uint32_t padding() {
3980 static_assert(BaseT::padding()==0, "expected no padding in LeafFnBase");
3981 return sizeof(LeafData) - sizeof(BaseT) - (1u << 3 * LOG2DIM);
3982 }
3983
3984 __hostdev__ static constexpr uint8_t bitWidth() { return 8u; }
3985 __hostdev__ float getValue(uint32_t i) const
3986 {
3987 return mCode[i]*BaseT::mQuantum + BaseT::mMinimum;// code * (max-min)/255 + min
3988 }
3989 /// @brief This class cannot be constructed or deleted
3990 LeafData() = delete;
3991 LeafData(const LeafData&) = delete;
3992 LeafData& operator=(const LeafData&) = delete;
3993 ~LeafData() = delete;
3994}; // LeafData<Fp8>
3995
3996template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
3997 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<Fp16, CoordT, MaskT, LOG2DIM>
3998 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
3999{
4000 using BaseT = LeafFnBase<CoordT, MaskT, LOG2DIM>;
4001 using BuildType = Fp16;
4002 using ArrayType = uint16_t;// type used for the internal mValue array
4003 static constexpr bool FIXED_SIZE = true;
4004 alignas(32) uint16_t mCode[1u << 3 * LOG2DIM];
4005
4006 __hostdev__ static constexpr uint64_t memUsage() { return sizeof(LeafData); }
4007 __hostdev__ static constexpr uint32_t padding() {
4008 static_assert(BaseT::padding()==0, "expected no padding in LeafFnBase");
4009 return sizeof(LeafData) - sizeof(BaseT) - 2*(1u << 3 * LOG2DIM);
4010 }
4011
4012 __hostdev__ static constexpr uint8_t bitWidth() { return 16u; }
4013 __hostdev__ float getValue(uint32_t i) const
4014 {
4015 return mCode[i]*BaseT::mQuantum + BaseT::mMinimum;// code * (max-min)/65535 + min
4016 }
4017
4018 /// @brief This class cannot be constructed or deleted
4019 LeafData() = delete;
4020 LeafData(const LeafData&) = delete;
4021 LeafData& operator=(const LeafData&) = delete;
4022 ~LeafData() = delete;
4023}; // LeafData<Fp16>
4024
4025template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4026 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<FpN, CoordT, MaskT, LOG2DIM>
4027 : public LeafFnBase<CoordT, MaskT, LOG2DIM>
4028{// this class has no data members, however every instance is immediately followed
4029// bitWidth*64 bytes. Since its base class is 32B aligned so are the bitWidth*64 bytes
4030 using BaseT = LeafFnBase<CoordT, MaskT, LOG2DIM>;
4031 using BuildType = FpN;
4032 static constexpr bool FIXED_SIZE = false;
4033 __hostdev__ static constexpr uint32_t padding() {
4034 static_assert(BaseT::padding()==0, "expected no padding in LeafFnBase");
4035 return 0;
4036 }
4037
4038 __hostdev__ uint8_t bitWidth() const { return 1 << (BaseT::mFlags >> 5); }// 4,8,16,32 = 2^(2,3,4,5)
4039 __hostdev__ size_t memUsage() const { return sizeof(*this) + this->bitWidth()*64; }
4040 __hostdev__ static size_t memUsage(uint32_t bitWidth) { return 96u + bitWidth*64; }
4041 __hostdev__ float getValue(uint32_t i) const
4042 {
4043#ifdef NANOVDB_FPN_BRANCHLESS// faster
4044 const int b = BaseT::mFlags >> 5;// b = 0, 1, 2, 3, 4 corresponding to 1, 2, 4, 8, 16 bits
4045#if 0// use LUT
4046 uint16_t code = reinterpret_cast<const uint16_t*>(this + 1)[i >> (4 - b)];
4047 const static uint8_t shift[5] = {15, 7, 3, 1, 0};
4048 const static uint16_t mask[5] = {1, 3, 15, 255, 65535};
4049 code >>= (i & shift[b]) << b;
4050 code &= mask[b];
4051#else// no LUT
4052 uint32_t code = reinterpret_cast<const uint32_t*>(this + 1)[i >> (5 - b)];
4053 //code >>= (i & ((16 >> b) - 1)) << b;
4054 code >>= (i & ((32 >> b) - 1)) << b;
4055 code &= (1 << (1 << b)) - 1;
4056#endif
4057#else// use branched version (slow)
4058 float code;
4059 auto *values = reinterpret_cast<const uint8_t*>(this+1);
4060 switch (BaseT::mFlags >> 5) {
4061 case 0u:// 1 bit float
4062 code = float((values[i>>3] >> (i&7) ) & uint8_t(1));
4063 break;
4064 case 1u:// 2 bits float
4065 code = float((values[i>>2] >> ((i&3)<<1)) & uint8_t(3));
4066 break;
4067 case 2u:// 4 bits float
4068 code = float((values[i>>1] >> ((i&1)<<2)) & uint8_t(15));
4069 break;
4070 case 3u:// 8 bits float
4071 code = float(values[i]);
4072 break;
4073 default:// 16 bits float
4074 code = float(reinterpret_cast<const uint16_t*>(values)[i]);
4075 }
4076#endif
4077 return float(code) * BaseT::mQuantum + BaseT::mMinimum;// code * (max-min)/UNITS + min
4078 }
4079
4080 /// @brief This class cannot be constructed or deleted
4081 LeafData() = delete;
4082 LeafData(const LeafData&) = delete;
4083 LeafData& operator=(const LeafData&) = delete;
4084 ~LeafData() = delete;
4085}; // LeafData<FpN>
4086
4087// Partial template specialization of LeafData with bool
4088template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4089 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<bool, CoordT, MaskT, LOG2DIM>
4090{
4091 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
4092 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
4093 using ValueType = bool;
4094 using BuildType = bool;
4095 using FloatType = bool;// dummy value type
4096 using ArrayType = MaskT<LOG2DIM>;// type used for the internal mValue array
4097 static constexpr bool FIXED_SIZE = true;
4098
4099 CoordT mBBoxMin; // 12B.
4100 uint8_t mBBoxDif[3]; // 3B.
4101 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: is sparse ValueIndex, bits5,6,7: bit-width for FpN
4102 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
4103 MaskT<LOG2DIM> mValues; // LOG2DIM(3): 64B.
4104 uint64_t mPadding[2];// 16B padding to 32B alignment
4105
4106 __hostdev__ static constexpr uint32_t padding() {return sizeof(LeafData) - 12u - 3u - 1u - 2*sizeof(MaskT<LOG2DIM>) - 16u;}
4107 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
4108
4109 //__hostdev__ const ValueType* values() const { return nullptr; }
4110 __hostdev__ bool getValue(uint32_t i) const { return mValues.isOn(i); }
4111 __hostdev__ bool getMin() const { return false; }// dummy
4112 __hostdev__ bool getMax() const { return false; }// dummy
4113 __hostdev__ bool getAvg() const { return false; }// dummy
4114 __hostdev__ bool getDev() const { return false; }// dummy
4115 __hostdev__ void setValue(uint32_t offset, bool v)
4116 {
4117 mValueMask.setOn(offset);
4118 mValues.set(offset, v);
4119 }
4120
4121 __hostdev__ void setMin(const bool&) {}// no-op
4122 __hostdev__ void setMax(const bool&) {}// no-op
4123 __hostdev__ void setAvg(const bool&) {}// no-op
4124 __hostdev__ void setDev(const bool&) {}// no-op
4125
4126 template <typename T>
4127 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
4128
4129 /// @brief This class cannot be constructed or deleted
4130 LeafData() = delete;
4131 LeafData(const LeafData&) = delete;
4132 LeafData& operator=(const LeafData&) = delete;
4133 ~LeafData() = delete;
4134}; // LeafData<bool>
4135
4136// Partial template specialization of LeafData with ValueMask
4137template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4138 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<ValueMask, CoordT, MaskT, LOG2DIM>
4139{
4140 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
4141 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
4142 using ValueType = bool;
4143 using BuildType = ValueMask;
4144 using FloatType = bool;// dummy value type
4145 using ArrayType = void;// type used for the internal mValue array - void means missing
4146 static constexpr bool FIXED_SIZE = true;
4147
4148 CoordT mBBoxMin; // 12B.
4149 uint8_t mBBoxDif[3]; // 3B.
4150 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: is sparse ValueIndex, bits5,6,7: bit-width for FpN
4151 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
4152 uint64_t mPadding[2];// 16B padding to 32B alignment
4153
4154 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
4155
4156 __hostdev__ static constexpr uint32_t padding() {
4157 return sizeof(LeafData) - (12u + 3u + 1u + sizeof(MaskT<LOG2DIM>) + 2*8u);
4158 }
4159
4160 //__hostdev__ const ValueType* values() const { return nullptr; }
4161 __hostdev__ bool getValue(uint32_t i) const { return mValueMask.isOn(i); }
4162 __hostdev__ bool getMin() const { return false; }// dummy
4163 __hostdev__ bool getMax() const { return false; }// dummy
4164 __hostdev__ bool getAvg() const { return false; }// dummy
4165 __hostdev__ bool getDev() const { return false; }// dummy
4166 __hostdev__ void setValue(uint32_t offset, bool)
4167 {
4168 mValueMask.setOn(offset);
4169 }
4170
4171 __hostdev__ void setMin(const ValueType&) {}// no-op
4172 __hostdev__ void setMax(const ValueType&) {}// no-op
4173 __hostdev__ void setAvg(const FloatType&) {}// no-op
4174 __hostdev__ void setDev(const FloatType&) {}// no-op
4175
4176 template <typename T>
4177 __hostdev__ void setOrigin(const T& ijk) { mBBoxMin = ijk; }
4178
4179 /// @brief This class cannot be constructed or deleted
4180 LeafData() = delete;
4181 LeafData(const LeafData&) = delete;
4182 LeafData& operator=(const LeafData&) = delete;
4183 ~LeafData() = delete;
4184}; // LeafData<ValueMask>
4185
4186// Partial template specialization of LeafData with ValueIndex
4187template<typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4188 struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) LeafData<ValueIndex, CoordT, MaskT, LOG2DIM>
4189{
4190 static_assert(sizeof(CoordT) == sizeof(Coord), "Mismatching sizeof");
4191 static_assert(sizeof(MaskT<LOG2DIM>) == sizeof(Mask<LOG2DIM>), "Mismatching sizeof");
4192 using ValueType = uint64_t;
4193 using BuildType = ValueIndex;
4194 using FloatType = uint64_t;
4195 using ArrayType = void;// type used for the internal mValue array - void means missing
4196 static constexpr bool FIXED_SIZE = true;
4197
4198 CoordT mBBoxMin; // 12B.
4199 uint8_t mBBoxDif[3]; // 3B.
4200 uint8_t mFlags; // 1B. bit0: skip render?, bit1: has bbox?, bit3: unused, bit4: is sparse ValueIndex, bits5,6,7: bit-width for FpN
4201
4202 MaskT<LOG2DIM> mValueMask; // LOG2DIM(3): 64B.
4203 uint64_t mStatsOff;// 8B offset to min/max/avg/sdv
4204 uint64_t mValueOff;// 8B offset to values
4205 // No padding since it's always 32B aligned
4206
4207 __hostdev__ static constexpr uint32_t padding() {
4208 return sizeof(LeafData) - (12u + 3u + 1u + sizeof(MaskT<LOG2DIM>) + 2*8u);
4209 }
4210
4211 __hostdev__ static uint64_t memUsage() { return sizeof(LeafData); }
4212
4213 __hostdev__ uint64_t getMin() const { NANOVDB_ASSERT(mStatsOff); return mStatsOff + 0; }
4214 __hostdev__ uint64_t getMax() const { NANOVDB_ASSERT(mStatsOff); return mStatsOff + 1; }
4215 __hostdev__ uint64_t getAvg() const { NANOVDB_ASSERT(mStatsOff); return mStatsOff + 2; }
4216 __hostdev__ uint64_t getDev() const { NANOVDB_ASSERT(mStatsOff); return mStatsOff + 3; }
4217 __hostdev__ void setValue(uint32_t offset, uint64_t)
4218 {
4219 mValueMask.setOn(offset);
4220 }
4221
4222 __hostdev__ uint64_t getValue(uint32_t i) const
4223 {
4224 if (mFlags & uint8_t(16u)) {// if 4th bit is set only active voxels are indexed
4225 return mValueMask.isOn(i) ? mValueOff + mValueMask.countOn(i) : 0;// 0 is background
4226 }
4227 return mValueOff + i;// dense array of active and inactive voxels
4228 }
4229
4230 template <typename T>
4231 __hostdev__ void setMin(const T &min, T *p) { NANOVDB_ASSERT(mStatsOff); p[mStatsOff + 0] = min; }
4232 template <typename T>
4233 __hostdev__ void setMax(const T &max, T *p) { NANOVDB_ASSERT(mStatsOff); p[mStatsOff + 1] = max; }
4234 template <typename T>
4235 __hostdev__ void setAvg(const T &avg, T *p) { NANOVDB_ASSERT(mStatsOff); p[mStatsOff + 2] = avg; }
4236 template <typename T>
4237 __hostdev__ void setDev(const T &dev, T *p) { NANOVDB_ASSERT(mStatsOff); p[mStatsOff + 3] = dev; }
4238 template <typename T>
4239 __hostdev__ void setOrigin(const T &ijk) { mBBoxMin = ijk; }
4240
4241 /// @brief This class cannot be constructed or deleted
4242 LeafData() = delete;
4243 LeafData(const LeafData&) = delete;
4244 LeafData& operator=(const LeafData&) = delete;
4245 ~LeafData() = delete;
4246}; // LeafData<ValueIndex>
4247
4248/// @brief Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
4249template<typename BuildT,
4250 typename CoordT = Coord,
4251 template<uint32_t> class MaskT = Mask,
4252 uint32_t Log2Dim = 3>
4253 class LeafNode : private LeafData<BuildT, CoordT, MaskT, Log2Dim>
4254{
4255public:
4256 struct ChildNodeType
4257 {
4258 static constexpr uint32_t TOTAL = 0;
4259 static constexpr uint32_t DIM = 1;
4260 __hostdev__ static uint32_t dim() { return 1u; }
4261 }; // Voxel
4262 using LeafNodeType = LeafNode<BuildT, CoordT, MaskT, Log2Dim>;
4263 using DataType = LeafData<BuildT, CoordT, MaskT, Log2Dim>;
4264 using ValueType = typename DataType::ValueType;
4265 using FloatType = typename DataType::FloatType;
4266 using BuildType = typename DataType::BuildType;
4267 using CoordType = CoordT;
4268 static constexpr bool FIXED_SIZE = DataType::FIXED_SIZE;
4269 template<uint32_t LOG2>
4270 using MaskType = MaskT<LOG2>;
4271 template<bool ON>
4272 using MaskIterT = typename Mask<Log2Dim>::template Iterator<ON>;
4273
4274 /// @brief Visits all active values in a leaf node
4275 class ValueOnIterator : public MaskIterT<true>
4276 {
4277 using BaseT = MaskIterT<true>;
4278 const LeafNode *mParent;
4279 public:
4280 __hostdev__ ValueOnIterator() : BaseT(), mParent(nullptr) {}
4281 __hostdev__ ValueOnIterator(const LeafNode* parent) : BaseT(parent->data()->mValueMask.beginOn()), mParent(parent) {}
4282 ValueOnIterator& operator=(const ValueOnIterator&) = default;
4283 __hostdev__ ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->getValue(BaseT::pos());}
4284 __hostdev__ CoordT getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
4285 }; // Member class ValueOnIterator
4286
4287 ValueOnIterator beginValueOn() const {return ValueOnIterator(this);}
4288
4289 /// @brief Visits all inactive values in a leaf node
4290 class ValueOffIterator : public MaskIterT<false>
4291 {
4292 using BaseT = MaskIterT<false>;
4293 const LeafNode *mParent;
4294 public:
4295 __hostdev__ ValueOffIterator() : BaseT(), mParent(nullptr) {}
4296 __hostdev__ ValueOffIterator(const LeafNode* parent) : BaseT(parent->data()->mValueMask.beginOff()), mParent(parent) {}
4297 ValueOffIterator& operator=(const ValueOffIterator&) = default;
4298 __hostdev__ ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->getValue(BaseT::pos());}
4299 __hostdev__ CoordT getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
4300 }; // Member class ValueOffIterator
4301
4302 ValueOffIterator beginValueOff() const {return ValueOffIterator(this);}
4303
4304 /// @brief Visits all values in a leaf node, i.e. both active and inactive values
4305 class ValueIterator
4306 {
4307 const LeafNode *mParent;
4308 uint32_t mPos;
4309 public:
4310 __hostdev__ ValueIterator() : mParent(nullptr), mPos(1u << 3 * Log2Dim) {}
4311 __hostdev__ ValueIterator(const LeafNode* parent) : mParent(parent), mPos(0) {NANOVDB_ASSERT(parent);}
4312 ValueIterator& operator=(const ValueIterator&) = default;
4313 __hostdev__ ValueType operator*() const { NANOVDB_ASSERT(*this); return mParent->getValue(mPos);}
4314 __hostdev__ CoordT getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(mPos);}
4315 __hostdev__ bool isActive() const { NANOVDB_ASSERT(*this); return mParent->isActive(mPos);}
4316 __hostdev__ operator bool() const {return mPos < (1u << 3 * Log2Dim);}
4317 __hostdev__ ValueIterator& operator++() {++mPos; return *this;}
4318 __hostdev__ ValueIterator operator++(int) {
4319 auto tmp = *this;
4320 ++(*this);
4321 return tmp;
4322 }
4323 }; // Member class ValueIterator
4324
4325 ValueIterator beginValue() const {return ValueIterator(this);}
4326
4327 static_assert(is_same<ValueType,typename BuildToValueMap<BuildType>::Type>::value, "Mismatching BuildType");
4328 static constexpr uint32_t LOG2DIM = Log2Dim;
4329 static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
4330 static constexpr uint32_t DIM = 1u << TOTAL; // number of voxels along each axis of this node
4331 static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
4332 static constexpr uint32_t MASK = (1u << LOG2DIM) - 1u; // mask for bit operations
4333 static constexpr uint32_t LEVEL = 0; // level 0 = leaf
4334 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
4335
4336 __hostdev__ DataType* data() { return reinterpret_cast<DataType*>(this); }
4337
4338 __hostdev__ const DataType* data() const { return reinterpret_cast<const DataType*>(this); }
4339
4340 /// @brief Return a const reference to the bit mask of active voxels in this leaf node
4341 __hostdev__ const MaskType<LOG2DIM>& valueMask() const { return DataType::mValueMask; }
4342
4343 /// @brief Return a const reference to the minimum active value encoded in this leaf node
4344 __hostdev__ ValueType minimum() const { return this->getMin(); }
4345
4346 /// @brief Return a const reference to the maximum active value encoded in this leaf node
4347 __hostdev__ ValueType maximum() const { return this->getMax(); }
4348
4349 /// @brief Return a const reference to the average of all the active values encoded in this leaf node
4350 __hostdev__ FloatType average() const { return DataType::getAvg(); }
4351
4352 /// @brief Return the variance of all the active values encoded in this leaf node
4353 __hostdev__ FloatType variance() const { return DataType::getDev()*DataType::getDev(); }
4354
4355 /// @brief Return a const reference to the standard deviation of all the active values encoded in this leaf node
4356 __hostdev__ FloatType stdDeviation() const { return DataType::getDev(); }
4357
4358 __hostdev__ uint8_t flags() const { return DataType::mFlags; }
4359
4360 /// @brief Return the origin in index space of this leaf node
4361 __hostdev__ CoordT origin() const { return DataType::mBBoxMin & ~MASK; }
4362
4363 __hostdev__ static CoordT OffsetToLocalCoord(uint32_t n)
4364 {
4365 NANOVDB_ASSERT(n < SIZE);
4366 const uint32_t m = n & ((1 << 2 * LOG2DIM) - 1);
4367 return CoordT(n >> 2 * LOG2DIM, m >> LOG2DIM, m & MASK);
4368 }
4369
4370 /// @brief Converts (in place) a local index coordinate to a global index coordinate
4371 __hostdev__ void localToGlobalCoord(Coord& ijk) const { ijk += this->origin(); }
4372
4373 __hostdev__ CoordT offsetToGlobalCoord(uint32_t n) const
4374 {
4375 return OffsetToLocalCoord(n) + this->origin();
4376 }
4377
4378 /// @brief Return the dimension, in index space, of this leaf node (typically 8 as for openvdb leaf nodes!)
4379 __hostdev__ static uint32_t dim() { return 1u << LOG2DIM; }
4380
4381 /// @brief Return the bounding box in index space of active values in this leaf node
4382 __hostdev__ BBox<CoordT> bbox() const
4383 {
4384 BBox<CoordT> bbox(DataType::mBBoxMin, DataType::mBBoxMin);
4385 if ( this->hasBBox() ) {
4386 bbox.max()[0] += DataType::mBBoxDif[0];
4387 bbox.max()[1] += DataType::mBBoxDif[1];
4388 bbox.max()[2] += DataType::mBBoxDif[2];
4389 } else {// very rare case
4390 bbox = BBox<CoordT>();// invalid
4391 }
4392 return bbox;
4393 }
4394
4395 /// @brief Return the total number of voxels (e.g. values) encoded in this leaf node
4396 __hostdev__ static uint32_t voxelCount() { return 1u << (3 * LOG2DIM); }
4397
4398 __hostdev__ static uint32_t padding() {return DataType::padding();}
4399
4400 /// @brief return memory usage in bytes for the class
4401 __hostdev__ uint64_t memUsage() { return DataType::memUsage(); }
4402
4403 /// @brief This class cannot be constructed or deleted
4404 LeafNode() = delete;
4405 LeafNode(const LeafNode&) = delete;
4406 LeafNode& operator=(const LeafNode&) = delete;
4407 ~LeafNode() = delete;
4408
4409 /// @brief Return the voxel value at the given offset.
4410 __hostdev__ ValueType getValue(uint32_t offset) const { return DataType::getValue(offset); }
4411
4412 /// @brief Return the voxel value at the given coordinate.
4413 __hostdev__ ValueType getValue(const CoordT& ijk) const { return DataType::getValue(CoordToOffset(ijk)); }
4414
4415 /// @brief Sets the value at the specified location and activate its state.
4416 ///
4417 /// @note This is safe since it does not change the topology of the tree (unlike setValue methods on the other nodes)
4418 __hostdev__ void setValue(const CoordT& ijk, const ValueType& v) { DataType::setValue(CoordToOffset(ijk), v); }
4419
4420 /// @brief Sets the value at the specified location but leaves its state unchanged.
4421 ///
4422 /// @note This is safe since it does not change the topology of the tree (unlike setValue methods on the other nodes)
4423 __hostdev__ void setValueOnly(uint32_t offset, const ValueType& v) { DataType::setValueOnly(offset, v); }
4424 __hostdev__ void setValueOnly(const CoordT& ijk, const ValueType& v) { DataType::setValueOnly(CoordToOffset(ijk), v); }
4425
4426 /// @brief Return @c true if the voxel value at the given coordinate is active.
4427 __hostdev__ bool isActive(const CoordT& ijk) const { return DataType::mValueMask.isOn(CoordToOffset(ijk)); }
4428 __hostdev__ bool isActive(uint32_t n) const { return DataType::mValueMask.isOn(n); }
4429
4430 /// @brief Return @c true if any of the voxel value are active in this leaf node.
4431 __hostdev__ bool isActive() const
4432 {
4433 //NANOVDB_ASSERT( bool(DataType::mFlags & uint8_t(2)) != DataType::mValueMask.isOff() );
4434 //return DataType::mFlags & uint8_t(2);
4435 return !DataType::mValueMask.isOff();
4436 }
4437
4438 __hostdev__ bool hasBBox() const {return DataType::mFlags & uint8_t(2);}
4439
4440 /// @brief Return @c true if the voxel value at the given coordinate is active and updates @c v with the value.
4441 __hostdev__ bool probeValue(const CoordT& ijk, ValueType& v) const
4442 {
4443 const uint32_t n = CoordToOffset(ijk);
4444 v = DataType::getValue(n);
4445 return DataType::mValueMask.isOn(n);
4446 }
4447
4448 __hostdev__ const LeafNode* probeLeaf(const CoordT&) const { return this; }
4449
4450 /// @brief Return the linear offset corresponding to the given coordinate
4451 __hostdev__ static uint32_t CoordToOffset(const CoordT& ijk)
4452 {
4453 #if 0
4454 return ((ijk[0] & MASK) << (2 * LOG2DIM)) + ((ijk[1] & MASK) << LOG2DIM) + (ijk[2] & MASK);
4455 #else
4456 return ((ijk[0] & MASK) << (2 * LOG2DIM)) | ((ijk[1] & MASK) << LOG2DIM) | (ijk[2] & MASK);
4457 #endif
4458 }
4459
4460 /// @brief Updates the local bounding box of active voxels in this node. Return true if bbox was updated.
4461 ///
4462 /// @warning It assumes that the origin and value mask have already been set.
4463 ///
4464 /// @details This method is based on few (intrinsic) bit operations and hence is relatively fast.
4465 /// However, it should only only be called of either the value mask has changed or if the
4466 /// active bounding box is still undefined. e.g. during construction of this node.
4467 __hostdev__ bool updateBBox();
4468
4469private:
4470 static_assert(sizeof(DataType) % NANOVDB_DATA_ALIGNMENT == 0, "sizeof(LeafData) is misaligned");
4471 //static_assert(offsetof(DataType, mValues) % 32 == 0, "LeafData::mValues is misaligned");
4472
4473 template<typename, int, int, int>
4474 friend class ReadAccessor;
4475
4476 template<typename>
4477 friend class RootNode;
4478 template<typename, uint32_t>
4479 friend class InternalNode;
4480
4481 /// @brief Private method to return a voxel value and update a (dummy) ReadAccessor
4482 template<typename AccT>
4483 __hostdev__ ValueType getValueAndCache(const CoordT& ijk, const AccT&) const { return this->getValue(ijk); }
4484
4485 /// @brief Return the node information.
4486 template<typename AccT>
4487 __hostdev__ typename AccT::NodeInfo getNodeInfoAndCache(const CoordType& /*ijk*/, const AccT& /*acc*/) const {
4488 using NodeInfoT = typename AccT::NodeInfo;
4489 return NodeInfoT{LEVEL, this->dim(), this->minimum(), this->maximum(),
4490 this->average(), this->stdDeviation(), this->bbox()[0], this->bbox()[1]};
4491 }
4492
4493 template<typename AccT>
4494 __hostdev__ bool isActiveAndCache(const CoordT& ijk, const AccT&) const { return this->isActive(ijk); }
4495
4496 template<typename AccT>
4497 __hostdev__ bool probeValueAndCache(const CoordT& ijk, ValueType& v, const AccT&) const { return this->probeValue(ijk, v); }
4498
4499 template<typename AccT>
4500 __hostdev__ const LeafNode* probeLeafAndCache(const CoordT&, const AccT&) const { return this; }
4501
4502 template<typename RayT, typename AccT>
4503 __hostdev__ uint32_t getDimAndCache(const CoordT&, const RayT& /*ray*/, const AccT&) const
4504 {
4505 if (DataType::mFlags & uint8_t(1u)) return this->dim(); // skip this node if the 1st bit is set
4506
4507 //if (!ray.intersects( this->bbox() )) return 1 << LOG2DIM;
4508 return ChildNodeType::dim();
4509 }
4510
4511}; // LeafNode class
4512
4513template<typename ValueT, typename CoordT, template<uint32_t> class MaskT, uint32_t LOG2DIM>
4514 __hostdev__ inline bool LeafNode<ValueT, CoordT, MaskT, LOG2DIM>::updateBBox()
4515{
4516 static_assert(LOG2DIM == 3, "LeafNode::updateBBox: only supports LOGDIM = 3!");
4517 if (DataType::mValueMask.isOff()) {
4518 DataType::mFlags &= ~uint8_t(2);// set 2nd bit off, which indicates that this nodes has no bbox
4519 return false;
4520 }
4521 auto update = [&](uint32_t min, uint32_t max, int axis) {
4522 NANOVDB_ASSERT(min <= max && max < 8);
4523 DataType::mBBoxMin[axis] = (DataType::mBBoxMin[axis] & ~MASK) + int(min);
4524 DataType::mBBoxDif[axis] = uint8_t(max - min);
4525 };
4526 uint64_t word64 = DataType::mValueMask.template getWord<uint64_t>(0);
4527 uint32_t Xmin = word64 ? 0u : 8u;
4528 uint32_t Xmax = Xmin;
4529 for (int i = 1; i < 8; ++i) { // last loop over 8 64 words
4530 if (uint64_t w = DataType::mValueMask.template getWord<uint64_t>(i)) { // skip if word has no set bits
4531 word64 |= w; // union 8 x 64 bits words into one 64 bit word
4532 if (Xmin == 8) {
4533 Xmin = i; // only set once
4534 }
4535 Xmax = i;
4536 }
4537 }
4538 NANOVDB_ASSERT(word64);
4539 update(Xmin, Xmax, 0);
4540 update(FindLowestOn(word64) >> 3, FindHighestOn(word64) >> 3, 1);
4541 const uint32_t *p = reinterpret_cast<const uint32_t*>(&word64), word32 = p[0] | p[1];
4542 const uint16_t *q = reinterpret_cast<const uint16_t*>(&word32), word16 = q[0] | q[1];
4543 const uint8_t *b = reinterpret_cast<const uint8_t* >(&word16), byte = b[0] | b[1];
4544 NANOVDB_ASSERT(byte);
4545 update(FindLowestOn(static_cast<uint32_t>(byte)), FindHighestOn(static_cast<uint32_t>(byte)), 2);
4546 DataType::mFlags |= uint8_t(2);// set 2nd bit on, which indicates that this nodes has a bbox
4547 return true;
4548} // LeafNode::updateBBox
4549
4550// --------------------------> Template specializations and traits <------------------------------------
4551
4552/// @brief Template specializations to the default configuration used in OpenVDB:
4553/// Root -> 32^3 -> 16^3 -> 8^3
4554template<typename BuildT>
4555 using NanoLeaf = LeafNode<BuildT, Coord, Mask, 3>;
4556template<typename BuildT>
4557 using NanoLower = InternalNode<NanoLeaf<BuildT>, 4>;
4558template<typename BuildT>
4559 using NanoUpper = InternalNode<NanoLower<BuildT>, 5>;
4560template<typename BuildT>
4561 using NanoRoot = RootNode<NanoUpper<BuildT>>;
4562template<typename BuildT>
4563 using NanoTree = Tree<NanoRoot<BuildT>>;
4564template<typename BuildT>
4565 using NanoGrid = Grid<NanoTree<BuildT>>;
4566
4567/// @brief Trait to map from LEVEL to node type
4568template<typename BuildT, int LEVEL>
4569 struct NanoNode;
4570
4571// Partial template specialization of above Node struct
4572template<typename BuildT>
4573 struct NanoNode<BuildT, 0>
4574{
4575 using Type = NanoLeaf<BuildT>;
4576 using type = NanoLeaf<BuildT>;
4577};
4578template<typename BuildT>
4579 struct NanoNode<BuildT, 1>
4580{
4581 using Type = NanoLower<BuildT>;
4582 using type = NanoLower<BuildT>;
4583};
4584template<typename BuildT>
4585 struct NanoNode<BuildT, 2>
4586{
4587 using Type = NanoUpper<BuildT>;
4588 using type = NanoUpper<BuildT>;
4589};
4590template<typename BuildT>
4591 struct NanoNode<BuildT, 3>
4592{
4593 using Type = NanoRoot<BuildT>;
4594 using type = NanoRoot<BuildT>;
4595};
4596
4597 using FloatTree = NanoTree<float>;
4598 using DoubleTree = NanoTree<double>;
4599 using Int32Tree = NanoTree<int32_t>;
4600 using UInt32Tree = NanoTree<uint32_t>;
4601 using Int64Tree = NanoTree<int64_t>;
4602 using Vec3fTree = NanoTree<Vec3f>;
4603 using Vec3dTree = NanoTree<Vec3d>;
4604 using Vec4fTree = NanoTree<Vec4f>;
4605 using Vec4dTree = NanoTree<Vec4d>;
4606 using Vec3ITree = NanoTree<Vec3i>;
4607 using MaskTree = NanoTree<ValueMask>;
4608 using IndexTree = NanoTree<ValueIndex>;
4609 using BoolTree = NanoTree<bool>;
4610
4611 using FloatGrid = Grid<FloatTree>;
4612 using DoubleGrid = Grid<DoubleTree>;
4613 using Int32Grid = Grid<Int32Tree>;
4614 using UInt32Grid = Grid<UInt32Tree>;
4615 using Int64Grid = Grid<Int64Tree>;
4616 using Vec3fGrid = Grid<Vec3fTree>;
4617 using Vec3dGrid = Grid<Vec3dTree>;
4618 using Vec4fGrid = Grid<Vec4fTree>;
4619 using Vec4dGrid = Grid<Vec4dTree>;
4620 using Vec3IGrid = Grid<Vec3ITree>;
4621 using MaskGrid = Grid<MaskTree>;
4622 using IndexGrid = Grid<IndexTree>;
4623 using BoolGrid = Grid<BoolTree>;
4624
4625// --------------------------> ReadAccessor <------------------------------------
4626
4627/// @brief A read-only value accessor with three levels of node caching. This allows for
4628/// inverse tree traversal during lookup, which is on average significantly faster
4629/// than calling the equivalent method on the tree (i.e. top-down traversal).
4630///
4631/// @note By virtue of the fact that a value accessor accelerates random access operations
4632/// by re-using cached access patterns, this access should be reused for multiple access
4633/// operations. In other words, never create an instance of this accessor for a single
4634/// access only. In general avoid single access operations with this accessor, and
4635/// if that is not possible call the corresponding method on the tree instead.
4636///
4637/// @warning Since this ReadAccessor internally caches raw pointers to the nodes of the tree
4638/// structure, it is not safe to copy between host and device, or even to share among
4639/// multiple threads on the same host or device. However, it is light-weight so simple
4640/// instantiate one per thread (on the host and/or device).
4641///
4642/// @details Used to accelerated random access into a VDB tree. Provides on average
4643/// O(1) random access operations by means of inverse tree traversal,
4644/// which amortizes the non-const time complexity of the root node.
4645
4646template <typename BuildT>
4647 class ReadAccessor<BuildT, -1, -1, -1>
4648{
4649 using GridT = NanoGrid<BuildT>;// grid
4650 using TreeT = NanoTree<BuildT>;// tree
4651 using RootT = NanoRoot<BuildT>; // root node
4652 using LeafT = NanoLeaf<BuildT>; // Leaf node
4653 using FloatType = typename RootT::FloatType;
4654 using CoordValueType = typename RootT::CoordType::ValueType;
4655
4656 mutable const RootT* mRoot; // 8 bytes (mutable to allow for access methods to be const)
4657public:
4658 using ValueType = typename RootT::ValueType;
4659 using CoordType = typename RootT::CoordType;
4660
4661 static const int CacheLevels = 0;
4662
4663 struct NodeInfo {
4664 uint32_t mLevel; // 4B
4665 uint32_t mDim; // 4B
4666 ValueType mMinimum; // typically 4B
4667 ValueType mMaximum; // typically 4B
4668 FloatType mAverage; // typically 4B
4669 FloatType mStdDevi; // typically 4B
4670 CoordType mBBoxMin; // 3*4B
4671 CoordType mBBoxMax; // 3*4B
4672 };
4673
4674 /// @brief Constructor from a root node
4675 __hostdev__ ReadAccessor(const RootT& root) : mRoot{&root} {}
4676
4677 /// @brief Constructor from a grid
4678 __hostdev__ ReadAccessor(const GridT& grid) : ReadAccessor(grid.tree().root()) {}
4679
4680 /// @brief Constructor from a tree
4681 __hostdev__ ReadAccessor(const TreeT& tree) : ReadAccessor(tree.root()) {}
4682
4683 /// @brief Reset this access to its initial state, i.e. with an empty cache
4684 /// @node Noop since this template specialization has no cache
4685 __hostdev__ void clear() {}
4686
4687 __hostdev__ const RootT& root() const { return *mRoot; }
4688
4689 /// @brief Defaults constructors
4690 ReadAccessor(const ReadAccessor&) = default;
4691 ~ReadAccessor() = default;
4692 ReadAccessor& operator=(const ReadAccessor&) = default;
4693
4694 __hostdev__ ValueType getValue(const CoordType& ijk) const
4695 {
4696 return mRoot->getValueAndCache(ijk, *this);
4697 }
4698 __hostdev__ ValueType operator()(const CoordType& ijk) const
4699 {
4700 return this->getValue(ijk);
4701 }
4702 __hostdev__ ValueType operator()(int i, int j, int k) const
4703 {
4704 return this->getValue(CoordType(i,j,k));
4705 }
4706
4707 __hostdev__ NodeInfo getNodeInfo(const CoordType& ijk) const
4708 {
4709 return mRoot->getNodeInfoAndCache(ijk, *this);
4710 }
4711
4712 __hostdev__ bool isActive(const CoordType& ijk) const
4713 {
4714 return mRoot->isActiveAndCache(ijk, *this);
4715 }
4716
4717 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const
4718 {
4719 return mRoot->probeValueAndCache(ijk, v, *this);
4720 }
4721
4722 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const
4723 {
4724 return mRoot->probeLeafAndCache(ijk, *this);
4725 }
4726
4727 template<typename RayT>
4728 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
4729 {
4730 return mRoot->getDimAndCache(ijk, ray, *this);
4731 }
4732
4733private:
4734 /// @brief Allow nodes to insert themselves into the cache.
4735 template<typename>
4736 friend class RootNode;
4737 template<typename, uint32_t>
4738 friend class InternalNode;
4739 template<typename, typename, template<uint32_t> class, uint32_t>
4740 friend class LeafNode;
4741
4742 /// @brief No-op
4743 template<typename NodeT>
4744 __hostdev__ void insert(const CoordType&, const NodeT*) const {}
4745}; // ReadAccessor<ValueT, -1, -1, -1> class
4746
4747/// @brief Node caching at a single tree level
4748template <typename BuildT, int LEVEL0>
4749 class ReadAccessor<BuildT, LEVEL0, -1, -1>//e.g. 0, 1, 2
4750{
4751 static_assert(LEVEL0 >= 0 && LEVEL0 <= 2, "LEVEL0 should be 0, 1, or 2");
4752
4753 using GridT = NanoGrid<BuildT>;// grid
4754 using TreeT = NanoTree<BuildT>;
4755 using RootT = NanoRoot<BuildT>; // root node
4756 using LeafT = NanoLeaf<BuildT>; // Leaf node
4757 using NodeT = typename NodeTrait<TreeT, LEVEL0>::type;
4758 using CoordT = typename RootT::CoordType;
4759 using ValueT = typename RootT::ValueType;
4760
4761 using FloatType = typename RootT::FloatType;
4762 using CoordValueType = typename RootT::CoordT::ValueType;
4763
4764 // All member data are mutable to allow for access methods to be const
4765 mutable CoordT mKey; // 3*4 = 12 bytes
4766 mutable const RootT* mRoot; // 8 bytes
4767 mutable const NodeT* mNode; // 8 bytes
4768
4769public:
4770 using ValueType = ValueT;
4771 using CoordType = CoordT;
4772
4773 static const int CacheLevels = 1;
4774
4775 using NodeInfo = typename ReadAccessor<ValueT, -1, -1, -1>::NodeInfo;
4776
4777 /// @brief Constructor from a root node
4778 __hostdev__ ReadAccessor(const RootT& root)
4779 : mKey(CoordType::max())
4780 , mRoot(&root)
4781 , mNode(nullptr)
4782 {
4783 }
4784
4785 /// @brief Constructor from a grid
4786 __hostdev__ ReadAccessor(const GridT& grid) : ReadAccessor(grid.tree().root()) {}
4787
4788 /// @brief Constructor from a tree
4789 __hostdev__ ReadAccessor(const TreeT& tree) : ReadAccessor(tree.root()) {}
4790
4791 /// @brief Reset this access to its initial state, i.e. with an empty cache
4792 __hostdev__ void clear()
4793 {
4794 mKey = CoordType::max();
4795 mNode = nullptr;
4796 }
4797
4798 __hostdev__ const RootT& root() const { return *mRoot; }
4799
4800 /// @brief Defaults constructors
4801 ReadAccessor(const ReadAccessor&) = default;
4802 ~ReadAccessor() = default;
4803 ReadAccessor& operator=(const ReadAccessor&) = default;
4804
4805 __hostdev__ bool isCached(const CoordType& ijk) const
4806 {
4807 return (ijk[0] & int32_t(~NodeT::MASK)) == mKey[0] &&
4808 (ijk[1] & int32_t(~NodeT::MASK)) == mKey[1] &&
4809 (ijk[2] & int32_t(~NodeT::MASK)) == mKey[2];
4810 }
4811
4812 __hostdev__ ValueType getValue(const CoordType& ijk) const
4813 {
4814 if (this->isCached(ijk)) {
4815 return mNode->getValueAndCache(ijk, *this);
4816 }
4817 return mRoot->getValueAndCache(ijk, *this);
4818 }
4819 __hostdev__ ValueType operator()(const CoordType& ijk) const
4820 {
4821 return this->getValue(ijk);
4822 }
4823 __hostdev__ ValueType operator()(int i, int j, int k) const
4824 {
4825 return this->getValue(CoordType(i,j,k));
4826 }
4827
4828 __hostdev__ NodeInfo getNodeInfo(const CoordType& ijk) const
4829 {
4830 if (this->isCached(ijk)) {
4831 return mNode->getNodeInfoAndCache(ijk, *this);
4832 }
4833 return mRoot->getNodeInfoAndCache(ijk, *this);
4834 }
4835
4836 __hostdev__ bool isActive(const CoordType& ijk) const
4837 {
4838 if (this->isCached(ijk)) {
4839 return mNode->isActiveAndCache(ijk, *this);
4840 }
4841 return mRoot->isActiveAndCache(ijk, *this);
4842 }
4843
4844 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const
4845 {
4846 if (this->isCached(ijk)) {
4847 return mNode->probeValueAndCache(ijk, v, *this);
4848 }
4849 return mRoot->probeValueAndCache(ijk, v, *this);
4850 }
4851
4852 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const
4853 {
4854 if (this->isCached(ijk)) {
4855 return mNode->probeLeafAndCache(ijk, *this);
4856 }
4857 return mRoot->probeLeafAndCache(ijk, *this);
4858 }
4859
4860 template<typename RayT>
4861 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
4862 {
4863 if (this->isCached(ijk)) {
4864 return mNode->getDimAndCache(ijk, ray, *this);
4865 }
4866 return mRoot->getDimAndCache(ijk, ray, *this);
4867 }
4868
4869private:
4870 /// @brief Allow nodes to insert themselves into the cache.
4871 template<typename>
4872 friend class RootNode;
4873 template<typename, uint32_t>
4874 friend class InternalNode;
4875 template<typename, typename, template<uint32_t> class, uint32_t>
4876 friend class LeafNode;
4877
4878 /// @brief Inserts a leaf node and key pair into this ReadAccessor
4879 __hostdev__ void insert(const CoordType& ijk, const NodeT* node) const
4880 {
4881 mKey = ijk & ~NodeT::MASK;
4882 mNode = node;
4883 }
4884
4885 // no-op
4886 template<typename OtherNodeT>
4887 __hostdev__ void insert(const CoordType&, const OtherNodeT*) const {}
4888
4889}; // ReadAccessor<ValueT, LEVEL0>
4890
4891template <typename BuildT, int LEVEL0, int LEVEL1>
4892 class ReadAccessor<BuildT, LEVEL0, LEVEL1, -1>//e.g. (0,1), (1,2), (0,2)
4893{
4894 static_assert(LEVEL0 >= 0 && LEVEL0 <= 2, "LEVEL0 must be 0, 1, 2");
4895 static_assert(LEVEL1 >= 0 && LEVEL1 <= 2, "LEVEL1 must be 0, 1, 2");
4896 static_assert(LEVEL0 < LEVEL1, "Level 0 must be lower than level 1");
4897 using GridT = NanoGrid<BuildT>;// grid
4898 using TreeT = NanoTree<BuildT>;
4899 using RootT = NanoRoot<BuildT>;
4900 using LeafT = NanoLeaf<BuildT>;
4901 using Node1T = typename NodeTrait<TreeT, LEVEL0>::type;
4902 using Node2T = typename NodeTrait<TreeT, LEVEL1>::type;
4903 using CoordT = typename RootT::CoordType;
4904 using ValueT = typename RootT::ValueType;
4905 using FloatType = typename RootT::FloatType;
4906 using CoordValueType = typename RootT::CoordT::ValueType;
4907
4908 // All member data are mutable to allow for access methods to be const
4909#ifdef USE_SINGLE_ACCESSOR_KEY // 44 bytes total
4910 mutable CoordT mKey; // 3*4 = 12 bytes
4911#else // 68 bytes total
4912 mutable CoordT mKeys[2]; // 2*3*4 = 24 bytes
4913#endif
4914 mutable const RootT* mRoot;
4915 mutable const Node1T* mNode1;
4916 mutable const Node2T* mNode2;
4917
4918public:
4919 using ValueType = ValueT;
4920 using CoordType = CoordT;
4921
4922 static const int CacheLevels = 2;
4923
4924 using NodeInfo = typename ReadAccessor<ValueT,-1,-1,-1>::NodeInfo;
4925
4926 /// @brief Constructor from a root node
4927 __hostdev__ ReadAccessor(const RootT& root)
4928#ifdef USE_SINGLE_ACCESSOR_KEY
4929 : mKey(CoordType::max())
4930#else
4931 : mKeys{CoordType::max(), CoordType::max()}
4932#endif
4933 , mRoot(&root)
4934 , mNode1(nullptr)
4935 , mNode2(nullptr)
4936 {
4937 }
4938
4939 /// @brief Constructor from a grid
4940 __hostdev__ ReadAccessor(const GridT& grid) : ReadAccessor(grid.tree().root()) {}
4941
4942 /// @brief Constructor from a tree
4943 __hostdev__ ReadAccessor(const TreeT& tree) : ReadAccessor(tree.root()) {}
4944
4945 /// @brief Reset this access to its initial state, i.e. with an empty cache
4946 __hostdev__ void clear()
4947 {
4948#ifdef USE_SINGLE_ACCESSOR_KEY
4949 mKey = CoordType::max();
4950#else
4951 mKeys[0] = mKeys[1] = CoordType::max();
4952#endif
4953 mNode1 = nullptr;
4954 mNode2 = nullptr;
4955 }
4956
4957 __hostdev__ const RootT& root() const { return *mRoot; }
4958
4959 /// @brief Defaults constructors
4960 ReadAccessor(const ReadAccessor&) = default;
4961 ~ReadAccessor() = default;
4962 ReadAccessor& operator=(const ReadAccessor&) = default;
4963
4964#ifdef USE_SINGLE_ACCESSOR_KEY
4965 __hostdev__ bool isCached1(CoordValueType dirty) const
4966 {
4967 if (!mNode1)
4968 return false;
4969 if (dirty & int32_t(~Node1T::MASK)) {
4970 mNode1 = nullptr;
4971 return false;
4972 }
4973 return true;
4974 }
4975 __hostdev__ bool isCached2(CoordValueType dirty) const
4976 {
4977 if (!mNode2)
4978 return false;
4979 if (dirty & int32_t(~Node2T::MASK)) {
4980 mNode2 = nullptr;
4981 return false;
4982 }
4983 return true;
4984 }
4985 __hostdev__ CoordValueType computeDirty(const CoordType& ijk) const
4986 {
4987 return (ijk[0] ^ mKey[0]) | (ijk[1] ^ mKey[1]) | (ijk[2] ^ mKey[2]);
4988 }
4989#else
4990 __hostdev__ bool isCached1(const CoordType& ijk) const
4991 {
4992 return (ijk[0] & int32_t(~Node1T::MASK)) == mKeys[0][0] &&
4993 (ijk[1] & int32_t(~Node1T::MASK)) == mKeys[0][1] &&
4994 (ijk[2] & int32_t(~Node1T::MASK)) == mKeys[0][2];
4995 }
4996 __hostdev__ bool isCached2(const CoordType& ijk) const
4997 {
4998 return (ijk[0] & int32_t(~Node2T::MASK)) == mKeys[1][0] &&
4999 (ijk[1] & int32_t(~Node2T::MASK)) == mKeys[1][1] &&
5000 (ijk[2] & int32_t(~Node2T::MASK)) == mKeys[1][2];
5001 }
5002#endif
5003
5004 __hostdev__ ValueType getValue(const CoordType& ijk) const
5005 {
5006#ifdef USE_SINGLE_ACCESSOR_KEY
5007 const CoordValueType dirty = this->computeDirty(ijk);
5008#else
5009 auto&& dirty = ijk;
5010#endif
5011 if (this->isCached1(dirty)) {
5012 return mNode1->getValueAndCache(ijk, *this);
5013 } else if (this->isCached2(dirty)) {
5014 return mNode2->getValueAndCache(ijk, *this);
5015 }
5016 return mRoot->getValueAndCache(ijk, *this);
5017 }
5018 __hostdev__ ValueType operator()(const CoordType& ijk) const
5019 {
5020 return this->getValue(ijk);
5021 }
5022 __hostdev__ ValueType operator()(int i, int j, int k) const
5023 {
5024 return this->getValue(CoordType(i,j,k));
5025 }
5026
5027 __hostdev__ NodeInfo getNodeInfo(const CoordType& ijk) const
5028 {
5029#ifdef USE_SINGLE_ACCESSOR_KEY
5030 const CoordValueType dirty = this->computeDirty(ijk);
5031#else
5032 auto&& dirty = ijk;
5033#endif
5034 if (this->isCached1(dirty)) {
5035 return mNode1->getNodeInfoAndCache(ijk, *this);
5036 } else if (this->isCached2(dirty)) {
5037 return mNode2->getNodeInfoAndCache(ijk, *this);
5038 }
5039 return mRoot->getNodeInfoAndCache(ijk, *this);
5040 }
5041
5042 __hostdev__ bool isActive(const CoordType& ijk) const
5043 {
5044#ifdef USE_SINGLE_ACCESSOR_KEY
5045 const CoordValueType dirty = this->computeDirty(ijk);
5046#else
5047 auto&& dirty = ijk;
5048#endif
5049 if (this->isCached1(dirty)) {
5050 return mNode1->isActiveAndCache(ijk, *this);
5051 } else if (this->isCached2(dirty)) {
5052 return mNode2->isActiveAndCache(ijk, *this);
5053 }
5054 return mRoot->isActiveAndCache(ijk, *this);
5055 }
5056
5057 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const
5058 {
5059#ifdef USE_SINGLE_ACCESSOR_KEY
5060 const CoordValueType dirty = this->computeDirty(ijk);
5061#else
5062 auto&& dirty = ijk;
5063#endif
5064 if (this->isCached1(dirty)) {
5065 return mNode1->probeValueAndCache(ijk, v, *this);
5066 } else if (this->isCached2(dirty)) {
5067 return mNode2->probeValueAndCache(ijk, v, *this);
5068 }
5069 return mRoot->probeValueAndCache(ijk, v, *this);
5070 }
5071
5072 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const
5073 {
5074#ifdef USE_SINGLE_ACCESSOR_KEY
5075 const CoordValueType dirty = this->computeDirty(ijk);
5076#else
5077 auto&& dirty = ijk;
5078#endif
5079 if (this->isCached1(dirty)) {
5080 return mNode1->probeLeafAndCache(ijk, *this);
5081 } else if (this->isCached2(dirty)) {
5082 return mNode2->probeLeafAndCache(ijk, *this);
5083 }
5084 return mRoot->probeLeafAndCache(ijk, *this);
5085 }
5086
5087 template<typename RayT>
5088 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
5089 {
5090#ifdef USE_SINGLE_ACCESSOR_KEY
5091 const CoordValueType dirty = this->computeDirty(ijk);
5092#else
5093 auto&& dirty = ijk;
5094#endif
5095 if (this->isCached1(dirty)) {
5096 return mNode1->getDimAndCache(ijk, ray, *this);
5097 } else if (this->isCached2(dirty)) {
5098 return mNode2->getDimAndCache(ijk, ray, *this);
5099 }
5100 return mRoot->getDimAndCache(ijk, ray, *this);
5101 }
5102
5103private:
5104 /// @brief Allow nodes to insert themselves into the cache.
5105 template<typename>
5106 friend class RootNode;
5107 template<typename, uint32_t>
5108 friend class InternalNode;
5109 template<typename, typename, template<uint32_t> class, uint32_t>
5110 friend class LeafNode;
5111
5112 /// @brief Inserts a leaf node and key pair into this ReadAccessor
5113 __hostdev__ void insert(const CoordType& ijk, const Node1T* node) const
5114 {
5115#ifdef USE_SINGLE_ACCESSOR_KEY
5116 mKey = ijk;
5117#else
5118 mKeys[0] = ijk & ~Node1T::MASK;
5119#endif
5120 mNode1 = node;
5121 }
5122 __hostdev__ void insert(const CoordType& ijk, const Node2T* node) const
5123 {
5124#ifdef USE_SINGLE_ACCESSOR_KEY
5125 mKey = ijk;
5126#else
5127 mKeys[1] = ijk & ~Node2T::MASK;
5128#endif
5129 mNode2 = node;
5130 }
5131 template <typename OtherNodeT>
5132 __hostdev__ void insert(const CoordType&, const OtherNodeT*) const {}
5133}; // ReadAccessor<BuildT, LEVEL0, LEVEL1>
5134
5135
5136/// @brief Node caching at all (three) tree levels
5137template <typename BuildT>
5138 class ReadAccessor<BuildT, 0, 1, 2>
5139{
5140 using GridT = NanoGrid<BuildT>;// grid
5141 using TreeT = NanoTree<BuildT>;
5142 using RootT = NanoRoot<BuildT>; // root node
5143 using NodeT2 = NanoUpper<BuildT>; // upper internal node
5144 using NodeT1 = NanoLower<BuildT>; // lower internal node
5145 using LeafT = NanoLeaf< BuildT>; // Leaf node
5146 using CoordT = typename RootT::CoordType;
5147 using ValueT = typename RootT::ValueType;
5148
5149 using FloatType = typename RootT::FloatType;
5150 using CoordValueType = typename RootT::CoordT::ValueType;
5151
5152 // All member data are mutable to allow for access methods to be const
5153#ifdef USE_SINGLE_ACCESSOR_KEY // 44 bytes total
5154 mutable CoordT mKey; // 3*4 = 12 bytes
5155#else // 68 bytes total
5156 mutable CoordT mKeys[3]; // 3*3*4 = 36 bytes
5157#endif
5158 mutable const RootT* mRoot;
5159 mutable const void* mNode[3]; // 4*8 = 32 bytes
5160
5161public:
5162 using ValueType = ValueT;
5163 using CoordType = CoordT;
5164
5165 static const int CacheLevels = 3;
5166
5167 using NodeInfo = typename ReadAccessor<ValueT, -1, -1, -1>::NodeInfo;
5168
5169 /// @brief Constructor from a root node
5170 __hostdev__ ReadAccessor(const RootT& root)
5171#ifdef USE_SINGLE_ACCESSOR_KEY
5172 : mKey(CoordType::max())
5173#else
5174 : mKeys{CoordType::max(), CoordType::max(), CoordType::max()}
5175#endif
5176 , mRoot(&root)
5177 , mNode{nullptr, nullptr, nullptr}
5178 {
5179 }
5180
5181 /// @brief Constructor from a grid
5182 __hostdev__ ReadAccessor(const GridT& grid) : ReadAccessor(grid.tree().root()) {}
5183
5184 /// @brief Constructor from a tree
5185 __hostdev__ ReadAccessor(const TreeT& tree) : ReadAccessor(tree.root()) {}
5186
5187 __hostdev__ const RootT& root() const { return *mRoot; }
5188
5189 /// @brief Defaults constructors
5190 ReadAccessor(const ReadAccessor&) = default;
5191 ~ReadAccessor() = default;
5192 ReadAccessor& operator=(const ReadAccessor&) = default;
5193
5194 /// @brief Return a const point to the cached node of the specified type
5195 ///
5196 /// @warning The return value could be NULL.
5197 template<typename NodeT>
5198 __hostdev__ const NodeT* getNode() const
5199 {
5200 using T = typename NodeTrait<TreeT, NodeT::LEVEL>::type;
5201 static_assert(is_same<T, NodeT>::value, "ReadAccessor::getNode: Invalid node type");
5202 return reinterpret_cast<const T*>(mNode[NodeT::LEVEL]);
5203 }
5204
5205 template <int LEVEL>
5206 __hostdev__ const typename NodeTrait<TreeT, LEVEL>::type* getNode() const
5207 {
5208 using T = typename NodeTrait<TreeT, LEVEL>::type;
5209 static_assert(LEVEL>=0 && LEVEL<=2, "ReadAccessor::getNode: Invalid node type");
5210 return reinterpret_cast<const T*>(mNode[LEVEL]);
5211 }
5212
5213
5214 /// @brief Reset this access to its initial state, i.e. with an empty cache
5215 __hostdev__ void clear()
5216 {
5217#ifdef USE_SINGLE_ACCESSOR_KEY
5218 mKey = CoordType::max();
5219#else
5220 mKeys[0] = mKeys[1] = mKeys[2] = CoordType::max();
5221#endif
5222 mNode[0] = mNode[1] = mNode[2] = nullptr;
5223 }
5224
5225#ifdef USE_SINGLE_ACCESSOR_KEY
5226 template<typename NodeT>
5227 __hostdev__ bool isCached(CoordValueType dirty) const
5228 {
5229 if (!mNode[NodeT::LEVEL])
5230 return false;
5231 if (dirty & int32_t(~NodeT::MASK)) {
5232 mNode[NodeT::LEVEL] = nullptr;
5233 return false;
5234 }
5235 return true;
5236 }
5237
5238 __hostdev__ CoordValueType computeDirty(const CoordType& ijk) const
5239 {
5240 return (ijk[0] ^ mKey[0]) | (ijk[1] ^ mKey[1]) | (ijk[2] ^ mKey[2]);
5241 }
5242#else
5243 template<typename NodeT>
5244 __hostdev__ bool isCached(const CoordType& ijk) const
5245 {
5246 return (ijk[0] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][0] && (ijk[1] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][1] && (ijk[2] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][2];
5247 }
5248#endif
5249
5250 __hostdev__ ValueType getValue(const CoordType& ijk) const
5251 {
5252#ifdef USE_SINGLE_ACCESSOR_KEY
5253 const CoordValueType dirty = this->computeDirty(ijk);
5254#else
5255 auto&& dirty = ijk;
5256#endif
5257 if (this->isCached<LeafT>(dirty)) {
5258 return ((LeafT*)mNode[0])->getValue(ijk);
5259 } else if (this->isCached<NodeT1>(dirty)) {
5260 return ((NodeT1*)mNode[1])->getValueAndCache(ijk, *this);
5261 } else if (this->isCached<NodeT2>(dirty)) {
5262 return ((NodeT2*)mNode[2])->getValueAndCache(ijk, *this);
5263 }
5264 return mRoot->getValueAndCache(ijk, *this);
5265 }
5266 __hostdev__ ValueType operator()(const CoordType& ijk) const
5267 {
5268 return this->getValue(ijk);
5269 }
5270 __hostdev__ ValueType operator()(int i, int j, int k) const
5271 {
5272 return this->getValue(CoordType(i,j,k));
5273 }
5274
5275 __hostdev__ NodeInfo getNodeInfo(const CoordType& ijk) const
5276 {
5277#ifdef USE_SINGLE_ACCESSOR_KEY
5278 const CoordValueType dirty = this->computeDirty(ijk);
5279#else
5280 auto&& dirty = ijk;
5281#endif
5282 if (this->isCached<LeafT>(dirty)) {
5283 return ((LeafT*)mNode[0])->getNodeInfoAndCache(ijk, *this);
5284 } else if (this->isCached<NodeT1>(dirty)) {
5285 return ((NodeT1*)mNode[1])->getNodeInfoAndCache(ijk, *this);
5286 } else if (this->isCached<NodeT2>(dirty)) {
5287 return ((NodeT2*)mNode[2])->getNodeInfoAndCache(ijk, *this);
5288 }
5289 return mRoot->getNodeInfoAndCache(ijk, *this);
5290 }
5291
5292 __hostdev__ bool isActive(const CoordType& ijk) const
5293 {
5294#ifdef USE_SINGLE_ACCESSOR_KEY
5295 const CoordValueType dirty = this->computeDirty(ijk);
5296#else
5297 auto&& dirty = ijk;
5298#endif
5299 if (this->isCached<LeafT>(dirty)) {
5300 return ((LeafT*)mNode[0])->isActive(ijk);
5301 } else if (this->isCached<NodeT1>(dirty)) {
5302 return ((NodeT1*)mNode[1])->isActiveAndCache(ijk, *this);
5303 } else if (this->isCached<NodeT2>(dirty)) {
5304 return ((NodeT2*)mNode[2])->isActiveAndCache(ijk, *this);
5305 }
5306 return mRoot->isActiveAndCache(ijk, *this);
5307 }
5308
5309 __hostdev__ bool probeValue(const CoordType& ijk, ValueType& v) const
5310 {
5311#ifdef USE_SINGLE_ACCESSOR_KEY
5312 const CoordValueType dirty = this->computeDirty(ijk);
5313#else
5314 auto&& dirty = ijk;
5315#endif
5316 if (this->isCached<LeafT>(dirty)) {
5317 return ((LeafT*)mNode[0])->probeValue(ijk, v);
5318 } else if (this->isCached<NodeT1>(dirty)) {
5319 return ((NodeT1*)mNode[1])->probeValueAndCache(ijk, v, *this);
5320 } else if (this->isCached<NodeT2>(dirty)) {
5321 return ((NodeT2*)mNode[2])->probeValueAndCache(ijk, v, *this);
5322 }
5323 return mRoot->probeValueAndCache(ijk, v, *this);
5324 }
5325
5326 __hostdev__ const LeafT* probeLeaf(const CoordType& ijk) const
5327 {
5328#ifdef USE_SINGLE_ACCESSOR_KEY
5329 const CoordValueType dirty = this->computeDirty(ijk);
5330#else
5331 auto&& dirty = ijk;
5332#endif
5333 if (this->isCached<LeafT>(dirty)) {
5334 return ((LeafT*)mNode[0]);
5335 } else if (this->isCached<NodeT1>(dirty)) {
5336 return ((NodeT1*)mNode[1])->probeLeafAndCache(ijk, *this);
5337 } else if (this->isCached<NodeT2>(dirty)) {
5338 return ((NodeT2*)mNode[2])->probeLeafAndCache(ijk, *this);
5339 }
5340 return mRoot->probeLeafAndCache(ijk, *this);
5341 }
5342
5343 template<typename RayT>
5344 __hostdev__ uint32_t getDim(const CoordType& ijk, const RayT& ray) const
5345 {
5346#ifdef USE_SINGLE_ACCESSOR_KEY
5347 const CoordValueType dirty = this->computeDirty(ijk);
5348#else
5349 auto&& dirty = ijk;
5350#endif
5351 if (this->isCached<LeafT>(dirty)) {
5352 return ((LeafT*)mNode[0])->getDimAndCache(ijk, ray, *this);
5353 } else if (this->isCached<NodeT1>(dirty)) {
5354 return ((NodeT1*)mNode[1])->getDimAndCache(ijk, ray, *this);
5355 } else if (this->isCached<NodeT2>(dirty)) {
5356 return ((NodeT2*)mNode[2])->getDimAndCache(ijk, ray, *this);
5357 }
5358 return mRoot->getDimAndCache(ijk, ray, *this);
5359 }
5360
5361private:
5362 /// @brief Allow nodes to insert themselves into the cache.
5363 template<typename>
5364 friend class RootNode;
5365 template<typename, uint32_t>
5366 friend class InternalNode;
5367 template<typename, typename, template<uint32_t> class, uint32_t>
5368 friend class LeafNode;
5369
5370 /// @brief Inserts a leaf node and key pair into this ReadAccessor
5371 template<typename NodeT>
5372 __hostdev__ void insert(const CoordType& ijk, const NodeT* node) const
5373 {
5374#ifdef USE_SINGLE_ACCESSOR_KEY
5375 mKey = ijk;
5376#else
5377 mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
5378#endif
5379 mNode[NodeT::LEVEL] = node;
5380 }
5381}; // ReadAccessor<BuildT, 0, 1, 2>
5382
5383//////////////////////////////////////////////////
5384
5385/// @brief Free-standing function for convenient creation of a ReadAccessor with
5386/// optional and customizable node caching.
5387///
5388/// @details createAccessor<>(grid): No caching of nodes and hence it's thread-safe but slow
5389/// createAccessor<0>(grid): Caching of leaf nodes only
5390/// createAccessor<1>(grid): Caching of lower internal nodes only
5391/// createAccessor<2>(grid): Caching of upper internal nodes only
5392/// createAccessor<0,1>(grid): Caching of leaf and lower internal nodes
5393/// createAccessor<0,2>(grid): Caching of leaf and upper internal nodes
5394/// createAccessor<1,2>(grid): Caching of lower and upper internal nodes
5395/// createAccessor<0,1,2>(grid): Caching of all nodes at all tree levels
5396
5397template <int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1, typename ValueT = float>
5398 ReadAccessor<ValueT, LEVEL0, LEVEL1, LEVEL2> createAccessor(const NanoGrid<ValueT> &grid)
5399{
5400 return ReadAccessor<ValueT, LEVEL0, LEVEL1, LEVEL2>(grid);
5401}
5402
5403template <int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1, typename ValueT = float>
5404 ReadAccessor<ValueT, LEVEL0, LEVEL1, LEVEL2> createAccessor(const NanoTree<ValueT> &tree)
5405{
5406 return ReadAccessor<ValueT, LEVEL0, LEVEL1, LEVEL2>(tree);
5407}
5408
5409template <int LEVEL0 = -1, int LEVEL1 = -1, int LEVEL2 = -1, typename ValueT = float>
5410 ReadAccessor<ValueT, LEVEL0, LEVEL1, LEVEL2> createAccessor(const NanoRoot<ValueT> &root)
5411{
5412 return ReadAccessor<ValueT, LEVEL0, LEVEL1, LEVEL2>(root);
5413}
5414
5415//////////////////////////////////////////////////
5416
5417/// @brief This is a convenient class that allows for access to grid meta-data
5418/// that are independent of the value type of a grid. That is, this class
5419/// can be used to get information about a grid without actually knowing
5420/// its ValueType.
5421 class GridMetaData
5422{
5423 // We cast to a grid templated on a dummy ValueType which is safe because we are very
5424 // careful only to call certain methods which are known to be invariant to the ValueType!
5425 // In other words, don't use this technique unless you are intimately familiar with the
5426 // memory-layout of the data structure and the reasons why certain methods are safe
5427 // to call and others are not!
5428 using GridT = NanoGrid<int>;
5429 __hostdev__ const GridT& grid() const { return *reinterpret_cast<const GridT*>(this); }
5430
5431public:
5432 __hostdev__ bool isValid() const { return this->grid().isValid(); }
5433 __hostdev__ uint64_t gridSize() const { return this->grid().gridSize(); }
5434 __hostdev__ uint32_t gridIndex() const { return this->grid().gridIndex(); }
5435 __hostdev__ uint32_t gridCount() const { return this->grid().gridCount(); }
5436 __hostdev__ const char* shortGridName() const { return this->grid().shortGridName(); }
5437 __hostdev__ GridType gridType() const { return this->grid().gridType(); }
5438 __hostdev__ GridClass gridClass() const { return this->grid().gridClass(); }
5439 __hostdev__ bool isLevelSet() const { return this->grid().isLevelSet(); }
5440 __hostdev__ bool isFogVolume() const { return this->grid().isFogVolume(); }
5441 __hostdev__ bool isPointIndex() const { return this->grid().isPointIndex(); }
5442 __hostdev__ bool isPointData() const { return this->grid().isPointData(); }
5443 __hostdev__ bool isMask() const { return this->grid().isMask(); }
5444 __hostdev__ bool isStaggered() const { return this->grid().isStaggered(); }
5445 __hostdev__ bool isUnknown() const { return this->grid().isUnknown(); }
5446 __hostdev__ const Map& map() const { return this->grid().map(); }
5447 __hostdev__ const BBox<Vec3R>& worldBBox() const { return this->grid().worldBBox(); }
5448 __hostdev__ const BBox<Coord>& indexBBox() const { return this->grid().indexBBox(); }
5449 __hostdev__ Vec3R voxelSize() const { return this->grid().voxelSize(); }
5450 __hostdev__ int blindDataCount() const { return this->grid().blindDataCount(); }
5451 __hostdev__ const GridBlindMetaData& blindMetaData(uint32_t n) const { return this->grid().blindMetaData(n); }
5452 __hostdev__ uint64_t activeVoxelCount() const { return this->grid().activeVoxelCount(); }
5453 __hostdev__ const uint32_t& activeTileCount(uint32_t level) const { return this->grid().tree().activeTileCount(level); }
5454 __hostdev__ uint32_t nodeCount(uint32_t level) const { return this->grid().tree().nodeCount(level); }
5455 __hostdev__ uint64_t checksum() const { return this->grid().checksum(); }
5456 __hostdev__ bool isEmpty() const { return this->grid().isEmpty(); }
5457 __hostdev__ Version version() const { return this->grid().version(); }
5458}; // GridMetaData
5459
5460/// @brief Class to access points at a specific voxel location
5461template<typename AttT>
5462 class PointAccessor : public DefaultReadAccessor<uint32_t>
5463{
5464 using AccT = DefaultReadAccessor<uint32_t>;
5465 const UInt32Grid* mGrid;
5466 const AttT* mData;
5467
5468public:
5469 using LeafNodeType = typename NanoRoot<uint32_t>::LeafNodeType;
5470
5471 PointAccessor(const UInt32Grid& grid)
5472 : AccT(grid.tree().root())
5473 , mGrid(&grid)
5474 , mData(reinterpret_cast<const AttT*>(grid.blindData(0)))
5475 {
5476 NANOVDB_ASSERT(grid.gridType() == GridType::UInt32);
5477 NANOVDB_ASSERT((grid.gridClass() == GridClass::PointIndex && is_same<uint32_t, AttT>::value) ||
5478 (grid.gridClass() == GridClass::PointData && is_same<Vec3f, AttT>::value));
5479 NANOVDB_ASSERT(grid.blindDataCount() >= 1);
5480 }
5481 /// @brief Return the total number of point in the grid and set the
5482 /// iterators to the complete range of points.
5483 __hostdev__ uint64_t gridPoints(const AttT*& begin, const AttT*& end) const
5484 {
5485 const uint64_t count = mGrid->blindMetaData(0u).mElementCount;
5486 begin = mData;
5487 end = begin + count;
5488 return count;
5489 }
5490 /// @brief Return the number of points in the leaf node containing the coordinate @a ijk.
5491 /// If this return value is larger than zero then the iterators @a begin and @a end
5492 /// will point to all the attributes contained within that leaf node.
5493 __hostdev__ uint64_t leafPoints(const Coord& ijk, const AttT*& begin, const AttT*& end) const
5494 {
5495 auto* leaf = this->probeLeaf(ijk);
5496 if (leaf == nullptr) {
5497 return 0;
5498 }
5499 begin = mData + leaf->minimum();
5500 end = begin + leaf->maximum();
5501 return leaf->maximum();
5502 }
5503
5504 /// @brief get iterators over offsets to points at a specific voxel location
5505 __hostdev__ uint64_t voxelPoints(const Coord& ijk, const AttT*& begin, const AttT*& end) const
5506 {
5507 auto* leaf = this->probeLeaf(ijk);
5508 if (leaf == nullptr)
5509 return 0;
5510 const uint32_t offset = LeafNodeType::CoordToOffset(ijk);
5511 if (leaf->isActive(offset)) {
5512 auto* p = mData + leaf->minimum();
5513 begin = p + (offset == 0 ? 0 : leaf->getValue(offset - 1));
5514 end = p + leaf->getValue(offset);
5515 return end - begin;
5516 }
5517 return 0;
5518 }
5519}; // PointAccessor
5520
5521/// @brief Class to access values in channels at a specific voxel location.
5522///
5523/// @note The ChannelT template parameter can be either const and non-const.
5524template<typename ChannelT>
5525 class ChannelAccessor : public DefaultReadAccessor<ValueIndex>
5526{
5527 using BaseT = DefaultReadAccessor<ValueIndex>;
5528 const IndexGrid &mGrid;
5529 ChannelT *mChannel;
5530
5531public:
5532 using ValueType = ChannelT;
5533 using TreeType = IndexTree;
5534 using AccessorType = ChannelAccessor<ChannelT>;
5535
5536 /// @brief Ctor from an IndexGrid and an integer ID of an internal channel
5537 /// that is assumed to exist as blind data in the IndexGrid.
5538 __hostdev__ ChannelAccessor(const IndexGrid& grid, uint32_t channelID = 0u)
5539 : BaseT(grid.tree().root())
5540 , mGrid(grid)
5541 , mChannel(nullptr)
5542 {
5543 NANOVDB_ASSERT(grid.gridType() == GridType::Index);
5544 NANOVDB_ASSERT(grid.gridClass() == GridClass::IndexGrid);
5545 this->setChannel(channelID);
5546 }
5547
5548 /// @brief Ctor from an IndexGrid and an external channel
5549 __hostdev__ ChannelAccessor(const IndexGrid& grid, ChannelT *channelPtr)
5550 : BaseT(grid.tree().root())
5551 , mGrid(grid)
5552 , mChannel(channelPtr)
5553 {
5554 NANOVDB_ASSERT(grid.gridType() == GridType::Index);
5555 NANOVDB_ASSERT(grid.gridClass() == GridClass::IndexGrid);
5556 NANOVDB_ASSERT(mChannel);
5557 }
5558
5559 /// @brief Return a const reference to the IndexGrid
5560 __hostdev__ const IndexGrid &grid() const {return mGrid;}
5561
5562 /// @brief Return a const reference to the tree of the IndexGrid
5563 __hostdev__ const IndexTree &tree() const {return mGrid.tree();}
5564
5565 /// @brief Return a vector of the axial voxel sizes
5566 __hostdev__ const Vec3R& voxelSize() const { return mGrid.voxelSize(); }
5567
5568 /// @brief Return total number of values indexed by the IndexGrid
5569 __hostdev__ const uint64_t& valueCount() const { return mGrid.valueCount(); }
5570
5571 /// @brief Change to an external channel
5572 __hostdev__ void setChannel(ChannelT *channelPtr)
5573 {
5574 mChannel = channelPtr;
5575 NANOVDB_ASSERT(mChannel);
5576 }
5577
5578 /// @brief Change to an internal channel, assuming it exists as as blind data
5579 /// in the IndexGrid.
5580 __hostdev__ void setChannel(uint32_t channelID)
5581 {
5582 this->setChannel(reinterpret_cast<ChannelT*>(const_cast<void*>(mGrid.blindData(channelID))));
5583 }
5584
5585 /// @brief Return the linear offset into a channel that maps to the specified coordinate
5586 __hostdev__ uint64_t getIndex(const Coord& ijk) const {return BaseT::getValue(ijk);}
5587 __hostdev__ uint64_t idx(int i, int j, int k) const {return BaseT::getValue(Coord(i,j,k));}
5588
5589 /// @brief Return the value from a cached channel that maps to the specified coordinate
5590 __hostdev__ ChannelT& getValue(const Coord& ijk) const {return mChannel[BaseT::getValue(ijk)];}
5591 __hostdev__ ChannelT& operator()(const Coord& ijk) const {return this->getValue(ijk);}
5592 __hostdev__ ChannelT& operator()(int i, int j, int k) const {return this->getValue(Coord(i,j,k));}
5593
5594 /// @brief return the state and updates the value of the specified voxel
5595 __hostdev__ bool probeValue(const CoordType& ijk, typename remove_const<ChannelT>::type &v) const
5596 {
5597 uint64_t idx;
5598 const bool isActive = BaseT::probeValue(ijk, idx);
5599 v = mChannel[idx];
5600 return isActive;
5601 }
5602 /// @brief Return the value from a specified channel that maps to the specified coordinate
5603 ///
5604 /// @note The template parameter can be either const or non-const
5605 template <typename T>
5606 __hostdev__ T& getValue(const Coord& ijk, T* channelPtr) const {return channelPtr[BaseT::getValue(ijk)];}
5607
5608}; // ChannelAccessor
5609
5610
5611#if !defined(__CUDA_ARCH__) && !defined(__HIP__)
5612
5613#if 0
5614// This MiniGridHandle class is only included as a stand-alone example. Note that aligned_alloc is a C++17 feature!
5615// Normally we recommend using GridHandle defined in util/GridHandle.h
5616struct MiniGridHandle {
5617 struct BufferType {
5618 uint8_t *data;
5619 uint64_t size;
5620 BufferType(uint64_t n=0) : data(std::aligned_alloc(NANOVDB_DATA_ALIGNMENT, n)), size(n) {assert(isValid(data));}
5621 BufferType(BufferType &&other) : data(other.data), size(other.size) {other.data=nullptr; other.size=0;}
5622 ~BufferType() {std::free(data);}
5623 BufferType& operator=(const BufferType &other) = delete;
5624 BufferType& operator=(BufferType &&other){data=other.data; size=other.size; other.data=nullptr; other.size=0; return *this;}
5625 static BufferType create(size_t n, BufferType* dummy = nullptr) {return BufferType(n);}
5626 } buffer;
5627 MiniGridHandle(BufferType &&buf) : buffer(std::move(buf)) {}
5628 const uint8_t* data() const {return buffer.data;}
5629};// MiniGridHandle
5630#endif
5631 namespace io {
5632
5633///
5634/// @brief This is a standalone alternative to io::writeGrid(...,Codec::NONE) defined in util/IO.h
5635/// Unlike the latter this function has no dependencies at all, not even NanoVDB.h, so it also
5636/// works if client code only includes PNanoVDB.h!
5637///
5638/// @details Writes a raw NanoVDB buffer, possibly with multiple grids, to a stream WITHOUT compression.
5639/// It follows all the conventions in util/IO.h so the stream can be read by all existing client
5640/// code of NanoVDB.
5641///
5642/// @note This method will always write uncompressed grids to the stream, i.e. Blosc or ZIP compression
5643/// is never applied! This is a fundamental limitation and feature of this standalone function.
5644///
5645/// @throw std::invalid_argument if buffer does not point to a valid NanoVDB grid.
5646///
5647/// @warning This is pretty ugly code that involves lots of pointer and bit manipulations - not for the faint of heart :)
5648template <typename StreamT>// StreamT class must support: "void write(char*, size_t)"
5649 void writeUncompressedGrid(StreamT &os, const void *buffer)
5650{
5651 char header[192] = {0}, *dst = header;// combines io::Header + io::MetaData, see util/IO.h
5652 const char *grid = (const char*)buffer, *tree = grid + 672, *root = tree + *(const uint64_t*)(tree + 24);
5653 auto cpy = [&](const char *src, int n){for (auto *end=src+n; src!=end; ++src) *dst++ = *src;};
5654 if (*(const uint64_t*)(grid)!=0x304244566f6e614eUL) {
5655 fprintf(stderr, "nanovdb::writeUncompressedGrid: invalid magic number\n"); exit(EXIT_FAILURE);
5656 } else if (*(const uint32_t*)(grid+16)>>21!=32) {
5657 fprintf(stderr, "nanovdb::writeUncompressedGrid: invalid major version\n"); exit(EXIT_FAILURE);
5658 }
5659 cpy(grid , 8);// uint64_t Header::magic
5660 cpy(grid + 16, 4);// uint32_t Heder::version
5661 *(uint16_t*)(dst) = 1; dst += 4;// uint16_t Header::gridCount=1 and uint16_t Header::codec=0
5662 cpy(grid + 32, 8);// uint64_t MetaData::gridSize
5663 cpy(grid + 32, 8);// uint64_t MetaData::fileSize
5664 dst += 8;// uint64_t MetaData::nameKey
5665 cpy(tree + 56, 8);// uint64_t MetaData::voxelCount
5666 cpy(grid + 636, 4);// uint32_t MetaData::gridType
5667 cpy(grid + 632, 4);// uint32_t MetaData::gridClass
5668 cpy(grid + 560, 48);// double[6] MetaData::worldBBox
5669 cpy(root , 24);// int[6] MetaData::indexBBox
5670 cpy(grid + 608, 24);// double[3] MetaData::voxelSize
5671 const char *gridName = grid + 40;// shortGridName
5672 if (*(const uint32_t*)(grid+20) & uint32_t(1)) {// has long grid name
5673 gridName = grid + *(const int64_t*)(grid + 640) + 288*(*(const uint32_t*)(grid + 648) - 1);
5674 gridName += *(const uint64_t*)gridName;// long grid name encoded in blind meta data
5675 }
5676 uint32_t nameSize = 1; // '\0'
5677 for (const char *p = gridName; *p!='\0'; ++p) ++nameSize;
5678 *(uint32_t*)(dst) = nameSize; dst += 4;// uint32_t MetaData::nameSize
5679 cpy(tree + 32, 12);// uint32_t[3] MetaData::nodeCount
5680 *(uint32_t*)(dst) = 1; dst += 4;// uint32_t MetaData::nodeCount[3]=1
5681 cpy(tree + 44, 12);// uint32_t[3] MetaData::tileCount
5682 dst += 4;// uint16_t codec and padding
5683 cpy(grid + 16, 4);// uint32_t MetaData::version
5684 assert(dst - header == 192);
5685 os.write(header, 192);// write header
5686 os.write(gridName, nameSize);// write grid name
5687 while(1) {// loop over all grids in the buffer (typically just one grid per buffer)
5688 const uint64_t gridSize = *(const uint64_t*)(grid + 32);
5689 os.write(grid, gridSize);// write grid <- bulk of writing!
5690 if (*(const uint32_t*)(grid+24) >= *(const uint32_t*)(grid+28) - 1) break;
5691 grid += gridSize;
5692 }
5693}// writeUncompressedGrid
5694
5695/// @brief write multiple NanoVDB grids to a single file, without compression.
5696template<typename GridHandleT, template<typename...> class VecT>
5697 void writeUncompressedGrids(const char* fileName, const VecT<GridHandleT>& handles)
5698{
5699#ifdef NANOVDB_USE_IOSTREAMS// use this to switch between std::ofstream or FILE implementations
5700 std::ofstream os(fileName, std::ios::out | std::ios::binary | std::ios::trunc);
5701#else
5702 struct StreamT {
5703 FILE *fptr;
5704 StreamT(const char *name) {fptr = fopen(name, "wb");}
5705 ~StreamT() {fclose(fptr);}
5706 void write(const char *data, size_t n){fwrite(data, 1, n, fptr);}
5707 bool is_open() const {return fptr != NULL;}
5708 } os(fileName);
5709#endif
5710 if (!os.is_open()) {
5711 fprintf(stderr, "nanovdb::writeUncompressedGrids: Unable to open file \"%s\"for output\n",fileName); exit(EXIT_FAILURE);
5712 }
5713 for (auto &handle : handles) writeUncompressedGrid(os, handle.data());
5714}// writeUncompressedGrids
5715
5716/// @brief read all uncompressed grids from a stream and return their handles.
5717///
5718/// @throw std::invalid_argument if stream does not contain a single uncompressed valid NanoVDB grid
5719///
5720/// @details StreamT class must support: "bool read(char*, size_t)" and "void skip(uint32_t)"
5721template<typename GridHandleT, typename StreamT, template<typename...> class VecT>
5722 VecT<GridHandleT> readUncompressedGrids(StreamT& is, const typename GridHandleT::BufferType& buffer = typename GridHandleT::BufferType())
5723{// header1, metadata11, grid11, metadata12, grid2 ... header2, metadata21, grid21, metadata22, grid22 ...
5724 char header[16], metadata[176];
5725 VecT<GridHandleT> handles;
5726 while(is.read(header, 16)) {// read all segments, e.g. header1, metadata11, grid11, metadata12, grid2 ...
5727 if (*(uint64_t*)(header)!=0x304244566f6e614eUL) {
5728 fprintf(stderr, "nanovdb::readUncompressedGrids: invalid magic number\n"); exit(EXIT_FAILURE);
5729 } else if (*(uint32_t*)(header+8)>>21!=32) {
5730 fprintf(stderr, "nanovdb::readUncompressedGrids: invalid major version\n"); exit(EXIT_FAILURE);
5731 } else if (*(uint16_t*)(header+14)!=0) {
5732 fprintf(stderr, "nanovdb::readUncompressedGrids: invalid codec\n"); exit(EXIT_FAILURE);
5733 }
5734 for (uint16_t i=0, e=*(uint16_t*)(header+12); i<e; ++i) {// read all grids in segment
5735 if (!is.read(metadata, 176)) {
5736 fprintf(stderr, "nanovdb::readUncompressedGrids: error reading metadata\n"); exit(EXIT_FAILURE);
5737 }
5738 const uint64_t gridSize = *(uint64_t*)(metadata);
5739 GridHandleT handle(GridHandleT::BufferType::create(gridSize, &buffer));
5740 is.skip(*(uint32_t*)(metadata + 136));// skip grid name
5741 is.read((char*)handle.data(), gridSize);
5742 handles.emplace_back(std::move(handle));
5743 }
5744 }
5745 return handles;
5746}// readUncompressedGrids
5747
5748/// @brief Read a multiple un-compressed NanoVDB grids from a file and return them as a vector.
5749template<typename GridHandleT, template<typename...> class VecT>
5750 VecT<GridHandleT> readUncompressedGrids(const char *fileName, const typename GridHandleT::BufferType& buffer = typename GridHandleT::BufferType())
5751{
5752#ifdef NANOVDB_USE_IOSTREAMS// use this to switch between std::ifstream or FILE implementations
5753 struct StreamT : public std::ifstream {
5754 StreamT(const char *name) : std::ifstream(name, std::ios::in | std::ios::binary) {}
5755 void skip(uint32_t off) {this->seekg(off, std::ios_base::cur);}
5756 };
5757#else
5758 struct StreamT {
5759 FILE *fptr;
5760 StreamT(const char *name) {fptr = fopen(name, "rb");}
5761 ~StreamT() {fclose(fptr);}
5762 bool read(char *data, size_t n){size_t m=fread(data, 1, n, fptr); return n==m;}
5763 void skip(uint32_t off){fseek(fptr, off, SEEK_CUR);}
5764 bool is_open() const {return fptr != NULL;}
5765 };
5766#endif
5767 StreamT is(fileName);
5768 if (!is.is_open()) {
5769 fprintf(stderr, "nanovdb::readUncompressedGrids: Unable to open file \"%s\"for input\n",fileName); exit(EXIT_FAILURE);
5770 }
5771 return readUncompressedGrids<GridHandleT, StreamT, VecT>(is, buffer);
5772}// readUncompressedGrids
5773
5774} // namespace io
5775
5776#endif// if !defined(__CUDA_ARCH__) && !defined(__HIP__)
5777
5778} // namespace nanovdb
5779
5780#endif // end of NANOVDB_NANOVDB_H_HAS_BEEN_INCLUDED
ROOT_LEVEL
#define ROOT_LEVEL
Definition CNanoVDB.h:53
value
ValueT value
Definition GridBuilder.h:1290
child
ChildT * child
Definition GridBuilder.h:1289
NANOVDB_HOSTDEV_DISABLE_WARNING
#define NANOVDB_HOSTDEV_DISABLE_WARNING
Definition NanoVDB.h:202
NANOVDB_MINOR_VERSION_NUMBER
#define NANOVDB_MINOR_VERSION_NUMBER
Definition NanoVDB.h:124
NANOVDB_DATA_ALIGNMENT
#define NANOVDB_DATA_ALIGNMENT
Definition NanoVDB.h:137
__hostdev__
#define __hostdev__
Definition NanoVDB.h:192
NANOVDB_MAJOR_VERSION_NUMBER
#define NANOVDB_MAJOR_VERSION_NUMBER
Definition NanoVDB.h:123
NANOVDB_ASSERT
#define NANOVDB_ASSERT(x)
Definition NanoVDB.h:173
NANOVDB_MAGIC_NUMBER
#define NANOVDB_MAGIC_NUMBER
Definition NanoVDB.h:121
NANOVDB_PATCH_VERSION_NUMBER
#define NANOVDB_PATCH_VERSION_NUMBER
Definition NanoVDB.h:125
nanovdb::BBox< CoordT, false >::Iterator::operator*
const CoordT & operator*() const
Definition NanoVDB.h:1747
nanovdb::BBox< CoordT, false >::Iterator::Iterator
Iterator(const BBox &b)
Definition NanoVDB.h:1720
nanovdb::BBox< CoordT, false >::Iterator::operator++
Iterator operator++(int)
Definition NanoVDB.h:1739
nanovdb::BBox< CoordT, false >::Iterator::operator++
Iterator & operator++()
Definition NanoVDB.h:1725
nanovdb::ChannelAccessor
Class to access values in channels at a specific voxel location.
Definition NanoVDB.h:5526
nanovdb::ChannelAccessor::getValue
T & getValue(const Coord &ijk, T *channelPtr) const
Return the value from a specified channel that maps to the specified coordinate.
Definition NanoVDB.h:5606
nanovdb::ChannelAccessor::getIndex
uint64_t getIndex(const Coord &ijk) const
Return the linear offset into a channel that maps to the specified coordinate.
Definition NanoVDB.h:5586
nanovdb::ChannelAccessor::grid
const IndexGrid & grid() const
Return a const reference to the IndexGrid.
Definition NanoVDB.h:5560
nanovdb::ChannelAccessor::valueCount
const uint64_t & valueCount() const
Return total number of values indexed by the IndexGrid.
Definition NanoVDB.h:5569
nanovdb::ChannelAccessor::voxelSize
const Vec3R & voxelSize() const
Return a vector of the axial voxel sizes.
Definition NanoVDB.h:5566
nanovdb::ChannelAccessor::operator()
ChannelT & operator()(int i, int j, int k) const
Definition NanoVDB.h:5592
nanovdb::ChannelAccessor::idx
uint64_t idx(int i, int j, int k) const
Definition NanoVDB.h:5587
nanovdb::ChannelAccessor::setChannel
void setChannel(uint32_t channelID)
Change to an internal channel, assuming it exists as as blind data in the IndexGrid.
Definition NanoVDB.h:5580
nanovdb::ChannelAccessor::ChannelAccessor
ChannelAccessor(const IndexGrid &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:5538
nanovdb::ChannelAccessor::ChannelAccessor
ChannelAccessor(const IndexGrid &grid, ChannelT *channelPtr)
Ctor from an IndexGrid and an external channel.
Definition NanoVDB.h:5549
nanovdb::ChannelAccessor::tree
const IndexTree & tree() const
Return a const reference to the tree of the IndexGrid.
Definition NanoVDB.h:5563
nanovdb::ChannelAccessor::probeValue
bool probeValue(const CoordType &ijk, typename remove_const< ChannelT >::type &v) const
return the state and updates the value of the specified voxel
Definition NanoVDB.h:5595
nanovdb::ChannelAccessor::setChannel
void setChannel(ChannelT *channelPtr)
Change to an external channel.
Definition NanoVDB.h:5572
nanovdb::ChannelAccessor::getValue
ChannelT & getValue(const Coord &ijk) const
Return the value from a cached channel that maps to the specified coordinate.
Definition NanoVDB.h:5590
nanovdb::ChannelAccessor::operator()
ChannelT & operator()(const Coord &ijk) const
Definition NanoVDB.h:5591
nanovdb::Coord
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition NanoVDB.h:967
nanovdb::Coord::operator&=
Coord & operator&=(int n)
Definition NanoVDB.h:1047
nanovdb::Coord::operator-
Coord operator-(const Coord &rhs) const
Definition NanoVDB.h:1076
nanovdb::Coord::operator<<
Coord operator<<(IndexType n) const
Definition NanoVDB.h:1033
nanovdb::Coord::Floor
static Coord Floor(const Vec3T &xyz)
Return the largest integer coordinates that are not greater than xyz (node centered conversion).
Definition NanoVDB.h:1133
nanovdb::Coord::Coord
Coord(ValueType n)
Initializes all coordinates to the given signed integer.
Definition NanoVDB.h:980
nanovdb::Coord::operator-=
Coord & operator-=(const Coord &rhs)
Definition NanoVDB.h:1084
nanovdb::Coord::operator>>=
Coord & operator>>=(uint32_t n)
Definition NanoVDB.h:1061
nanovdb::Coord::minComponent
Coord & minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition NanoVDB.h:1093
nanovdb::Coord::operator+
Coord operator+(const Coord &rhs) const
Definition NanoVDB.h:1075
nanovdb::Coord::memUsage
static size_t memUsage()
Definition NanoVDB.h:1008
nanovdb::Coord::operator<
bool operator<(const Coord &rhs) const
Return true if this Coord is lexicographically less than the given Coord.
Definition NanoVDB.h:1039
nanovdb::Coord::operator+=
Coord & operator+=(const Coord &rhs)
Definition NanoVDB.h:1077
nanovdb::Coord::operator=
Coord & operator=(const CoordT &other)
Assignment operator that works with openvdb::Coord.
Definition NanoVDB.h:1020
nanovdb::Coord::y
int32_t y() const
Definition NanoVDB.h:997
nanovdb::Coord::maxComponent
Coord & maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition NanoVDB.h:1105
nanovdb::Coord::operator&
Coord operator&(IndexType n) const
Return a new instance with coordinates masked by the given unsigned integer.
Definition NanoVDB.h:1030
nanovdb::Coord::Coord
Coord()
Initialize all coordinates to zero.
Definition NanoVDB.h:974
nanovdb::Coord::octant
uint8_t octant() const
Return the octant of this Coord.
Definition NanoVDB.h:1144
nanovdb::Coord::operator[]
const ValueType & operator[](IndexType i) const
Return a const reference to the given Coord component.
Definition NanoVDB.h:1012
nanovdb::Coord::z
int32_t z() const
Definition NanoVDB.h:998
nanovdb::Coord::operator<<=
Coord & operator<<=(uint32_t n)
Definition NanoVDB.h:1054
nanovdb::Coord::x
int32_t x() const
Definition NanoVDB.h:996
nanovdb::Coord::Coord
Coord(ValueType i, ValueType j, ValueType k)
Initializes coordinate to the given signed integers.
Definition NanoVDB.h:986
nanovdb::Coord::y
int32_t & y()
Definition NanoVDB.h:1001
nanovdb::Coord::offsetBy
Coord offsetBy(ValueType n) const
Definition NanoVDB.h:1121
nanovdb::Coord::x
int32_t & x()
Definition NanoVDB.h:1000
nanovdb::Coord::Coord
Coord(ValueType *ptr)
Definition NanoVDB.h:991
nanovdb::Coord::operator!=
bool operator!=(const Coord &rhs) const
Definition NanoVDB.h:1046
nanovdb::Coord::min
static Coord min()
Definition NanoVDB.h:1006
nanovdb::Coord::operator[]
ValueType & operator[](IndexType i)
Return a non-const reference to the given Coord component.
Definition NanoVDB.h:1016
nanovdb::Coord::operator==
bool operator==(const Coord &rhs) const
Definition NanoVDB.h:1045
nanovdb::Coord::offsetBy
Coord offsetBy(ValueType dx, ValueType dy, ValueType dz) const
Definition NanoVDB.h:1116
nanovdb::Coord::max
static Coord max()
Definition NanoVDB.h:1004
nanovdb::Coord::z
int32_t & z()
Definition NanoVDB.h:1002
nanovdb::Coord::lessThan
static bool lessThan(const Coord &a, const Coord &b)
Definition NanoVDB.h:1125
nanovdb::Coord::operator>>
Coord operator>>(IndexType n) const
Definition NanoVDB.h:1036
nanovdb::Coord::hash
uint32_t hash() const
Return a hash key derived from the existing coordinates.
Definition NanoVDB.h:1140
nanovdb::Coord::operator+=
Coord & operator+=(int n)
Definition NanoVDB.h:1068
nanovdb::DenseGridHandle
Definition DenseGrid.h:402
nanovdb::DenseGridHandle::data
uint8_t * data()
Returns a non-const pointer to the data.
Definition DenseGrid.h:432
nanovdb::Fp16
Dummy type for a 16bit quantization of float point values.
Definition NanoVDB.h:228
nanovdb::Fp4
Dummy type for a 4bit quantization of float point values.
Definition NanoVDB.h:222
nanovdb::Fp8
Dummy type for a 8bit quantization of float point values.
Definition NanoVDB.h:225
nanovdb::FpN
Dummy type for a variable bit quantization of floating point values.
Definition NanoVDB.h:231
nanovdb::GridMetaData
This is a convenient class that allows for access to grid meta-data that are independent of the value...
Definition NanoVDB.h:5422
nanovdb::GridMetaData::activeTileCount
const uint32_t & activeTileCount(uint32_t level) const
Definition NanoVDB.h:5453
nanovdb::GridMetaData::isPointData
bool isPointData() const
Definition NanoVDB.h:5442
nanovdb::GridMetaData::gridIndex
uint32_t gridIndex() const
Definition NanoVDB.h:5434
nanovdb::GridMetaData::shortGridName
const char * shortGridName() const
Definition NanoVDB.h:5436
nanovdb::GridMetaData::activeVoxelCount
uint64_t activeVoxelCount() const
Definition NanoVDB.h:5452
nanovdb::GridMetaData::isStaggered
bool isStaggered() const
Definition NanoVDB.h:5444
nanovdb::GridMetaData::isValid
bool isValid() const
Definition NanoVDB.h:5432
nanovdb::GridMetaData::worldBBox
const BBox< Vec3R > & worldBBox() const
Definition NanoVDB.h:5447
nanovdb::GridMetaData::gridType
GridType gridType() const
Definition NanoVDB.h:5437
nanovdb::GridMetaData::gridSize
uint64_t gridSize() const
Definition NanoVDB.h:5433
nanovdb::GridMetaData::blindMetaData
const GridBlindMetaData & blindMetaData(uint32_t n) const
Definition NanoVDB.h:5451
nanovdb::GridMetaData::blindDataCount
int blindDataCount() const
Definition NanoVDB.h:5450
nanovdb::GridMetaData::checksum
uint64_t checksum() const
Definition NanoVDB.h:5455
nanovdb::GridMetaData::isFogVolume
bool isFogVolume() const
Definition NanoVDB.h:5440
nanovdb::GridMetaData::isMask
bool isMask() const
Definition NanoVDB.h:5443
nanovdb::GridMetaData::gridCount
uint32_t gridCount() const
Definition NanoVDB.h:5435
nanovdb::GridMetaData::gridClass
GridClass gridClass() const
Definition NanoVDB.h:5438
nanovdb::GridMetaData::version
Version version() const
Definition NanoVDB.h:5457
nanovdb::GridMetaData::isEmpty
bool isEmpty() const
Definition NanoVDB.h:5456
nanovdb::GridMetaData::voxelSize
Vec3R voxelSize() const
Definition NanoVDB.h:5449
nanovdb::GridMetaData::indexBBox
const BBox< Coord > & indexBBox() const
Definition NanoVDB.h:5448
nanovdb::GridMetaData::map
const Map & map() const
Definition NanoVDB.h:5446
nanovdb::GridMetaData::isLevelSet
bool isLevelSet() const
Definition NanoVDB.h:5439
nanovdb::GridMetaData::nodeCount
uint32_t nodeCount(uint32_t level) const
Definition NanoVDB.h:5454
nanovdb::GridMetaData::isPointIndex
bool isPointIndex() const
Definition NanoVDB.h:5441
nanovdb::GridMetaData::isUnknown
bool isUnknown() const
Definition NanoVDB.h:5445
nanovdb::Grid
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition NanoVDB.h:2558
nanovdb::Grid::indexToWorld
Vec3T indexToWorld(const Vec3T &xyz) const
index to world space transformation
Definition NanoVDB.h:2620
nanovdb::Grid::indexToWorldF
Vec3T indexToWorldF(const Vec3T &xyz) const
index to world space transformation
Definition NanoVDB.h:2643
nanovdb::Grid::gridType
const GridType & gridType() const
Definition NanoVDB.h:2674
nanovdb::Grid::blindDataCount
uint32_t blindDataCount() const
Return the count of blind-data encoded in this grid.
Definition NanoVDB.h:2723
nanovdb::Grid::ValueType
typename TreeT::ValueType ValueType
Definition NanoVDB.h:2563
nanovdb::Grid::valueCount
enable_if< is_same< T, ValueIndex >::value, constuint64_t & >::type valueCount() const
Return the total number of values indexed by this IndexGrid.
Definition NanoVDB.h:2597
nanovdb::Grid::RootType
typename TreeT::RootType RootType
Definition NanoVDB.h:2561
nanovdb::Grid::isSequential
bool isSequential() const
return true if the specified node type is layed out breadth-first in memory and has a fixed size....
Definition NanoVDB.h:2694
nanovdb::Grid::~Grid
~Grid()=delete
nanovdb::Grid::isPointData
bool isPointData() const
Definition NanoVDB.h:2681
nanovdb::Grid::gridIndex
uint32_t gridIndex() const
Return index of this grid in the buffer.
Definition NanoVDB.h:2588
nanovdb::Grid::shortGridName
const char * shortGridName() const
Return a c-string with the name of this grid, truncated to 255 characters.
Definition NanoVDB.h:2714
nanovdb::Grid::isBreadthFirst
bool isBreadthFirst() const
Definition NanoVDB.h:2689
nanovdb::Grid::activeVoxelCount
uint64_t activeVoxelCount() const
Return the total number of active voxels in this tree.
Definition NanoVDB.h:2670
nanovdb::Grid::indexToWorldDirF
Vec3T indexToWorldDirF(const Vec3T &dir) const
transformation from index space direction to world space direction
Definition NanoVDB.h:2648
nanovdb::Grid::CoordType
typename TreeT::CoordType CoordType
Definition NanoVDB.h:2565
nanovdb::Grid::worldToIndexF
Vec3T worldToIndexF(const Vec3T &xyz) const
world to index space transformation
Definition NanoVDB.h:2639
nanovdb::Grid::worldToIndexDirF
Vec3T worldToIndexDirF(const Vec3T &dir) const
transformation from world space direction to index space direction
Definition NanoVDB.h:2653
nanovdb::Grid::voxelSize
const Vec3R & voxelSize() const
Return a const reference to the size of a voxel in world units.
Definition NanoVDB.h:2609
nanovdb::Grid::isStaggered
bool isStaggered() const
Definition NanoVDB.h:2678
nanovdb::Grid::gridClass
const GridClass & gridClass() const
Definition NanoVDB.h:2675
nanovdb::Grid::isValid
bool isValid() const
Methods related to the classification of this grid.
Definition NanoVDB.h:2673
nanovdb::Grid::data
DataType * data()
Definition NanoVDB.h:2577
nanovdb::Grid::hasAverage
bool hasAverage() const
Definition NanoVDB.h:2687
nanovdb::Grid::hasMinMax
bool hasMinMax() const
Definition NanoVDB.h:2684
nanovdb::Grid::gridName
const char * gridName() const
Return a c-string with the name of this grid.
Definition NanoVDB.h:2702
nanovdb::Grid::worldBBox
const BBox< Vec3R > & worldBBox() const
Computes a AABB of active values in world space.
Definition NanoVDB.h:2661
nanovdb::Grid::getAccessor
AccessorType getAccessor() const
Return a new instance of a ReadAccessor used to access values in this grid.
Definition NanoVDB.h:2606
nanovdb::Grid::gridSize
uint64_t gridSize() const
Return the memory footprint of the entire grid, i.e. including all nodes and blind data.
Definition NanoVDB.h:2585
nanovdb::Grid::blindMetaData
const GridBlindMetaData & blindMetaData(uint32_t n) const
Definition NanoVDB.h:2740
nanovdb::Grid::indexToWorldDir
Vec3T indexToWorldDir(const Vec3T &dir) const
transformation from index space direction to world space direction
Definition NanoVDB.h:2625
nanovdb::Grid::indexToWorldGradF
Vec3T indexToWorldGradF(const Vec3T &grad) const
Transforms the gradient from index space to world space.
Definition NanoVDB.h:2658
nanovdb::Grid::checksum
uint64_t checksum() const
Return checksum of the grid buffer.
Definition NanoVDB.h:2717
nanovdb::Grid::isFogVolume
bool isFogVolume() const
Definition NanoVDB.h:2677
nanovdb::Grid::tree
const TreeT & tree() const
Return a const reference to the tree.
Definition NanoVDB.h:2600
nanovdb::Grid::isMask
bool isMask() const
Definition NanoVDB.h:2682
nanovdb::Grid::indexBBox
const BBox< CoordType > & indexBBox() const
Computes a AABB of active values in index space.
Definition NanoVDB.h:2667
nanovdb::Grid::hasLongGridName
bool hasLongGridName() const
Definition NanoVDB.h:2686
nanovdb::Grid::blindData
const void * blindData(uint32_t n) const
Returns a const pointer to the blindData at the specified linear offset.
Definition NanoVDB.h:2731
nanovdb::Grid::memUsage
static uint64_t memUsage()
Return memory usage in bytes for this class only.
Definition NanoVDB.h:2582
nanovdb::Grid::tree
TreeT & tree()
Return a non-const reference to the tree.
Definition NanoVDB.h:2603
nanovdb::Grid::worldToIndex
Vec3T worldToIndex(const Vec3T &xyz) const
world to index space transformation
Definition NanoVDB.h:2616
nanovdb::Grid::gridCount
uint32_t gridCount() const
Return total number of grids in the buffer.
Definition NanoVDB.h:2591
nanovdb::Grid::worldToIndexDir
Vec3T worldToIndexDir(const Vec3T &dir) const
transformation from world space direction to index space direction
Definition NanoVDB.h:2630
nanovdb::Grid::version
Version version() const
Definition NanoVDB.h:2575
nanovdb::Grid::isEmpty
bool isEmpty() const
Return true if this grid is empty, i.e. contains no values or nodes.
Definition NanoVDB.h:2720
nanovdb::Grid::map
const Map & map() const
Return a const reference to the Map for this grid.
Definition NanoVDB.h:2612
nanovdb::Grid::hasStdDeviation
bool hasStdDeviation() const
Definition NanoVDB.h:2688
nanovdb::Grid::hasBBox
bool hasBBox() const
Definition NanoVDB.h:2685
nanovdb::Grid::isLevelSet
bool isLevelSet() const
Definition NanoVDB.h:2676
nanovdb::Grid::isGridIndex
bool isGridIndex() const
Definition NanoVDB.h:2680
nanovdb::Grid::TreeType
TreeT TreeType
Definition NanoVDB.h:2560
nanovdb::Grid::Grid
Grid(const Grid &)=delete
Disallow constructions, copy and assignment.
nanovdb::Grid::BuildType
typename TreeT::BuildType BuildType
Definition NanoVDB.h:2564
nanovdb::Grid::operator=
Grid & operator=(const Grid &)=delete
nanovdb::Grid::indexToWorldGrad
Vec3T indexToWorldGrad(const Vec3T &grad) const
transform the gradient from index space to world space.
Definition NanoVDB.h:2635
nanovdb::Grid::data
const DataType * data() const
Definition NanoVDB.h:2579
nanovdb::Grid::isPointIndex
bool isPointIndex() const
Definition NanoVDB.h:2679
nanovdb::Grid::isUnknown
bool isUnknown() const
Definition NanoVDB.h:2683
nanovdb::Half
Dummy type for a 16 bit floating point values.
Definition NanoVDB.h:219
nanovdb::InternalNode::ChildIterator
Visits child nodes of this node only.
Definition NanoVDB.h:3548
nanovdb::InternalNode::ChildIterator::ChildIterator
ChildIterator()
Definition NanoVDB.h:3552
nanovdb::InternalNode::ChildIterator::getOrigin
CoordType getOrigin() const
Definition NanoVDB.h:3557
nanovdb::InternalNode::ChildIterator::operator->
const ChildT * operator->() const
Definition NanoVDB.h:3556
nanovdb::InternalNode::ChildIterator::operator=
ChildIterator & operator=(const ChildIterator &)=default
nanovdb::InternalNode::ChildIterator::ChildIterator
ChildIterator(const InternalNode *parent)
Definition NanoVDB.h:3553
nanovdb::InternalNode::ChildIterator::operator*
const ChildT & operator*() const
Definition NanoVDB.h:3555
nanovdb::InternalNode::ValueIterator
Visits all tile values in this node, i.e. both inactive and active tiles.
Definition NanoVDB.h:3564
nanovdb::InternalNode::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::InternalNode::ValueIterator::ValueIterator
ValueIterator(const InternalNode *parent)
Definition NanoVDB.h:3569
nanovdb::InternalNode::ValueIterator::isActive
bool isActive() const
Definition NanoVDB.h:3573
nanovdb::InternalNode::ValueIterator::ValueIterator
ValueIterator()
Definition NanoVDB.h:3568
nanovdb::InternalNode::ValueIterator::getOrigin
CoordType getOrigin() const
Definition NanoVDB.h:3572
nanovdb::InternalNode::ValueIterator::operator*
ValueType operator*() const
Definition NanoVDB.h:3571
nanovdb::InternalNode::ValueOnIterator
Visits active tile values of this node only.
Definition NanoVDB.h:3580
nanovdb::InternalNode::ValueOnIterator::ValueOnIterator
ValueOnIterator(const InternalNode *parent)
Definition NanoVDB.h:3585
nanovdb::InternalNode::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::InternalNode::ValueOnIterator::getOrigin
CoordType getOrigin() const
Definition NanoVDB.h:3588
nanovdb::InternalNode::ValueOnIterator::operator*
ValueType operator*() const
Definition NanoVDB.h:3587
nanovdb::InternalNode::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition NanoVDB.h:3584
nanovdb::InternalNode
Internal nodes of a VDB treedim(),.
Definition NanoVDB.h:3523
nanovdb::InternalNode::~InternalNode
~InternalNode()=delete
nanovdb::InternalNode::offsetToGlobalCoord
Coord offsetToGlobalCoord(uint32_t n) const
Definition NanoVDB.h:3702
nanovdb::InternalNode::valueMask
const MaskType< LOG2DIM > & valueMask() const
Return a const reference to the bit mask of active voxels in this internal node.
Definition NanoVDB.h:3610
nanovdb::InternalNode::beginValue
ValueIterator beginValue() const
Definition NanoVDB.h:3576
nanovdb::InternalNode::isActive
bool isActive() const
Return true if this node or any of its child nodes contain active values.
Definition NanoVDB.h:3710
nanovdb::InternalNode::dim
static uint32_t dim()
Return the dimension, in voxel units, of this internal node (typically 8*16 or 8*16*32)
Definition NanoVDB.h:3604
nanovdb::InternalNode::memUsage
static size_t memUsage()
Return memory usage in bytes for the class.
Definition NanoVDB.h:3607
nanovdb::InternalNode::origin
CoordType origin() const
Return the origin in index space of this leaf node.
Definition NanoVDB.h:3616
nanovdb::InternalNode::CoordType
typename ChildT::CoordType CoordType
Definition NanoVDB.h:3531
nanovdb::InternalNode::beginChild
ChildIterator beginChild() const
Definition NanoVDB.h:3560
nanovdb::InternalNode::bbox
const BBox< CoordType > & bbox() const
Return a const reference to the bounding box in index space of active values in this internal node an...
Definition NanoVDB.h:3634
nanovdb::InternalNode::variance
FloatType variance() const
Return the variance of all the active values encoded in this internal node and any of its child nodes...
Definition NanoVDB.h:3628
nanovdb::InternalNode::childMask
const MaskType< LOG2DIM > & childMask() const
Return a const reference to the bit mask of child nodes in this internal node.
Definition NanoVDB.h:3613
nanovdb::InternalNode::average
const FloatType & average() const
Return a const reference to the average of all the active values encoded in this internal node and an...
Definition NanoVDB.h:3625
nanovdb::InternalNode::data
DataType * data()
Definition NanoVDB.h:3599
nanovdb::InternalNode::localToGlobalCoord
void localToGlobalCoord(Coord &ijk) const
modifies local coordinates to global coordinates of a tile or child node
Definition NanoVDB.h:3696
nanovdb::InternalNode::BuildType
typename DataType::BuildT BuildType
Definition NanoVDB.h:3528
nanovdb::InternalNode::MaskIterT
typename Mask< Log2Dim >::template Iterator< On > MaskIterT
Definition NanoVDB.h:3536
nanovdb::InternalNode::ChildNodeType
ChildT ChildNodeType
Definition NanoVDB.h:3530
nanovdb::InternalNode::probeLeaf
const LeafNodeType * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:3659
nanovdb::InternalNode::isActive
bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:3643
nanovdb::InternalNode::ValueType
typename DataType::ValueT ValueType
Definition NanoVDB.h:3526
nanovdb::InternalNode::CoordToOffset
static uint32_t CoordToOffset(const CoordType &ijk)
Return the linear offset corresponding to the given coordinate.
Definition NanoVDB.h:3674
nanovdb::InternalNode::FloatType
typename DataType::StatsT FloatType
Definition NanoVDB.h:3527
nanovdb::InternalNode::OffsetToLocalCoord
static Coord OffsetToLocalCoord(uint32_t n)
Definition NanoVDB.h:3688
nanovdb::InternalNode::probeValue
bool probeValue(const CoordType &ijk, ValueType &v) const
return the state and updates the value of the specified voxel
Definition NanoVDB.h:3650
nanovdb::InternalNode::LeafNodeType
typename ChildT::LeafNodeType LeafNodeType
Definition NanoVDB.h:3529
nanovdb::InternalNode::probeChild
const ChildNodeType * probeChild(const CoordType &ijk) const
Definition NanoVDB.h:3667
nanovdb::InternalNode::stdDeviation
const FloatType & stdDeviation() const
Return a const reference to the standard deviation of all the active values encoded in this internal ...
Definition NanoVDB.h:3631
nanovdb::InternalNode::maximum
const ValueType & maximum() const
Return a const reference to the maximum active value encoded in this internal node and any of its chi...
Definition NanoVDB.h:3622
nanovdb::InternalNode::InternalNode
InternalNode()=delete
This class cannot be constructed or deleted.
nanovdb::InternalNode::getValue
ValueType getValue(const CoordType &ijk) const
Return the value of the given voxel.
Definition NanoVDB.h:3637
nanovdb::InternalNode::MaskType
typename ChildT::template MaskType< LOG2 > MaskType
Definition NanoVDB.h:3534
nanovdb::InternalNode::minimum
const ValueType & minimum() const
Return a const reference to the minimum active value encoded in this internal node and any of its chi...
Definition NanoVDB.h:3619
nanovdb::InternalNode::data
const DataType * data() const
Definition NanoVDB.h:3601
nanovdb::InternalNode::operator=
InternalNode & operator=(const InternalNode &)=delete
nanovdb::InternalNode::InternalNode
InternalNode(const InternalNode &)=delete
nanovdb::InternalNode::beginValueOn
ValueOnIterator beginValueOn() const
Definition NanoVDB.h:3591
nanovdb::LeafNode::ValueIterator
Visits all values in a leaf node, i.e. both active and inactive values.
Definition NanoVDB.h:4306
nanovdb::LeafNode::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::LeafNode::ValueIterator::operator++
ValueIterator & operator++()
Definition NanoVDB.h:4317
nanovdb::LeafNode::ValueIterator::operator++
ValueIterator operator++(int)
Definition NanoVDB.h:4318
nanovdb::LeafNode::ValueIterator::ValueIterator
ValueIterator(const LeafNode *parent)
Definition NanoVDB.h:4311
nanovdb::LeafNode::ValueIterator::isActive
bool isActive() const
Definition NanoVDB.h:4315
nanovdb::LeafNode::ValueIterator::getCoord
CoordT getCoord() const
Definition NanoVDB.h:4314
nanovdb::LeafNode::ValueIterator::ValueIterator
ValueIterator()
Definition NanoVDB.h:4310
nanovdb::LeafNode::ValueIterator::operator*
ValueType operator*() const
Definition NanoVDB.h:4313
nanovdb::LeafNode::ValueOffIterator
Visits all inactive values in a leaf node.
Definition NanoVDB.h:4291
nanovdb::LeafNode::ValueOffIterator::ValueOffIterator
ValueOffIterator()
Definition NanoVDB.h:4295
nanovdb::LeafNode::ValueOffIterator::getCoord
CoordT getCoord() const
Definition NanoVDB.h:4299
nanovdb::LeafNode::ValueOffIterator::operator=
ValueOffIterator & operator=(const ValueOffIterator &)=default
nanovdb::LeafNode::ValueOffIterator::operator*
ValueType operator*() const
Definition NanoVDB.h:4298
nanovdb::LeafNode::ValueOffIterator::ValueOffIterator
ValueOffIterator(const LeafNode *parent)
Definition NanoVDB.h:4296
nanovdb::LeafNode::ValueOnIterator
Visits all active values in a leaf node.
Definition NanoVDB.h:4276
nanovdb::LeafNode::ValueOnIterator::getCoord
CoordT getCoord() const
Definition NanoVDB.h:4284
nanovdb::LeafNode::ValueOnIterator::ValueOnIterator
ValueOnIterator(const LeafNode *parent)
Definition NanoVDB.h:4281
nanovdb::LeafNode::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::LeafNode::ValueOnIterator::operator*
ValueType operator*() const
Definition NanoVDB.h:4283
nanovdb::LeafNode::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition NanoVDB.h:4280
nanovdb::LeafNode
Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
Definition NanoVDB.h:4254
nanovdb::LeafNode::setValue
void setValue(const CoordT &ijk, const ValueType &v)
Sets the value at the specified location and activate its state.
Definition NanoVDB.h:4418
nanovdb::LeafNode::setValueOnly
void setValueOnly(uint32_t offset, const ValueType &v)
Sets the value at the specified location but leaves its state unchanged.
Definition NanoVDB.h:4423
nanovdb::LeafNode::isActive
bool isActive(const CoordT &ijk) const
Return true if the voxel value at the given coordinate is active.
Definition NanoVDB.h:4427
nanovdb::LeafNode::BuildType
typename DataType::BuildType BuildType
Definition NanoVDB.h:4266
nanovdb::LeafNode::valueMask
const MaskType< LOG2DIM > & valueMask() const
Return a const reference to the bit mask of active voxels in this leaf node.
Definition NanoVDB.h:4341
nanovdb::LeafNode::beginValue
ValueIterator beginValue() const
Definition NanoVDB.h:4325
nanovdb::LeafNode::isActive
bool isActive() const
Return true if any of the voxel value are active in this leaf node.
Definition NanoVDB.h:4431
nanovdb::LeafNode::CoordType
CoordT CoordType
Definition NanoVDB.h:4267
nanovdb::LeafNode::dim
static uint32_t dim()
Return the dimension, in index space, of this leaf node (typically 8 as for openvdb leaf nodes!...
Definition NanoVDB.h:4379
nanovdb::LeafNode::probeValue
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:4441
nanovdb::LeafNode::variance
FloatType variance() const
Return the variance of all the active values encoded in this leaf node.
Definition NanoVDB.h:4353
nanovdb::LeafNode::operator=
LeafNode & operator=(const LeafNode &)=delete
nanovdb::LeafNode::isActive
bool isActive(uint32_t n) const
Definition NanoVDB.h:4428
nanovdb::LeafNode::data
DataType * data()
Definition NanoVDB.h:4336
nanovdb::LeafNode::flags
uint8_t flags() const
Definition NanoVDB.h:4358
nanovdb::LeafNode::localToGlobalCoord
void localToGlobalCoord(Coord &ijk) const
Converts (in place) a local index coordinate to a global index coordinate.
Definition NanoVDB.h:4371
nanovdb::LeafNode::maximum
ValueType maximum() const
Return a const reference to the maximum active value encoded in this leaf node.
Definition NanoVDB.h:4347
nanovdb::LeafNode::FloatType
typename DataType::FloatType FloatType
Definition NanoVDB.h:4265
nanovdb::LeafNode::origin
CoordT origin() const
Return the origin in index space of this leaf node.
Definition NanoVDB.h:4361
nanovdb::LeafNode::MaskIterT
typename Mask< Log2Dim >::template Iterator< ON > MaskIterT
Definition NanoVDB.h:4272
nanovdb::LeafNode::~LeafNode
~LeafNode()=delete
nanovdb::LeafNode::CoordToOffset
static uint32_t CoordToOffset(const CoordT &ijk)
Return the linear offset corresponding to the given coordinate.
Definition NanoVDB.h:4451
nanovdb::LeafNode::offsetToGlobalCoord
CoordT offsetToGlobalCoord(uint32_t n) const
Definition NanoVDB.h:4373
nanovdb::LeafNode::setValueOnly
void setValueOnly(const CoordT &ijk, const ValueType &v)
Definition NanoVDB.h:4424
nanovdb::LeafNode::getValue
ValueType getValue(uint32_t offset) const
Return the voxel value at the given offset.
Definition NanoVDB.h:4410
nanovdb::LeafNode::average
FloatType average() const
Return a const reference to the average of all the active values encoded in this leaf node.
Definition NanoVDB.h:4350
nanovdb::LeafNode::probeLeaf
const LeafNode * probeLeaf(const CoordT &) const
Definition NanoVDB.h:4448
nanovdb::LeafNode::getValue
ValueType getValue(const CoordT &ijk) const
Return the voxel value at the given coordinate.
Definition NanoVDB.h:4413
nanovdb::LeafNode::voxelCount
static uint32_t voxelCount()
Return the total number of voxels (e.g. values) encoded in this leaf node.
Definition NanoVDB.h:4396
nanovdb::LeafNode::LeafNode
LeafNode(const LeafNode &)=delete
nanovdb::LeafNode::beginValueOff
ValueOffIterator beginValueOff() const
Definition NanoVDB.h:4302
nanovdb::LeafNode::bbox
BBox< CoordT > bbox() const
Return the bounding box in index space of active values in this leaf node.
Definition NanoVDB.h:4382
nanovdb::LeafNode::LeafNode
LeafNode()=delete
This class cannot be constructed or deleted.
nanovdb::LeafNode::minimum
ValueType minimum() const
Return a const reference to the minimum active value encoded in this leaf node.
Definition NanoVDB.h:4344
nanovdb::LeafNode::ValueType
typename DataType::ValueType ValueType
Definition NanoVDB.h:4264
nanovdb::LeafNode::padding
static uint32_t padding()
Definition NanoVDB.h:4398
nanovdb::LeafNode::OffsetToLocalCoord
static CoordT OffsetToLocalCoord(uint32_t n)
Definition NanoVDB.h:4363
nanovdb::LeafNode::hasBBox
bool hasBBox() const
Definition NanoVDB.h:4438
nanovdb::LeafNode::memUsage
uint64_t memUsage()
return memory usage in bytes for the class
Definition NanoVDB.h:4401
nanovdb::LeafNode::data
const DataType * data() const
Definition NanoVDB.h:4338
nanovdb::LeafNode::beginValueOn
ValueOnIterator beginValueOn() const
Definition NanoVDB.h:4287
nanovdb::LeafNode::stdDeviation
FloatType stdDeviation() const
Return a const reference to the standard deviation of all the active values encoded in this leaf node...
Definition NanoVDB.h:4356
nanovdb::Mask::Iterator
Definition NanoVDB.h:1993
nanovdb::Mask::Iterator::Iterator
Iterator()
Definition NanoVDB.h:1995
nanovdb::Mask::Iterator::operator=
Iterator & operator=(const Iterator &)=default
nanovdb::Mask::Iterator::operator*
uint32_t operator*() const
Definition NanoVDB.h:1998
nanovdb::Mask::Iterator::operator++
Iterator operator++(int)
Definition NanoVDB.h:2006
nanovdb::Mask::Iterator::pos
uint32_t pos() const
Definition NanoVDB.h:1999
nanovdb::Mask::Iterator::Iterator
Iterator(uint32_t pos, const Mask *parent)
Definition NanoVDB.h:1996
nanovdb::Mask::Iterator::operator++
Iterator & operator++()
Definition NanoVDB.h:2001
nanovdb::Mask
Bit-mask to encode active states and facilitate sequential iterators and a fast codec for I/O compres...
Definition NanoVDB.h:1959
nanovdb::Mask::set
void set(uint32_t n, bool On)
Set the specified bit on or off.
Definition NanoVDB.h:2117
nanovdb::Mask::beginOn
OnIterator beginOn() const
Definition NanoVDB.h:2021
nanovdb::Mask::isOff
bool isOff(uint32_t n) const
Return true if the given bit is NOT set.
Definition NanoVDB.h:2090
nanovdb::Mask::getWord
const WordT & getWord(int n) const
Return a const reference to the nth word of the bit mask, for a word of arbitrary size.
Definition NanoVDB.h:2047
nanovdb::Mask::operator==
bool operator==(const Mask &other) const
Definition NanoVDB.h:2076
nanovdb::Mask::memUsage
static size_t memUsage()
Return the memory footprint in bytes of this Mask.
Definition NanoVDB.h:1966
nanovdb::Mask::beginOff
OffIterator beginOff() const
Definition NanoVDB.h:2023
nanovdb::Mask::setOn
void setOn()
Set all bits on.
Definition NanoVDB.h:2130
nanovdb::Mask::toggle
void toggle(uint32_t n)
Definition NanoVDB.h:2157
nanovdb::Mask::countOn
uint32_t countOn() const
Return the total number of set bits in this Mask.
Definition NanoVDB.h:1975
nanovdb::Mask::operator^=
Mask & operator^=(const Mask &other)
Bitwise XOR.
Definition NanoVDB.h:2184
nanovdb::Mask::setOff
void setOff(uint32_t n)
Set the specified bit off.
Definition NanoVDB.h:2114
nanovdb::Mask::Mask
Mask(const Mask &other)
Copy constructor.
Definition NanoVDB.h:2039
nanovdb::Mask::getWord
WordT & getWord(int n)
Return a reference to the nth word of the bit mask, for a word of arbitrary size.
Definition NanoVDB.h:2055
nanovdb::Mask::Mask
Mask(bool on)
Definition NanoVDB.h:2031
nanovdb::Mask::operator=
Mask & operator=(const MaskT &other)
Assignment operator that works with openvdb::util::NodeMask.
Definition NanoVDB.h:2063
nanovdb::Mask::isOn
bool isOn(uint32_t n) const
Return true if the given bit is set.
Definition NanoVDB.h:2087
nanovdb::Mask::set
void set(bool on)
Set all bits off.
Definition NanoVDB.h:2144
nanovdb::Mask::operator|=
Mask & operator|=(const Mask &other)
Bitwise union.
Definition NanoVDB.h:2168
nanovdb::Mask::setOff
void setOff()
Set all bits off.
Definition NanoVDB.h:2137
nanovdb::Mask::operator&=
Mask & operator&=(const Mask &other)
Bitwise intersection.
Definition NanoVDB.h:2160
nanovdb::Mask::bitCount
static uint32_t bitCount()
Return the number of bits available in this Mask.
Definition NanoVDB.h:1969
nanovdb::Mask::isOff
bool isOff() const
Return true if none of the bits are set in this Mask.
Definition NanoVDB.h:2102
nanovdb::Mask::operator!=
bool operator!=(const Mask &other) const
Definition NanoVDB.h:2084
nanovdb::Mask::toggle
void toggle()
brief Toggle the state of all bits in the mask
Definition NanoVDB.h:2151
nanovdb::Mask::operator-=
Mask & operator-=(const Mask &other)
Bitwise difference.
Definition NanoVDB.h:2176
nanovdb::Mask::wordCount
static uint32_t wordCount()
Return the number of machine words used by this Mask.
Definition NanoVDB.h:1972
nanovdb::Mask::isOn
bool isOn() const
Return true if all the bits are set in this Mask.
Definition NanoVDB.h:2093
nanovdb::Mask::countOn
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:1984
nanovdb::Mask::Mask
Mask()
Initialize all bits to zero.
Definition NanoVDB.h:2026
nanovdb::Mask::setOn
void setOn(uint32_t n)
Set the specified bit on.
Definition NanoVDB.h:2111
nanovdb::PointAccessor
Class to access points at a specific voxel location.
Definition NanoVDB.h:5463
nanovdb::PointAccessor::gridPoints
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:5483
nanovdb::PointAccessor::LeafNodeType
typename NanoRoot< uint32_t >::LeafNodeType LeafNodeType
Definition NanoVDB.h:5469
nanovdb::PointAccessor::leafPoints
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:5493
nanovdb::PointAccessor::PointAccessor
PointAccessor(const UInt32Grid &grid)
Definition NanoVDB.h:5471
nanovdb::PointAccessor::voxelPoints
uint64_t voxelPoints(const Coord &ijk, const AttT *&begin, const AttT *&end) const
get iterators over offsets to points at a specific voxel location
Definition NanoVDB.h:5505
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::operator=
ReadAccessor & operator=(const ReadAccessor &)=default
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::~ReadAccessor
~ReadAccessor()=default
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::operator()
ValueType operator()(int i, int j, int k) const
Definition NanoVDB.h:4702
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::ReadAccessor
ReadAccessor(const GridT &grid)
Constructor from a grid.
Definition NanoVDB.h:4678
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::getNodeInfo
NodeInfo getNodeInfo(const CoordType &ijk) const
Definition NanoVDB.h:4707
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::ReadAccessor
ReadAccessor(const TreeT &tree)
Constructor from a tree.
Definition NanoVDB.h:4681
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::operator()
ValueType operator()(const CoordType &ijk) const
Definition NanoVDB.h:4698
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::isActive
bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:4712
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::probeValue
bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:4717
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::CoordType
typename RootT::CoordType CoordType
Definition NanoVDB.h:4659
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::ReadAccessor
ReadAccessor(const ReadAccessor &)=default
Defaults constructors.
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::root
const RootT & root() const
Definition NanoVDB.h:4687
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::clear
void clear()
Reset this access to its initial state, i.e. with an empty cache @node Noop since this template speci...
Definition NanoVDB.h:4685
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::getValue
ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:4694
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::ValueType
typename RootT::ValueType ValueType
Definition NanoVDB.h:4658
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::probeLeaf
const LeafT * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:4722
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::getDim
uint32_t getDim(const CoordType &ijk, const RayT &ray) const
Definition NanoVDB.h:4728
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::ReadAccessor
ReadAccessor(const RootT &root)
Constructor from a root node.
Definition NanoVDB.h:4675
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >
Node caching at all (three) tree levels.
Definition NanoVDB.h:5139
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::operator=
ReadAccessor & operator=(const ReadAccessor &)=default
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::NodeInfo
typename ReadAccessor< ValueT, -1, -1, -1 >::NodeInfo NodeInfo
Definition NanoVDB.h:5167
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::getNode
const NodeTrait< TreeT, LEVEL >::type * getNode() const
Definition NanoVDB.h:5206
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::CoordType
CoordT CoordType
Definition NanoVDB.h:5163
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::~ReadAccessor
~ReadAccessor()=default
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::operator()
ValueType operator()(int i, int j, int k) const
Definition NanoVDB.h:5270
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::ReadAccessor
ReadAccessor(const GridT &grid)
Constructor from a grid.
Definition NanoVDB.h:5182
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::getNodeInfo
NodeInfo getNodeInfo(const CoordType &ijk) const
Definition NanoVDB.h:5275
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::ReadAccessor
ReadAccessor(const TreeT &tree)
Constructor from a tree.
Definition NanoVDB.h:5185
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::operator()
ValueType operator()(const CoordType &ijk) const
Definition NanoVDB.h:5266
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::ValueType
ValueT ValueType
Definition NanoVDB.h:5162
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::isActive
bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:5292
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::getNode
const NodeT * getNode() const
Return a const point to the cached node of the specified type.
Definition NanoVDB.h:5198
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::probeValue
bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:5309
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::ReadAccessor
ReadAccessor(const ReadAccessor &)=default
Defaults constructors.
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::root
const RootT & root() const
Definition NanoVDB.h:5187
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::clear
void clear()
Reset this access to its initial state, i.e. with an empty cache.
Definition NanoVDB.h:5215
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::getValue
ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:5250
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::isCached
bool isCached(const CoordType &ijk) const
Definition NanoVDB.h:5244
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::probeLeaf
const LeafT * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:5326
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::getDim
uint32_t getDim(const CoordType &ijk, const RayT &ray) const
Definition NanoVDB.h:5344
nanovdb::ReadAccessor< BuildT, 0, 1, 2 >::ReadAccessor
ReadAccessor(const RootT &root)
Constructor from a root node.
Definition NanoVDB.h:5170
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::operator=
ReadAccessor & operator=(const ReadAccessor &)=default
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::NodeInfo
typename ReadAccessor< ValueT, -1, -1, -1 >::NodeInfo NodeInfo
Definition NanoVDB.h:4775
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::CoordType
CoordT CoordType
Definition NanoVDB.h:4771
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::~ReadAccessor
~ReadAccessor()=default
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::operator()
ValueType operator()(int i, int j, int k) const
Definition NanoVDB.h:4823
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::ReadAccessor
ReadAccessor(const GridT &grid)
Constructor from a grid.
Definition NanoVDB.h:4786
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::isCached
bool isCached(const CoordType &ijk) const
Definition NanoVDB.h:4805
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::getNodeInfo
NodeInfo getNodeInfo(const CoordType &ijk) const
Definition NanoVDB.h:4828
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::ReadAccessor
ReadAccessor(const TreeT &tree)
Constructor from a tree.
Definition NanoVDB.h:4789
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::operator()
ValueType operator()(const CoordType &ijk) const
Definition NanoVDB.h:4819
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::ValueType
ValueT ValueType
Definition NanoVDB.h:4770
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::isActive
bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:4836
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::probeValue
bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:4844
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::ReadAccessor
ReadAccessor(const ReadAccessor &)=default
Defaults constructors.
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::root
const RootT & root() const
Definition NanoVDB.h:4798
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::clear
void clear()
Reset this access to its initial state, i.e. with an empty cache.
Definition NanoVDB.h:4792
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::getValue
ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:4812
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::probeLeaf
const LeafT * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:4852
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::getDim
uint32_t getDim(const CoordType &ijk, const RayT &ray) const
Definition NanoVDB.h:4861
nanovdb::ReadAccessor< BuildT, LEVEL0, -1, -1 >::ReadAccessor
ReadAccessor(const RootT &root)
Constructor from a root node.
Definition NanoVDB.h:4778
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::operator=
ReadAccessor & operator=(const ReadAccessor &)=default
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::CoordType
CoordT CoordType
Definition NanoVDB.h:4920
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::~ReadAccessor
~ReadAccessor()=default
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::operator()
ValueType operator()(int i, int j, int k) const
Definition NanoVDB.h:5022
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::ReadAccessor
ReadAccessor(const GridT &grid)
Constructor from a grid.
Definition NanoVDB.h:4940
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::getNodeInfo
NodeInfo getNodeInfo(const CoordType &ijk) const
Definition NanoVDB.h:5027
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::ReadAccessor
ReadAccessor(const TreeT &tree)
Constructor from a tree.
Definition NanoVDB.h:4943
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::operator()
ValueType operator()(const CoordType &ijk) const
Definition NanoVDB.h:5018
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::ValueType
ValueT ValueType
Definition NanoVDB.h:4919
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::isActive
bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:5042
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::probeValue
bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:5057
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::NodeInfo
typename ReadAccessor< ValueT,-1,-1,-1 >::NodeInfo NodeInfo
Definition NanoVDB.h:4924
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::isCached1
bool isCached1(const CoordType &ijk) const
Definition NanoVDB.h:4990
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::ReadAccessor
ReadAccessor(const ReadAccessor &)=default
Defaults constructors.
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::root
const RootT & root() const
Definition NanoVDB.h:4957
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::clear
void clear()
Reset this access to its initial state, i.e. with an empty cache.
Definition NanoVDB.h:4946
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::getValue
ValueType getValue(const CoordType &ijk) const
Definition NanoVDB.h:5004
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::isCached2
bool isCached2(const CoordType &ijk) const
Definition NanoVDB.h:4996
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::probeLeaf
const LeafT * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:5072
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::getDim
uint32_t getDim(const CoordType &ijk, const RayT &ray) const
Definition NanoVDB.h:5088
nanovdb::ReadAccessor< BuildT, LEVEL0, LEVEL1, -1 >::ReadAccessor
ReadAccessor(const RootT &root)
Constructor from a root node.
Definition NanoVDB.h:4927
nanovdb::ReadAccessor
Definition NanoVDB.h:2547
nanovdb::Rgba8
8-bit red, green, blue, alpha packed into 32 bit unsigned int
Definition NanoVDB.h:559
nanovdb::Rgba8::packed
const uint32_t & packed() const
Definition NanoVDB.h:593
nanovdb::Rgba8::Rgba8
Rgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a=255u)
Definition NanoVDB.h:573
nanovdb::Rgba8::operator=
Rgba8 & operator=(const Rgba8 &)=default
nanovdb::Rgba8::g
const uint8_t & g() const
Definition NanoVDB.h:596
nanovdb::Rgba8::g
uint8_t & g()
Definition NanoVDB.h:600
nanovdb::Rgba8::Rgba8
Rgba8(float r, float g, float b, float a=1.0f)
Definition NanoVDB.h:575
nanovdb::Rgba8::packed
uint32_t packed
Definition NanoVDB.h:562
nanovdb::Rgba8::a
const uint8_t & a() const
Definition NanoVDB.h:598
nanovdb::Rgba8::operator<
bool operator<(const Rgba8 &rhs) const
Definition NanoVDB.h:582
nanovdb::Rgba8::Rgba8
Rgba8(Rgba8 &&)=default
nanovdb::Rgba8::r
const uint8_t & r() const
Definition NanoVDB.h:595
nanovdb::Rgba8::Rgba8
Rgba8()
Definition NanoVDB.h:572
nanovdb::Rgba8::Rgba8
Rgba8(uint8_t v)
Definition NanoVDB.h:574
nanovdb::Rgba8::lengthSqr
float lengthSqr() const
Definition NanoVDB.h:584
nanovdb::Rgba8::operator=
Rgba8 & operator=(Rgba8 &&)=default
nanovdb::Rgba8::b
const uint8_t & b() const
Definition NanoVDB.h:597
nanovdb::Rgba8::packed
uint32_t & packed()
Definition NanoVDB.h:594
nanovdb::Rgba8::r
uint8_t & r()
Definition NanoVDB.h:599
nanovdb::Rgba8::operator[]
uint8_t & operator[](int n)
Definition NanoVDB.h:592
nanovdb::Rgba8::length
float length() const
Definition NanoVDB.h:590
nanovdb::Rgba8::operator[]
const uint8_t & operator[](int n) const
Definition NanoVDB.h:591
nanovdb::Rgba8::operator==
bool operator==(const Rgba8 &rhs) const
Definition NanoVDB.h:583
nanovdb::Rgba8::Rgba8
Rgba8(const Rgba8 &)=default
nanovdb::Rgba8::b
uint8_t & b()
Definition NanoVDB.h:601
nanovdb::Rgba8::c
uint8_t c[4]
Definition NanoVDB.h:561
nanovdb::Rgba8::a
uint8_t & a()
Definition NanoVDB.h:602
nanovdb::Rgba8::SIZE
static const int SIZE
Definition NanoVDB.h:565
nanovdb::RootNode::ChildIterator
Definition NanoVDB.h:3096
nanovdb::RootNode::ChildIterator::ChildIterator
ChildIterator()
Definition NanoVDB.h:3100
nanovdb::RootNode::ChildIterator::operator++
ChildIterator & operator++()
Definition NanoVDB.h:3111
nanovdb::RootNode::ChildIterator::operator++
ChildIterator operator++(int)
Definition NanoVDB.h:3117
nanovdb::RootNode::ChildIterator::getOrigin
CoordType getOrigin() const
Definition NanoVDB.h:3108
nanovdb::RootNode::ChildIterator::operator->
const ChildT * operator->() const
Definition NanoVDB.h:3107
nanovdb::RootNode::ChildIterator::operator=
ChildIterator & operator=(const ChildIterator &)=default
nanovdb::RootNode::ChildIterator::pos
uint32_t pos() const
Definition NanoVDB.h:3110
nanovdb::RootNode::ChildIterator::operator*
const ChildT & operator*() const
Definition NanoVDB.h:3106
nanovdb::RootNode::ChildIterator::ChildIterator
ChildIterator(const RootNode *parent)
Definition NanoVDB.h:3101
nanovdb::RootNode::ValueIterator
Definition NanoVDB.h:3127
nanovdb::RootNode::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::RootNode::ValueIterator::operator++
ValueIterator & operator++()
Definition NanoVDB.h:3142
nanovdb::RootNode::ValueIterator::operator++
ValueIterator operator++(int)
Definition NanoVDB.h:3148
nanovdb::RootNode::ValueIterator::isActive
bool isActive() const
Definition NanoVDB.h:3138
nanovdb::RootNode::ValueIterator::ValueIterator
ValueIterator()
Definition NanoVDB.h:3131
nanovdb::RootNode::ValueIterator::getOrigin
CoordType getOrigin() const
Definition NanoVDB.h:3141
nanovdb::RootNode::ValueIterator::operator*
ValueType operator*() const
Definition NanoVDB.h:3137
nanovdb::RootNode::ValueIterator::pos
uint32_t pos() const
Definition NanoVDB.h:3140
nanovdb::RootNode::ValueIterator::ValueIterator
ValueIterator(const RootNode *parent)
Definition NanoVDB.h:3132
nanovdb::RootNode::ValueOnIterator
Definition NanoVDB.h:3158
nanovdb::RootNode::ValueOnIterator::operator++
ValueOnIterator operator++(int)
Definition NanoVDB.h:3178
nanovdb::RootNode::ValueOnIterator::ValueOnIterator
ValueOnIterator(const RootNode *parent)
Definition NanoVDB.h:3163
nanovdb::RootNode::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::RootNode::ValueOnIterator::getOrigin
CoordType getOrigin() const
Definition NanoVDB.h:3171
nanovdb::RootNode::ValueOnIterator::operator++
ValueOnIterator & operator++()
Definition NanoVDB.h:3172
nanovdb::RootNode::ValueOnIterator::operator*
ValueType operator*() const
Definition NanoVDB.h:3168
nanovdb::RootNode::ValueOnIterator::pos
uint32_t pos() const
Definition NanoVDB.h:3170
nanovdb::RootNode::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition NanoVDB.h:3162
nanovdb::RootNode
Top-most node of the VDB tree structure.
Definition NanoVDB.h:3076
nanovdb::RootNode::tileCount
const uint32_t & tileCount() const
Return the number of tiles encoded in this root node.
Definition NanoVDB.h:3209
nanovdb::RootNode::memUsage
static uint64_t memUsage(uint32_t tableSize)
Return the expected memory footprint in bytes with the specified number of tiles.
Definition NanoVDB.h:3227
nanovdb::RootNode::beginValue
ValueIterator beginValue() const
Definition NanoVDB.h:3155
nanovdb::RootNode::CoordType
typename ChildT::CoordType CoordType
Definition NanoVDB.h:3087
nanovdb::RootNode::beginChild
ChildIterator beginChild() const
Definition NanoVDB.h:3124
nanovdb::RootNode::variance
FloatType variance() const
Return the variance of all the active values encoded in this root node and any of its child nodes.
Definition NanoVDB.h:3221
nanovdb::RootNode::average
const FloatType & average() const
Return a const reference to the average of all the active values encoded in this root node and any of...
Definition NanoVDB.h:3218
nanovdb::RootNode::operator=
RootNode & operator=(const RootNode &)=delete
nanovdb::RootNode::data
DataType * data()
Definition NanoVDB.h:3195
nanovdb::RootNode::getAccessor
AccessorType getAccessor() const
Definition NanoVDB.h:3193
nanovdb::RootNode::BuildType
typename DataType::BuildT BuildType
Definition NanoVDB.h:3085
nanovdb::RootNode::bbox
const BBoxType & bbox() const
Return a const reference to the index bounding box of all the active values in this tree,...
Definition NanoVDB.h:3200
nanovdb::RootNode::RootNode
RootNode(const RootNode &)=delete
nanovdb::RootNode::ChildNodeType
ChildT ChildNodeType
Definition NanoVDB.h:3080
nanovdb::RootNode::probeLeaf
const LeafNodeType * probeLeaf(const CoordType &ijk) const
Definition NanoVDB.h:3266
nanovdb::RootNode::isActive
bool isActive(const CoordType &ijk) const
Definition NanoVDB.h:3241
nanovdb::RootNode::ValueType
typename DataType::ValueT ValueType
Definition NanoVDB.h:3083
nanovdb::RootNode::FloatType
typename DataType::StatsT FloatType
Definition NanoVDB.h:3084
nanovdb::RootNode::memUsage
uint64_t memUsage() const
Return the actual memory footprint of this root node.
Definition NanoVDB.h:3230
nanovdb::RootNode::probeValue
bool probeValue(const CoordType &ijk, ValueType &v) const
Definition NanoVDB.h:3252
nanovdb::RootNode::LeafNodeType
typename ChildT::LeafNodeType LeafNodeType
Definition NanoVDB.h:3079
nanovdb::RootNode::probeChild
const ChildNodeType * probeChild(const CoordType &ijk) const
Definition NanoVDB.h:3276
nanovdb::RootNode::stdDeviation
const FloatType & stdDeviation() const
Return a const reference to the standard deviation of all the active values encoded in this root node...
Definition NanoVDB.h:3224
nanovdb::RootNode::probeTile
const Tile * probeTile(const CoordType &ijk) const
Find and return a Tile of this root node.
Definition NanoVDB.h:3286
nanovdb::RootNode::maximum
const ValueType & maximum() const
Return a const reference to the maximum active value encoded in this root node and any of its child n...
Definition NanoVDB.h:3215
nanovdb::RootNode::Tile
typename DataType::Tile Tile
Definition NanoVDB.h:3090
nanovdb::RootNode::getValue
ValueType getValue(const CoordType &ijk) const
Return the value of the given voxel.
Definition NanoVDB.h:3233
nanovdb::RootNode::background
const ValueType & background() const
Return the total number of active voxels in the root and all its child nodes.
Definition NanoVDB.h:3206
nanovdb::RootNode::isEmpty
bool isEmpty() const
Return true if this RootNode is empty, i.e. contains no values or nodes.
Definition NanoVDB.h:3250
nanovdb::RootNode::~RootNode
~RootNode()=delete
nanovdb::RootNode::RootNode
RootNode()=delete
This class cannot be constructed or deleted.
nanovdb::RootNode::minimum
const ValueType & minimum() const
Return a const reference to the minimum active value encoded in this root node and any of its child n...
Definition NanoVDB.h:3212
nanovdb::RootNode::data
const DataType * data() const
Definition NanoVDB.h:3197
nanovdb::RootNode::beginValueOn
ValueOnIterator beginValueOn() const
Definition NanoVDB.h:3185
nanovdb::Tree
VDB Tree, which is a thin wrapper around a RootNode.
Definition NanoVDB.h:2801
nanovdb::Tree::Node2
typename RootT::ChildNodeType Node2
Definition NanoVDB.h:2817
nanovdb::Tree::getFirstLower
const NodeTrait< RootT, 1 >::type * getFirstLower() const
Definition NanoVDB.h:2932
nanovdb::Tree::Node3
RootT Node3
Definition NanoVDB.h:2816
nanovdb::Tree::activeTileCount
const uint32_t & activeTileCount(uint32_t level) const
Return the total number of active tiles at the specified level of the tree.
Definition NanoVDB.h:2869
nanovdb::Tree::getFirstNode
const NodeT * getFirstNode() const
return a const pointer to the first node of the specified type
Definition NanoVDB.h:2902
nanovdb::Tree::activeVoxelCount
uint64_t activeVoxelCount() const
Return the total number of active voxels in this tree.
Definition NanoVDB.h:2862
nanovdb::Tree::LeafNodeType
typename RootT::LeafNodeType LeafNodeType
Definition NanoVDB.h:2810
nanovdb::Tree::bbox
const BBox< CoordType > & bbox() const
Return a const reference to the index bounding box of all the active values in this tree,...
Definition NanoVDB.h:2859
nanovdb::Tree::getFirstUpper
const NodeTrait< RootT, 2 >::type * getFirstUpper() const
Definition NanoVDB.h:2934
nanovdb::Tree::data
DataType * data()
Definition NanoVDB.h:2827
nanovdb::Tree::nodeCount
uint32_t nodeCount() const
Definition NanoVDB.h:2876
nanovdb::Tree::getFirstLower
NodeTrait< RootT, 1 >::type * getFirstLower()
Definition NanoVDB.h:2931
nanovdb::Tree::Tree
Tree()=delete
This class cannot be constructed or deleted.
nanovdb::Tree::getAccessor
AccessorType getAccessor() const
Definition NanoVDB.h:2838
nanovdb::Tree::getFirstUpper
NodeTrait< RootT, 2 >::type * getFirstUpper()
Definition NanoVDB.h:2933
nanovdb::Tree::isActive
bool isActive(const CoordType &ijk) const
Return the active state of the given voxel (regardless of state or location in the tree....
Definition NanoVDB.h:2844
nanovdb::Tree::getFirstLeaf
const LeafNodeType * getFirstLeaf() const
Definition NanoVDB.h:2930
nanovdb::Tree::getFirstNode
NodeTrait< RootT, LEVEL >::type * getFirstNode()
return a pointer to the first node at the specified level
Definition NanoVDB.h:2913
nanovdb::Tree::~Tree
~Tree()=delete
nanovdb::Tree::probeValue
bool probeValue(const CoordType &ijk, ValueType &v) const
Combines the previous two methods in a single call.
Definition NanoVDB.h:2850
nanovdb::Tree::CoordType
typename RootT::CoordType CoordType
Definition NanoVDB.h:2813
nanovdb::Tree::root
RootT & root()
Definition NanoVDB.h:2834
nanovdb::Tree::getFirstLeaf
LeafNodeType * getFirstLeaf()
Template specializations of getFirstNode.
Definition NanoVDB.h:2929
nanovdb::Tree::Tree
Tree(const Tree &)=delete
nanovdb::Tree::memUsage
static uint64_t memUsage()
return memory usage in bytes for the class
Definition NanoVDB.h:2832
nanovdb::Tree::Node0
LeafNodeType Node0
Definition NanoVDB.h:2819
nanovdb::Tree::getFirstNode
NodeT * getFirstNode()
return a pointer to the first node of the specified type
Definition NanoVDB.h:2892
nanovdb::Tree::nodeCount
uint32_t nodeCount(int level) const
Definition NanoVDB.h:2882
nanovdb::Tree::Node1
typename Node2::ChildNodeType Node1
Definition NanoVDB.h:2818
nanovdb::Tree::getFirstNode
const NodeTrait< RootT, LEVEL >::type * getFirstNode() const
return a const pointer to the first node of the specified level
Definition NanoVDB.h:2923
nanovdb::Tree::root
const RootT & root() const
Definition NanoVDB.h:2836
nanovdb::Tree::getValue
ValueType getValue(const CoordType &ijk) const
Return the value of the given voxel (regardless of state or location in the tree.)
Definition NanoVDB.h:2841
nanovdb::Tree::RootType
RootT RootType
Definition NanoVDB.h:2809
nanovdb::Tree::background
const ValueType & background() const
Return a const reference to the background value.
Definition NanoVDB.h:2853
nanovdb::Tree::isEmpty
bool isEmpty() const
Return true if this tree is empty, i.e. contains no values or nodes.
Definition NanoVDB.h:2847
nanovdb::Tree::operator=
Tree & operator=(const Tree &)=delete
nanovdb::Tree::ValueType
typename RootT::ValueType ValueType
Definition NanoVDB.h:2811
nanovdb::Tree::data
const DataType * data() const
Definition NanoVDB.h:2829
nanovdb::Tree::BuildType
typename RootT::BuildType BuildType
Definition NanoVDB.h:2812
nanovdb::ValueIndex
Dummy type for a voxel whose value equals an offset into an external value array.
Definition NanoVDB.h:213
nanovdb::ValueMask
Dummy type for a voxel whose value equals its binary active state.
Definition NanoVDB.h:216
nanovdb::Vec3< float >
nanovdb::Vec3::Vec3
Vec3(const Vec3< T2 > &v)
Definition NanoVDB.h:1176
nanovdb::Vec3::round
Coord round() const
Definition NanoVDB.h:1275
nanovdb::Vec3::Vec3
Vec3(T x)
Definition NanoVDB.h:1167
nanovdb::Vec3::min
ValueType min() const
Return the smallest vector component.
Definition NanoVDB.h:1264
nanovdb::Vec3::minComponent
Vec3 & minComponent(const Vec3 &other)
Perform a component-wise minimum with the other Coord.
Definition NanoVDB.h:1241
nanovdb::Vec3::Vec3
Vec3(const Coord &ijk)
Definition NanoVDB.h:1180
nanovdb::Vec3::operator==
bool operator==(const Vec3 &rhs) const
Definition NanoVDB.h:1184
nanovdb::Vec3::operator-
Vec3 operator-() const
Definition NanoVDB.h:1210
nanovdb::Vec3::length
T length() const
Definition NanoVDB.h:1209
nanovdb::Vec3::operator*
Vec3 operator*(const Vec3 &v) const
Definition NanoVDB.h:1211
nanovdb::Vec3::maxComponent
Vec3 & maxComponent(const Vec3 &other)
Perform a component-wise maximum with the other Coord.
Definition NanoVDB.h:1253
nanovdb::Vec3::operator-=
Vec3 & operator-=(const Vec3 &v)
Definition NanoVDB.h:1224
nanovdb::Vec3::floor
Coord floor() const
Definition NanoVDB.h:1273
nanovdb::Vec3::operator*
Vec3 operator*(const T &s) const
Definition NanoVDB.h:1215
nanovdb::Vec3::Vec3
Vec3(T x, T y, T z)
Definition NanoVDB.h:1171
nanovdb::Vec3::operator/
Vec3 operator/(const Vec3 &v) const
Definition NanoVDB.h:1212
nanovdb::Vec3::dot
T dot(const Vec3T &v) const
Definition NanoVDB.h:1197
nanovdb::Vec3::operator=
Vec3 & operator=(const Vec3T &rhs)
Definition NanoVDB.h:1187
nanovdb::Vec3::operator*=
Vec3 & operator*=(const T &s)
Definition NanoVDB.h:1231
nanovdb::Vec3::normalize
Vec3 & normalize()
Definition NanoVDB.h:1239
nanovdb::Vec3::lengthSqr
T lengthSqr() const
Definition NanoVDB.h:1205
nanovdb::Vec3::operator+=
Vec3 & operator+=(const Vec3 &v)
Definition NanoVDB.h:1217
nanovdb::Vec3::ceil
Coord ceil() const
Definition NanoVDB.h:1274
nanovdb::Vec3::Vec3
Vec3()=default
nanovdb::Vec3::operator[]
const T & operator[](int i) const
Definition NanoVDB.h:1194
nanovdb::Vec3::cross
Vec3 cross(const Vec3T &v) const
Definition NanoVDB.h:1199
nanovdb::Vec3::operator/
Vec3 operator/(const T &s) const
Definition NanoVDB.h:1216
nanovdb::Vec3::operator!=
bool operator!=(const Vec3 &rhs) const
Definition NanoVDB.h:1185
nanovdb::Vec3::operator+
Vec3 operator+(const Vec3 &v) const
Definition NanoVDB.h:1213
nanovdb::Vec3::operator[]
T & operator[](int i)
Definition NanoVDB.h:1195
nanovdb::Vec3::operator-
Vec3 operator-(const Vec3 &v) const
Definition NanoVDB.h:1214
nanovdb::Vec3::max
ValueType max() const
Return the largest vector component.
Definition NanoVDB.h:1269
nanovdb::Vec3::operator/=
Vec3 & operator/=(const T &s)
Definition NanoVDB.h:1238
nanovdb::Vec4
A simple vector class with three double components, similar to openvdb::math::Vec4.
Definition NanoVDB.h:1305
nanovdb::Vec4::normalize
Vec4 & normalize()
Definition NanoVDB.h:1377
nanovdb::Vec4::operator/=
Vec4 & operator/=(const T &s)
Definition NanoVDB.h:1376
nanovdb::Vec4::operator/
Vec4 operator/(const Vec4 &v) const
Definition NanoVDB.h:1347
nanovdb::Vec4::operator+=
Vec4 & operator+=(const Vec4 &v)
Definition NanoVDB.h:1352
nanovdb::Vec4::operator*
Vec4 operator*(const T &s) const
Definition NanoVDB.h:1350
nanovdb::Vec4::length
T length() const
Definition NanoVDB.h:1344
nanovdb::Vec4::operator-
Vec4 operator-(const Vec4 &v) const
Definition NanoVDB.h:1349
nanovdb::Vec4::operator*=
Vec4 & operator*=(const T &s)
Definition NanoVDB.h:1368
nanovdb::Vec4::operator*
Vec4 operator*(const Vec4 &v) const
Definition NanoVDB.h:1346
nanovdb::Vec4::Vec4
Vec4(T x, T y, T z, T w)
Definition NanoVDB.h:1316
nanovdb::Vec4::operator!=
bool operator!=(const Vec4 &rhs) const
Definition NanoVDB.h:1326
nanovdb::Vec4::maxComponent
Vec4 & maxComponent(const Vec4 &other)
Perform a component-wise maximum with the other Coord.
Definition NanoVDB.h:1393
nanovdb::Vec4::Vec4
Vec4(const Vec4< T2 > &v)
Definition NanoVDB.h:1321
nanovdb::Vec4::lengthSqr
T lengthSqr() const
Definition NanoVDB.h:1340
nanovdb::Vec4::operator[]
const T & operator[](int i) const
Definition NanoVDB.h:1336
nanovdb::Vec4::operator=
Vec4 & operator=(const Vec4T &rhs)
Definition NanoVDB.h:1328
nanovdb::Vec4::operator-=
Vec4 & operator-=(const Vec4 &v)
Definition NanoVDB.h:1360
nanovdb::Vec4::Vec4
Vec4()=default
nanovdb::Vec4::operator==
bool operator==(const Vec4 &rhs) const
Definition NanoVDB.h:1325
nanovdb::Vec4::minComponent
Vec4 & minComponent(const Vec4 &other)
Perform a component-wise minimum with the other Coord.
Definition NanoVDB.h:1379
nanovdb::Vec4::operator[]
T & operator[](int i)
Definition NanoVDB.h:1337
nanovdb::Vec4::operator-
Vec4 operator-() const
Definition NanoVDB.h:1345
nanovdb::Vec4::operator/
Vec4 operator/(const T &s) const
Definition NanoVDB.h:1351
nanovdb::Vec4::dot
T dot(const Vec4T &v) const
Definition NanoVDB.h:1339
nanovdb::Vec4::Vec4
Vec4(T x)
Definition NanoVDB.h:1312
nanovdb::Vec4::operator+
Vec4 operator+(const Vec4 &v) const
Definition NanoVDB.h:1348
nanovdb::Version
Bit-compacted representation of all three version numbers.
Definition NanoVDB.h:648
nanovdb::Version::c_str
const char * c_str() const
Definition NanoVDB.h:674
nanovdb::Version::getPatch
uint32_t getPatch() const
Definition NanoVDB.h:671
nanovdb::Version::operator<=
bool operator<=(const Version &rhs) const
Definition NanoVDB.h:665
nanovdb::Version::Version
Version()
Definition NanoVDB.h:651
nanovdb::Version::operator==
bool operator==(const Version &rhs) const
Definition NanoVDB.h:663
nanovdb::Version::Version
Version(uint32_t major, uint32_t minor, uint32_t patch)
Definition NanoVDB.h:656
nanovdb::Version::getMajor
uint32_t getMajor() const
Definition NanoVDB.h:669
nanovdb::Version::operator>=
bool operator>=(const Version &rhs) const
Definition NanoVDB.h:667
nanovdb::Version::getMinor
uint32_t getMinor() const
Definition NanoVDB.h:670
nanovdb::Version::id
uint32_t id() const
Definition NanoVDB.h:668
nanovdb::io::writeUncompressedGrid
void writeUncompressedGrid(StreamT &os, const void *buffer)
This is a standalone alternative to io::writeGrid(...,Codec::NONE) defined in util/IO....
Definition NanoVDB.h:5649
nanovdb::io::readUncompressedGrids
VecT< GridHandleT > readUncompressedGrids(StreamT &is, const typename GridHandleT::BufferType &buffer=typename GridHandleT::BufferType())
read all uncompressed grids from a stream and return their handles.
Definition NanoVDB.h:5722
nanovdb::io::writeUncompressedGrids
void writeUncompressedGrids(const char *fileName, const VecT< GridHandleT > &handles)
write multiple NanoVDB grids to a single file, without compression.
Definition NanoVDB.h:5697
nanovdb
Definition NanoVDB.h:208
nanovdb::AlignUp
uint64_t AlignUp(uint64_t byteCount)
round up byteSize to the nearest wordSize, e.g. to align to machine word: AlignUp<sizeof(size_t)(n)
Definition NanoVDB.h:954
nanovdb::toStr
const char * toStr(GridType gridType)
Retuns a c-string used to describe a GridType.
Definition NanoVDB.h:267
nanovdb::Fract
float Fract(float x)
Definition NanoVDB.h:809
nanovdb::PtrDiff
static int64_t PtrDiff(const T1 *p, const T2 *q)
Definition NanoVDB.h:535
nanovdb::alignmentPadding
static uint64_t alignmentPadding(const void *p)
return the smallest number of bytes that when added to the specified pointer results in an aligned po...
Definition NanoVDB.h:510
nanovdb::matMult
Vec3T matMult(const float *mat, const Vec3T &xyz)
Definition NanoVDB.h:1533
nanovdb::PtrAdd
static DstT * PtrAdd(SrcT *p, int64_t offset)
Definition NanoVDB.h:542
nanovdb::GridClass
GridClass
Classes (defined in OpenVDB) that are currently supported by NanoVDB.
Definition NanoVDB.h:281
nanovdb::GridClass::FogVolume
@ FogVolume
nanovdb::GridClass::VoxelVolume
@ VoxelVolume
nanovdb::GridClass::End
@ End
nanovdb::GridClass::Topology
@ Topology
nanovdb::GridClass::PointIndex
@ PointIndex
nanovdb::GridClass::PointData
@ PointData
nanovdb::GridClass::Staggered
@ Staggered
nanovdb::GridClass::LevelSet
@ LevelSet
nanovdb::matMultT
Vec3T matMultT(const float *mat, const Vec3T &xyz)
Definition NanoVDB.h:1567
nanovdb::GridType
GridType
List of types that are currently supported by NanoVDB.
Definition NanoVDB.h:243
nanovdb::GridType::Float
@ Float
nanovdb::GridType::Boolean
@ Boolean
nanovdb::GridType::Int16
@ Int16
nanovdb::GridType::End
@ End
nanovdb::GridType::Unknown
@ Unknown
nanovdb::GridType::Index
@ Index
nanovdb::GridType::RGBA8
@ RGBA8
nanovdb::GridType::Int32
@ Int32
nanovdb::GridType::Double
@ Double
nanovdb::GridType::UInt32
@ UInt32
nanovdb::GridType::Int64
@ Int64
nanovdb::createAccessor
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:5398
nanovdb::alignPtr
static T * alignPtr(T *p)
offset the specified pointer so it is aligned.
Definition NanoVDB.h:518
nanovdb::GridFlags
GridFlags
Grid flags which indicate what extra information is present in the grid buffer.
Definition NanoVDB.h:306
nanovdb::GridFlags::HasAverage
@ HasAverage
nanovdb::GridFlags::HasStdDeviation
@ HasStdDeviation
nanovdb::GridFlags::HasLongGridName
@ HasLongGridName
nanovdb::GridFlags::HasMinMax
@ HasMinMax
nanovdb::GridFlags::End
@ End
nanovdb::GridFlags::HasBBox
@ HasBBox
nanovdb::GridFlags::IsBreadthFirst
@ IsBreadthFirst
nanovdb::Floor
int32_t Floor(float x)
Definition NanoVDB.h:818
nanovdb::GridBlindDataClass
GridBlindDataClass
Blind-data Classes that are currently supported by NanoVDB.
Definition NanoVDB.h:335
nanovdb::GridBlindDataClass::ChannelArray
@ ChannelArray
nanovdb::GridBlindDataClass::IndexArray
@ IndexArray
nanovdb::GridBlindDataClass::AttributeArray
@ AttributeArray
nanovdb::GridBlindDataClass::GridName
@ GridName
nanovdb::mapToGridType
GridType mapToGridType()
Maps from a templated value type to a GridType enum.
Definition NanoVDB.h:1488
nanovdb::isAligned
static bool isAligned(const void *p)
return true if the specified pointer is aligned
Definition NanoVDB.h:498
nanovdb::GridBlindDataSemantic
GridBlindDataSemantic
Blind-data Semantics that are currently understood by NanoVDB.
Definition NanoVDB.h:343
nanovdb::GridBlindDataSemantic::PointRadius
@ PointRadius
nanovdb::GridBlindDataSemantic::PointPosition
@ PointPosition
nanovdb::GridBlindDataSemantic::PointColor
@ PointColor
nanovdb::GridBlindDataSemantic::PointVelocity
@ PointVelocity
nanovdb::GridBlindDataSemantic::PointNormal
@ PointNormal
nanovdb::GridBlindDataSemantic::PointId
@ PointId
nanovdb::isFloatingPoint
bool isFloatingPoint(GridType gridType)
return true if the GridType maps to a floating point value.
Definition NanoVDB.h:610
nanovdb::isValid
static bool isValid(const void *p)
return true if the specified pointer is aligned and not NULL
Definition NanoVDB.h:504
std
Definition Coord.h:589
nanovdb::BBox< CoordT, false >::begin
Iterator begin() const
Definition NanoVDB.h:1749
nanovdb::BBox< CoordT, false >::BBox
BBox()
Definition NanoVDB.h:1750
nanovdb::BBox< CoordT, false >::is_divisible
bool is_divisible() const
Definition NanoVDB.h:1774
nanovdb::BBox< CoordT, false >::BBox
BBox(const CoordT &min, const CoordT &max)
Definition NanoVDB.h:1754
nanovdb::BBox< CoordT, false >::dim
CoordT dim() const
Definition NanoVDB.h:1781
nanovdb::BBox< CoordT, false >::empty
bool empty() const
Return true if this bounding box is empty, i.e. uninitialized.
Definition NanoVDB.h:1778
nanovdb::BBox< CoordT, false >::expandBy
BBox expandBy(typename CoordT::ValueType padding) const
Return a new instance that is expanded by the specified padding.
Definition NanoVDB.h:1805
nanovdb::BBox< CoordT, false >::isInside
bool isInside(const BBox &b) const
Return true if the given bounding box is inside this bounding box.
Definition NanoVDB.h:1785
nanovdb::BBox< CoordT, false >::hasOverlap
bool hasOverlap(const BBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition NanoVDB.h:1791
nanovdb::BBox< CoordT, false >::volume
uint64_t volume() const
Definition NanoVDB.h:1782
nanovdb::BBox< CoordT, false >::createCube
static BBox createCube(const CoordT &min, typename CoordT::ValueType dim)
Definition NanoVDB.h:1769
nanovdb::BBox< CoordT, false >::BBox
BBox(BBox &other, const SplitT &)
Definition NanoVDB.h:1760
nanovdb::BBox< CoordT, false >::asReal
BBox< Vec3< RealT > > asReal() const
Definition NanoVDB.h:1798
nanovdb::BBox< CoordT, false >::isInside
bool isInside(const CoordT &p) const
Definition NanoVDB.h:1783
nanovdb::BBox< Vec3T, true >::dim
Vec3T dim() const
Definition NanoVDB.h:1694
nanovdb::BBox< Vec3T, true >::isInside
bool isInside(const Vec3T &p) const
Definition NanoVDB.h:1695
nanovdb::BBox< Vec3T, true >::BBox
BBox()
Definition NanoVDB.h:1671
nanovdb::BBox< Vec3T, true >::BBox
BBox(const Coord &min, const Coord &max)
Definition NanoVDB.h:1680
nanovdb::BBox< Vec3T, true >::empty
bool empty() const
Definition NanoVDB.h:1691
nanovdb::BBox< Vec3T, true >::BBox
BBox(const Vec3T &min, const Vec3T &max)
Definition NanoVDB.h:1676
nanovdb::BBox< Vec3T, true >::Vec3Type
Vec3T Vec3Type
Definition NanoVDB.h:1666
nanovdb::BBox< Vec3T, true >::ValueType
typename Vec3T::ValueType ValueType
Definition NanoVDB.h:1667
nanovdb::BBox< Vec3T, true >::createCube
static BBox createCube(const Coord &min, typename Coord::ValueType dim)
Definition NanoVDB.h:1685
nanovdb::BBox< Vec3T, true >::BBox
BBox(const BaseBBox< Coord > &bbox)
Definition NanoVDB.h:1690
nanovdb::BBox
Definition NanoVDB.h:1657
nanovdb::BaseBBox
Definition NanoVDB.h:1603
nanovdb::BaseBBox::mCoord
Vec3T mCoord[2]
Definition NanoVDB.h:1604
nanovdb::BaseBBox::BaseBBox
BaseBBox()
Definition NanoVDB.h:1649
nanovdb::BaseBBox::max
const Vec3T & max() const
Definition NanoVDB.h:1612
nanovdb::BaseBBox::translate
Coord & translate(const Vec3T &xyz)
Definition NanoVDB.h:1613
nanovdb::BaseBBox::expand
BaseBBox & expand(const Vec3T &xyz)
Definition NanoVDB.h:1620
nanovdb::BaseBBox::operator!=
bool operator!=(const BaseBBox &rhs) const
Definition NanoVDB.h:1606
nanovdb::BaseBBox::operator[]
const Vec3T & operator[](int i) const
Definition NanoVDB.h:1607
nanovdb::BaseBBox::operator[]
Vec3T & operator[](int i)
Definition NanoVDB.h:1608
nanovdb::BaseBBox::isInside
bool isInside(const Vec3T &xyz)
Definition NanoVDB.h:1639
nanovdb::BaseBBox::min
const Vec3T & min() const
Definition NanoVDB.h:1611
nanovdb::BaseBBox::BaseBBox
BaseBBox(const Vec3T &min, const Vec3T &max)
Definition NanoVDB.h:1650
nanovdb::BaseBBox::min
Vec3T & min()
Definition NanoVDB.h:1609
nanovdb::BaseBBox::operator==
bool operator==(const BaseBBox &rhs) const
Definition NanoVDB.h:1605
nanovdb::BaseBBox::max
Vec3T & max()
Definition NanoVDB.h:1610
nanovdb::BaseBBox::intersect
BaseBBox & intersect(const BaseBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition NanoVDB.h:1628
nanovdb::BuildToValueMap
Maps one type (e.g. the build types above) to other (actual) types.
Definition NanoVDB.h:441
nanovdb::Delta< double >::value
static double value()
Definition NanoVDB.h:713
nanovdb::Delta< float >::value
static float value()
Definition NanoVDB.h:708
nanovdb::Delta
Delta for small floating-point offsets.
Definition NanoVDB.h:704
nanovdb::FloatTraits
Definition NanoVDB.h:1456
nanovdb::GridBlindMetaData
Definition NanoVDB.h:2317
nanovdb::GridBlindMetaData::mFlags
uint32_t mFlags
Definition NanoVDB.h:2321
nanovdb::GridBlindMetaData::memUsage
static uint64_t memUsage(uint64_t blindDataCount=0)
return memory usage in bytes for the class (note this computes for all blindMetaData structures....
Definition NanoVDB.h:2328
nanovdb::GridBlindMetaData::setBlindData
void setBlindData(void *ptr)
Definition NanoVDB.h:2333
nanovdb::GridBlindMetaData::mDataType
GridType mDataType
Definition NanoVDB.h:2324
nanovdb::GridBlindMetaData::mSemantic
GridBlindDataSemantic mSemantic
Definition NanoVDB.h:2322
nanovdb::GridBlindMetaData::mByteOffset
int64_t mByteOffset
Definition NanoVDB.h:2319
nanovdb::GridBlindMetaData::mDataClass
GridBlindDataClass mDataClass
Definition NanoVDB.h:2323
nanovdb::GridBlindMetaData::mElementCount
uint64_t mElementCount
Definition NanoVDB.h:2320
nanovdb::GridBlindMetaData::getBlindData
const T * getBlindData() const
Definition NanoVDB.h:2336
nanovdb::GridData
Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
Definition NanoVDB.h:2434
nanovdb::GridData::mFlags
uint32_t mFlags
Definition NanoVDB.h:2439
nanovdb::GridData::treePtr
const void * treePtr() const
Definition NanoVDB.h:2532
nanovdb::GridData::setMinMaxOn
void setMinMaxOn(bool on=true)
Definition NanoVDB.h:2456
nanovdb::GridData::setAverageOn
void setAverageOn(bool on=true)
Definition NanoVDB.h:2480
nanovdb::GridData::applyInverseJacobianF
Vec3T applyInverseJacobianF(const Vec3T &xyz) const
Definition NanoVDB.h:2524
nanovdb::GridData::applyIJTF
Vec3T applyIJTF(const Vec3T &xyz) const
Definition NanoVDB.h:2526
nanovdb::GridData::mBlindMetadataCount
uint32_t mBlindMetadataCount
Definition NanoVDB.h:2450
nanovdb::GridData::mVersion
Version mVersion
Definition NanoVDB.h:2438
nanovdb::GridData::mData0
uint32_t mData0
Definition NanoVDB.h:2451
nanovdb::GridData::mGridType
GridType mGridType
Definition NanoVDB.h:2448
nanovdb::GridData::mMagic
uint64_t mMagic
Definition NanoVDB.h:2436
nanovdb::GridData::setStdDeviationOn
void setStdDeviationOn(bool on=true)
Definition NanoVDB.h:2488
nanovdb::GridData::applyIJT
Vec3T applyIJT(const Vec3T &xyz) const
Definition NanoVDB.h:2515
nanovdb::GridData::mGridClass
GridClass mGridClass
Definition NanoVDB.h:2447
nanovdb::GridData::setBBoxOn
void setBBoxOn(bool on=true)
Definition NanoVDB.h:2464
nanovdb::GridData::setLongGridNameOn
void setLongGridNameOn(bool on=true)
Definition NanoVDB.h:2472
nanovdb::GridData::applyJacobianF
Vec3T applyJacobianF(const Vec3T &xyz) const
Definition NanoVDB.h:2522
nanovdb::GridData::mGridSize
uint64_t mGridSize
Definition NanoVDB.h:2442
nanovdb::GridData::mWorldBBox
BBox< Vec3R > mWorldBBox
Definition NanoVDB.h:2445
nanovdb::GridData::applyInverseJacobian
Vec3T applyInverseJacobian(const Vec3T &xyz) const
Definition NanoVDB.h:2513
nanovdb::GridData::treePtr
void * treePtr()
Definition NanoVDB.h:2529
nanovdb::GridData::blindMetaData
const GridBlindMetaData * blindMetaData(uint32_t n) const
Returns a const reference to the blindMetaData at the specified linear offset.
Definition NanoVDB.h:2537
nanovdb::GridData::setBreadthFirstOn
void setBreadthFirstOn(bool on=true)
Definition NanoVDB.h:2496
nanovdb::GridData::mChecksum
uint64_t mChecksum
Definition NanoVDB.h:2437
nanovdb::GridData::applyMapF
Vec3T applyMapF(const Vec3T &xyz) const
Definition NanoVDB.h:2518
nanovdb::GridData::mData1
uint64_t mData1
Definition NanoVDB.h:2452
nanovdb::GridData::mGridCount
uint32_t mGridCount
Definition NanoVDB.h:2441
nanovdb::GridData::mVoxelSize
Vec3R mVoxelSize
Definition NanoVDB.h:2446
nanovdb::GridData::applyInverseMap
Vec3T applyInverseMap(const Vec3T &xyz) const
Definition NanoVDB.h:2509
nanovdb::GridData::mMap
Map mMap
Definition NanoVDB.h:2444
nanovdb::GridData::applyJacobian
Vec3T applyJacobian(const Vec3T &xyz) const
Definition NanoVDB.h:2511
nanovdb::GridData::setFlagsOff
void setFlagsOff()
Definition NanoVDB.h:2455
nanovdb::GridData::mBlindMetadataOffset
int64_t mBlindMetadataOffset
Definition NanoVDB.h:2449
nanovdb::GridData::mGridIndex
uint32_t mGridIndex
Definition NanoVDB.h:2440
nanovdb::GridData::applyMap
Vec3T applyMap(const Vec3T &xyz) const
Definition NanoVDB.h:2507
nanovdb::GridData::applyInverseMapF
Vec3T applyInverseMapF(const Vec3T &xyz) const
Definition NanoVDB.h:2520
nanovdb::GridTree< const GridT >::Type
const typename GridT::TreeType Type
Definition NanoVDB.h:2792
nanovdb::GridTree< const GridT >::type
const typename GridT::TreeType type
Definition NanoVDB.h:2793
nanovdb::GridTree
defines a tree type from a grid type while preserving constness
Definition NanoVDB.h:2785
nanovdb::GridTree::Type
typename GridT::TreeType Type
Definition NanoVDB.h:2786
nanovdb::GridTree::type
typename GridT::TreeType type
Definition NanoVDB.h:2787
nanovdb::InternalData
Struct with all the member data of the InternalNode (useful during serialization of an openvdb Intern...
Definition NanoVDB.h:3420
nanovdb::InternalData::setOrigin
void setOrigin(const T &ijk)
Definition NanoVDB.h:3501
nanovdb::InternalData::mAverage
StatsT mAverage
Definition NanoVDB.h:3446
nanovdb::InternalData::CoordT
typename ChildT::CoordType CoordT
Definition NanoVDB.h:3424
nanovdb::InternalData::setChild
void setChild(uint32_t n, const void *ptr)
Definition NanoVDB.h:3461
nanovdb::InternalData::~InternalData
~InternalData()=delete
nanovdb::InternalData::mChildMask
MaskT mChildMask
Definition NanoVDB.h:3442
nanovdb::InternalData::setValue
void setValue(uint32_t n, const ValueT &v)
Definition NanoVDB.h:3468
nanovdb::InternalData::InternalData
InternalData(const InternalData &)=delete
nanovdb::InternalData::getMax
const ValueT & getMax() const
Definition NanoVDB.h:3504
nanovdb::InternalData::setDev
void setDev(const StatsT &v)
Definition NanoVDB.h:3511
nanovdb::InternalData::getChild
const ChildT * getChild(uint32_t n) const
Definition NanoVDB.h:3480
nanovdb::InternalData::isActive
bool isActive(uint32_t n) const
Definition NanoVDB.h:3492
nanovdb::InternalData::setMin
void setMin(const ValueT &v)
Definition NanoVDB.h:3508
nanovdb::InternalData::StatsT
typename ChildT::FloatType StatsT
Definition NanoVDB.h:3423
nanovdb::InternalData::isChild
bool isChild(uint32_t n) const
Definition NanoVDB.h:3498
nanovdb::InternalData::BuildT
typename ChildT::BuildType BuildT
Definition NanoVDB.h:3422
nanovdb::InternalData::getValue
ValueT getValue(uint32_t n) const
Definition NanoVDB.h:3486
nanovdb::InternalData::padding
static constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:3453
nanovdb::InternalData::getMin
const ValueT & getMin() const
Definition NanoVDB.h:3503
nanovdb::InternalData::setMax
void setMax(const ValueT &v)
Definition NanoVDB.h:3509
nanovdb::InternalData::mStdDevi
StatsT mStdDevi
Definition NanoVDB.h:3447
nanovdb::InternalData::mBBox
BBox< CoordT > mBBox
Definition NanoVDB.h:3439
nanovdb::InternalData::getChild
ChildT * getChild(uint32_t n)
Returns a pointer to the child node at the specifed linear offset.
Definition NanoVDB.h:3475
nanovdb::InternalData::mMaximum
ValueT mMaximum
Definition NanoVDB.h:3445
nanovdb::InternalData::stdDeviation
const StatsT & stdDeviation() const
Definition NanoVDB.h:3506
nanovdb::InternalData::memUsage
static uint64_t memUsage()
Definition NanoVDB.h:3459
nanovdb::InternalData::average
const StatsT & average() const
Definition NanoVDB.h:3505
nanovdb::InternalData::mValueMask
MaskT mValueMask
Definition NanoVDB.h:3441
nanovdb::InternalData::MaskT
typename ChildT::template MaskType< LOG2DIM > MaskT
Definition NanoVDB.h:3425
nanovdb::InternalData::operator=
InternalData & operator=(const InternalData &)=delete
nanovdb::InternalData::setAvg
void setAvg(const StatsT &v)
Definition NanoVDB.h:3510
nanovdb::InternalData::ValueT
typename ChildT::ValueType ValueT
Definition NanoVDB.h:3421
nanovdb::InternalData::mMinimum
ValueT mMinimum
Definition NanoVDB.h:3444
nanovdb::InternalData::InternalData
InternalData()=delete
This class cannot be constructed or deleted.
nanovdb::InternalData::mFlags
uint64_t mFlags
Definition NanoVDB.h:3440
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::bitWidth
static constexpr uint8_t bitWidth()
Definition NanoVDB.h:4012
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::~LeafData
~LeafData()=delete
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::getValue
float getValue(uint32_t i) const
Definition NanoVDB.h:4013
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::padding
static constexpr uint32_t padding()
Definition NanoVDB.h:4007
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData< Fp16, CoordT, MaskT, LOG2DIM >::memUsage
static constexpr uint64_t memUsage()
Definition NanoVDB.h:4006
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::bitWidth
static constexpr uint8_t bitWidth()
Definition NanoVDB.h:3951
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::~LeafData
~LeafData()=delete
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::getValue
float getValue(uint32_t i) const
Definition NanoVDB.h:3952
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::padding
static constexpr uint32_t padding()
Definition NanoVDB.h:3946
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData< Fp4, CoordT, MaskT, LOG2DIM >::memUsage
static constexpr uint64_t memUsage()
Definition NanoVDB.h:3945
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::bitWidth
static constexpr uint8_t bitWidth()
Definition NanoVDB.h:3984
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::~LeafData
~LeafData()=delete
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::getValue
float getValue(uint32_t i) const
Definition NanoVDB.h:3985
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::padding
static constexpr uint32_t padding()
Definition NanoVDB.h:3979
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::memUsage
static constexpr int64_t memUsage()
Definition NanoVDB.h:3978
nanovdb::LeafData< Fp8, CoordT, MaskT, LOG2DIM >::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::memUsage
size_t memUsage() const
Definition NanoVDB.h:4039
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::~LeafData
~LeafData()=delete
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::getValue
float getValue(uint32_t i) const
Definition NanoVDB.h:4041
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::bitWidth
uint8_t bitWidth() const
Definition NanoVDB.h:4038
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::padding
static constexpr uint32_t padding()
Definition NanoVDB.h:4033
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData< FpN, CoordT, MaskT, LOG2DIM >::memUsage
static size_t memUsage(uint32_t bitWidth)
Definition NanoVDB.h:4040
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::setOrigin
void setOrigin(const T &ijk)
Definition NanoVDB.h:4239
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::setDev
void setDev(const T &dev, T *p)
Definition NanoVDB.h:4237
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::getMax
uint64_t getMax() const
Definition NanoVDB.h:4214
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::~LeafData
~LeafData()=delete
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::mValueOff
uint64_t mValueOff
Definition NanoVDB.h:4204
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::mFlags
uint8_t mFlags
Definition NanoVDB.h:4200
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::getValue
uint64_t getValue(uint32_t i) const
Definition NanoVDB.h:4222
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::mValueMask
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:4202
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::mBBoxMin
CoordT mBBoxMin
Definition NanoVDB.h:4198
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::padding
static constexpr uint32_t padding()
Definition NanoVDB.h:4207
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::setValue
void setValue(uint32_t offset, uint64_t)
Definition NanoVDB.h:4217
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::setMax
void setMax(const T &max, T *p)
Definition NanoVDB.h:4233
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::memUsage
static uint64_t memUsage()
Definition NanoVDB.h:4211
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::setMin
void setMin(const T &min, T *p)
Definition NanoVDB.h:4231
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::getAvg
uint64_t getAvg() const
Definition NanoVDB.h:4215
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::getDev
uint64_t getDev() const
Definition NanoVDB.h:4216
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::mStatsOff
uint64_t mStatsOff
Definition NanoVDB.h:4203
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::setAvg
void setAvg(const T &avg, T *p)
Definition NanoVDB.h:4235
nanovdb::LeafData< ValueIndex, CoordT, MaskT, LOG2DIM >::getMin
uint64_t getMin() const
Definition NanoVDB.h:4213
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::setOrigin
void setOrigin(const T &ijk)
Definition NanoVDB.h:4177
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::getDev
bool getDev() const
Definition NanoVDB.h:4165
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::getMin
bool getMin() const
Definition NanoVDB.h:4162
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::~LeafData
~LeafData()=delete
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::setMax
void setMax(const ValueType &)
Definition NanoVDB.h:4172
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::getValue
bool getValue(uint32_t i) const
Definition NanoVDB.h:4161
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::mFlags
uint8_t mFlags
Definition NanoVDB.h:4150
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::getMax
bool getMax() const
Definition NanoVDB.h:4163
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::setDev
void setDev(const FloatType &)
Definition NanoVDB.h:4174
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::getAvg
bool getAvg() const
Definition NanoVDB.h:4164
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::mValueMask
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:4151
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::setValue
void setValue(uint32_t offset, bool)
Definition NanoVDB.h:4166
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::mBBoxMin
CoordT mBBoxMin
Definition NanoVDB.h:4148
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::padding
static constexpr uint32_t padding()
Definition NanoVDB.h:4156
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::setAvg
void setAvg(const FloatType &)
Definition NanoVDB.h:4173
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::memUsage
static uint64_t memUsage()
Definition NanoVDB.h:4154
nanovdb::LeafData< ValueMask, CoordT, MaskT, LOG2DIM >::setMin
void setMin(const ValueType &)
Definition NanoVDB.h:4171
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::setOrigin
void setOrigin(const T &ijk)
Definition NanoVDB.h:4127
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::getDev
bool getDev() const
Definition NanoVDB.h:4114
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::setMin
void setMin(const bool &)
Definition NanoVDB.h:4121
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::getMin
bool getMin() const
Definition NanoVDB.h:4111
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::setMax
void setMax(const bool &)
Definition NanoVDB.h:4122
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::~LeafData
~LeafData()=delete
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::setValue
void setValue(uint32_t offset, bool v)
Definition NanoVDB.h:4115
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::getValue
bool getValue(uint32_t i) const
Definition NanoVDB.h:4110
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::mFlags
uint8_t mFlags
Definition NanoVDB.h:4101
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::getMax
bool getMax() const
Definition NanoVDB.h:4112
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::getAvg
bool getAvg() const
Definition NanoVDB.h:4113
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::mValueMask
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:4102
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::mValues
MaskT< LOG2DIM > mValues
Definition NanoVDB.h:4103
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::mBBoxMin
CoordT mBBoxMin
Definition NanoVDB.h:4099
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::padding
static constexpr uint32_t padding()
Definition NanoVDB.h:4106
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::setDev
void setDev(const bool &)
Definition NanoVDB.h:4124
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::memUsage
static uint64_t memUsage()
Definition NanoVDB.h:4107
nanovdb::LeafData< bool, CoordT, MaskT, LOG2DIM >::setAvg
void setAvg(const bool &)
Definition NanoVDB.h:4123
nanovdb::LeafData
Stuct with all the member data of the LeafNode (useful during serialization of an openvdb LeafNode)
Definition NanoVDB.h:3812
nanovdb::LeafData::setOrigin
void setOrigin(const T &ijk)
Definition NanoVDB.h:3862
nanovdb::LeafData::mMaximum
ValueType mMaximum
Definition NanoVDB.h:3827
nanovdb::LeafData::getDev
FloatType getDev() const
Definition NanoVDB.h:3854
nanovdb::LeafData::FloatType
typename FloatTraits< ValueT >::FloatType FloatType
Definition NanoVDB.h:3817
nanovdb::LeafData::~LeafData
~LeafData()=delete
nanovdb::LeafData::setMin
void setMin(const ValueType &v)
Definition NanoVDB.h:3856
nanovdb::LeafData::setMax
void setMax(const ValueType &v)
Definition NanoVDB.h:3857
nanovdb::LeafData::mAverage
FloatType mAverage
Definition NanoVDB.h:3828
nanovdb::LeafData::setDev
void setDev(const FloatType &v)
Definition NanoVDB.h:3859
nanovdb::LeafData::mFlags
uint8_t mFlags
Definition NanoVDB.h:3823
nanovdb::LeafData::operator=
LeafData & operator=(const LeafData &)=delete
nanovdb::LeafData::LeafData
LeafData(const LeafData &)=delete
nanovdb::LeafData::getMin
ValueType getMin() const
Definition NanoVDB.h:3851
nanovdb::LeafData::getValue
ValueType getValue(uint32_t i) const
Definition NanoVDB.h:3843
nanovdb::LeafData::setValue
void setValue(uint32_t offset, const ValueType &value)
Definition NanoVDB.h:3845
nanovdb::LeafData::ValueType
ValueT ValueType
Definition NanoVDB.h:3815
nanovdb::LeafData::mValueMask
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:3824
nanovdb::LeafData::setValueOnly
void setValueOnly(uint32_t offset, const ValueType &value)
Definition NanoVDB.h:3844
nanovdb::LeafData::mBBoxMin
CoordT mBBoxMin
Definition NanoVDB.h:3821
nanovdb::LeafData::padding
static constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:3835
nanovdb::LeafData::getMax
ValueType getMax() const
Definition NanoVDB.h:3852
nanovdb::LeafData::LeafData
LeafData()=delete
This class cannot be constructed or deleted.
nanovdb::LeafData::ArrayType
ValueT ArrayType
Definition NanoVDB.h:3818
nanovdb::LeafData::getAvg
FloatType getAvg() const
Definition NanoVDB.h:3853
nanovdb::LeafData::memUsage
static uint64_t memUsage()
Definition NanoVDB.h:3840
nanovdb::LeafData::mMinimum
ValueType mMinimum
Definition NanoVDB.h:3826
nanovdb::LeafData::setAvg
void setAvg(const FloatType &v)
Definition NanoVDB.h:3858
nanovdb::LeafData::BuildType
ValueT BuildType
Definition NanoVDB.h:3816
nanovdb::LeafData::mStdDevi
FloatType mStdDevi
Definition NanoVDB.h:3829
nanovdb::LeafFnBase
Base-class for quantized float leaf nodes.
Definition NanoVDB.h:3874
nanovdb::LeafFnBase::setOrigin
void setOrigin(const T &ijk)
Definition NanoVDB.h:3929
nanovdb::LeafFnBase::getMin
float getMin() const
return the quantized minimum of the active values in this node
Definition NanoVDB.h:3904
nanovdb::LeafFnBase::setDev
void setDev(float dev)
Definition NanoVDB.h:3926
nanovdb::LeafFnBase::setMin
void setMin(float min)
Definition NanoVDB.h:3917
nanovdb::LeafFnBase::getAvg
float getAvg() const
return the quantized average of the active values in this node
Definition NanoVDB.h:3910
nanovdb::LeafFnBase::mFlags
uint8_t mFlags
Definition NanoVDB.h:3882
nanovdb::LeafFnBase::mQuantum
float mQuantum
Definition NanoVDB.h:3886
nanovdb::LeafFnBase::mValueMask
MaskT< LOG2DIM > mValueMask
Definition NanoVDB.h:3883
nanovdb::LeafFnBase::init
void init(float min, float max, uint8_t bitWidth)
Definition NanoVDB.h:3897
nanovdb::LeafFnBase::mAvg
uint16_t mAvg
Definition NanoVDB.h:3887
nanovdb::LeafFnBase::mBBoxMin
CoordT mBBoxMin
Definition NanoVDB.h:3880
nanovdb::LeafFnBase::padding
static constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:3894
nanovdb::LeafFnBase::mMinimum
float mMinimum
Definition NanoVDB.h:3885
nanovdb::LeafFnBase::setMax
void setMax(float max)
Definition NanoVDB.h:3920
nanovdb::LeafFnBase::setAvg
void setAvg(float avg)
Definition NanoVDB.h:3923
nanovdb::LeafFnBase::memUsage
static uint64_t memUsage()
Definition NanoVDB.h:3889
nanovdb::LeafFnBase::getDev
float getDev() const
return the quantized standard deviation of the active values in this node
Definition NanoVDB.h:3914
nanovdb::LeafFnBase::getMax
float getMax() const
return the quantized maximum of the active values in this node
Definition NanoVDB.h:3907
nanovdb::LeafNode::ChildNodeType
Definition NanoVDB.h:4257
nanovdb::LeafNode::ChildNodeType::dim
static uint32_t dim()
Definition NanoVDB.h:4260
nanovdb::Map
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:2226
nanovdb::Map::mTaperD
double mTaperD
Definition NanoVDB.h:2234
nanovdb::Map::applyInverseJacobianF
Vec3T applyInverseJacobianF(const Vec3T &xyz) const
Definition NanoVDB.h:2272
nanovdb::Map::applyIJTF
Vec3T applyIJTF(const Vec3T &xyz) const
Definition NanoVDB.h:2277
nanovdb::Map::applyIJT
Vec3T applyIJT(const Vec3T &xyz) const
Definition NanoVDB.h:2275
nanovdb::Map::applyJacobianF
Vec3T applyJacobianF(const Vec3T &xyz) const
Definition NanoVDB.h:2256
nanovdb::Map::applyInverseJacobian
Vec3T applyInverseJacobian(const Vec3T &xyz) const
Definition NanoVDB.h:2270
nanovdb::Map::set
void set(const Mat4T &mat, const Mat4T &invMat, double taper)
Initialize the member data.
Definition NanoVDB.h:2243
nanovdb::Map::applyMapF
Vec3T applyMapF(const Vec3T &xyz) const
Definition NanoVDB.h:2251
nanovdb::Map::applyInverseMap
Vec3T applyInverseMap(const Vec3T &xyz) const
Definition NanoVDB.h:2259
nanovdb::Map::applyJacobian
Vec3T applyJacobian(const Vec3T &xyz) const
Definition NanoVDB.h:2254
nanovdb::Map::applyMap
Vec3T applyMap(const Vec3T &xyz) const
Definition NanoVDB.h:2249
nanovdb::Map::applyInverseMapF
Vec3T applyInverseMapF(const Vec3T &xyz) const
Definition NanoVDB.h:2264
nanovdb::Map::mTaperF
float mTaperF
Definition NanoVDB.h:2230
nanovdb::Maximum
Maximum floating-point values.
Definition NanoVDB.h:745
nanovdb::Maximum::value
static T value()
Definition NanoVDB.h:746
nanovdb::NanoNode
Trait to map from LEVEL to node type.
Definition NanoVDB.h:4569
nanovdb::NodeTrait< GridOrTreeOrRootT, 0 >::type
typename GridOrTreeOrRootT::LeafNodeType type
Definition NanoVDB.h:2353
nanovdb::NodeTrait< GridOrTreeOrRootT, 0 >::Type
typename GridOrTreeOrRootT::LeafNodeType Type
Definition NanoVDB.h:2352
nanovdb::NodeTrait< GridOrTreeOrRootT, 1 >::Type
typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType Type
Definition NanoVDB.h:2367
nanovdb::NodeTrait< GridOrTreeOrRootT, 1 >::type
typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType type
Definition NanoVDB.h:2368
nanovdb::NodeTrait< GridOrTreeOrRootT, 2 >::Type
typename GridOrTreeOrRootT::RootType::ChildNodeType Type
Definition NanoVDB.h:2381
nanovdb::NodeTrait< GridOrTreeOrRootT, 2 >::type
typename GridOrTreeOrRootT::RootType::ChildNodeType type
Definition NanoVDB.h:2382
nanovdb::NodeTrait< GridOrTreeOrRootT, 3 >::type
typename GridOrTreeOrRootT::RootType type
Definition NanoVDB.h:2396
nanovdb::NodeTrait< GridOrTreeOrRootT, 3 >::Type
typename GridOrTreeOrRootT::RootType Type
Definition NanoVDB.h:2395
nanovdb::NodeTrait< const GridOrTreeOrRootT, 0 >::Type
const typename GridOrTreeOrRootT::LeafNodeType Type
Definition NanoVDB.h:2359
nanovdb::NodeTrait< const GridOrTreeOrRootT, 0 >::type
const typename GridOrTreeOrRootT::LeafNodeType type
Definition NanoVDB.h:2360
nanovdb::NodeTrait< const GridOrTreeOrRootT, 1 >::Type
const typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType Type
Definition NanoVDB.h:2374
nanovdb::NodeTrait< const GridOrTreeOrRootT, 1 >::type
const typename GridOrTreeOrRootT::RootType::ChildNodeType::ChildNodeType type
Definition NanoVDB.h:2375
nanovdb::NodeTrait< const GridOrTreeOrRootT, 2 >::type
const typename GridOrTreeOrRootT::RootType::ChildNodeType type
Definition NanoVDB.h:2389
nanovdb::NodeTrait< const GridOrTreeOrRootT, 2 >::Type
const typename GridOrTreeOrRootT::RootType::ChildNodeType Type
Definition NanoVDB.h:2388
nanovdb::NodeTrait< const GridOrTreeOrRootT, 3 >::type
const typename GridOrTreeOrRootT::RootType type
Definition NanoVDB.h:2404
nanovdb::NodeTrait< const GridOrTreeOrRootT, 3 >::Type
const typename GridOrTreeOrRootT::RootType Type
Definition NanoVDB.h:2403
nanovdb::NodeTrait
Struct to derive node type from its level in a given grid, tree or root while preserving constness.
Definition NanoVDB.h:2345
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mLevel
uint32_t mLevel
Definition NanoVDB.h:4664
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mMaximum
ValueType mMaximum
Definition NanoVDB.h:4667
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mDim
uint32_t mDim
Definition NanoVDB.h:4665
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mAverage
FloatType mAverage
Definition NanoVDB.h:4668
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mBBoxMax
CoordType mBBoxMax
Definition NanoVDB.h:4671
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mMinimum
ValueType mMinimum
Definition NanoVDB.h:4666
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mBBoxMin
CoordType mBBoxMin
Definition NanoVDB.h:4670
nanovdb::ReadAccessor< BuildT, -1, -1, -1 >::NodeInfo::mStdDevi
FloatType mStdDevi
Definition NanoVDB.h:4669
nanovdb::RootData::Tile
Definition NanoVDB.h:3003
nanovdb::RootData::Tile::value
ValueT value
Definition NanoVDB.h:3025
nanovdb::RootData::Tile::setChild
void setChild(const CoordType &k, const ChildT *ptr, const RootData *data)
Definition NanoVDB.h:3005
nanovdb::RootData::Tile::state
uint32_t state
Definition NanoVDB.h:3024
nanovdb::RootData::Tile::isActive
bool isActive() const
Definition NanoVDB.h:3020
nanovdb::RootData::Tile::key
KeyT key
Definition NanoVDB.h:3022
nanovdb::RootData::Tile::setValue
void setValue(const CoordType &k, bool s, const ValueType &v)
Definition NanoVDB.h:3011
nanovdb::RootData::Tile::origin
CoordT origin() const
Definition NanoVDB.h:3021
nanovdb::RootData::Tile::isValue
bool isValue() const
Definition NanoVDB.h:3019
nanovdb::RootData::Tile::isChild
bool isChild() const
Definition NanoVDB.h:3018
nanovdb::RootData::Tile::child
int64_t child
Definition NanoVDB.h:3023
nanovdb::RootData
Struct with all the member data of the RootNode (useful during serialization of an openvdb RootNode)
Definition NanoVDB.h:2955
nanovdb::RootData::mAverage
StatsT mAverage
Definition NanoVDB.h:2992
nanovdb::RootData::CoordT
typename ChildT::CoordType CoordT
Definition NanoVDB.h:2958
nanovdb::RootData::KeyToCoord
static CoordT KeyToCoord(const KeyT &key)
Definition NanoVDB.h:2974
nanovdb::RootData::getChild
const ChildT * getChild(const Tile *tile) const
Definition NanoVDB.h:3050
nanovdb::RootData::RootData
RootData()=delete
This class cannot be constructed or deleted.
nanovdb::RootData::mBackground
ValueT mBackground
Definition NanoVDB.h:2989
nanovdb::RootData::tile
Tile * tile(uint32_t n)
Definition NanoVDB.h:3036
nanovdb::RootData::tile
const Tile * tile(uint32_t n) const
Returns a non-const reference to the tile at the specified linear offset.
Definition NanoVDB.h:3031
nanovdb::RootData::mTableSize
uint32_t mTableSize
Definition NanoVDB.h:2987
nanovdb::RootData::getMax
const ValueT & getMax() const
Definition NanoVDB.h:3057
nanovdb::RootData::setDev
void setDev(const StatsT &v)
Definition NanoVDB.h:3064
nanovdb::RootData::setMin
void setMin(const ValueT &v)
Definition NanoVDB.h:3061
nanovdb::RootData::StatsT
typename ChildT::FloatType StatsT
Definition NanoVDB.h:2959
nanovdb::RootData::BuildT
typename ChildT::BuildType BuildT
Definition NanoVDB.h:2957
nanovdb::RootData::getChild
ChildT * getChild(const Tile *tile)
Returns a const reference to the child node in the specified tile.
Definition NanoVDB.h:3045
nanovdb::RootData::~RootData
~RootData()=delete
nanovdb::RootData::padding
static constexpr uint32_t padding()
Return padding of this class in bytes, due to aliasing and 32B alignment.
Definition NanoVDB.h:2998
nanovdb::RootData::getMin
const ValueT & getMin() const
Definition NanoVDB.h:3056
nanovdb::RootData::setMax
void setMax(const ValueT &v)
Definition NanoVDB.h:3062
nanovdb::RootData::mStdDevi
StatsT mStdDevi
Definition NanoVDB.h:2993
nanovdb::RootData::RootData
RootData(const RootData &)=delete
nanovdb::RootData::CoordToKey
static KeyT CoordToKey(const CoordType &ijk)
Definition NanoVDB.h:2966
nanovdb::RootData::operator=
RootData & operator=(const RootData &)=delete
nanovdb::RootData::mBBox
BBox< CoordT > mBBox
Definition NanoVDB.h:2986
nanovdb::RootData::mMaximum
ValueT mMaximum
Definition NanoVDB.h:2991
nanovdb::RootData::stdDeviation
const StatsT & stdDeviation() const
Definition NanoVDB.h:3059
nanovdb::RootData::average
const StatsT & average() const
Definition NanoVDB.h:3058
nanovdb::RootData::setAvg
void setAvg(const StatsT &v)
Definition NanoVDB.h:3063
nanovdb::RootData::ValueT
typename ChildT::ValueType ValueT
Definition NanoVDB.h:2956
nanovdb::RootData::mMinimum
ValueT mMinimum
Definition NanoVDB.h:2990
nanovdb::TensorTraits< T, 0 >::scalar
static T scalar(const T &s)
Definition NanoVDB.h:1438
nanovdb::TensorTraits< T, 1 >::scalar
static ElementType scalar(const T &v)
Definition NanoVDB.h:1449
nanovdb::TensorTraits< T, 1 >::ElementType
typename T::ValueType ElementType
Definition NanoVDB.h:1448
nanovdb::TensorTraits
Definition NanoVDB.h:1428
nanovdb::Tolerance< double >::value
static double value()
Definition NanoVDB.h:697
nanovdb::Tolerance< float >::value
static float value()
Definition NanoVDB.h:692
nanovdb::Tolerance
Tolerance for floating-point comparison.
Definition NanoVDB.h:688
nanovdb::TreeData
Definition NanoVDB.h:2759
nanovdb::TreeData::getRoot
const RootT * getRoot() const
Definition NanoVDB.h:2771
nanovdb::TreeData::setFirstNode
void setFirstNode(const NodeT *node)
Definition NanoVDB.h:2774
nanovdb::TreeData::getRoot
RootT * getRoot()
Definition NanoVDB.h:2769
nanovdb::TreeData::setRoot
void setRoot(const RootT *root)
Definition NanoVDB.h:2767
nanovdb::TreeData::mVoxelCount
uint64_t mVoxelCount
Definition NanoVDB.h:2764
nanovdb::enable_if
C++11 implementation of std::enable_if.
Definition NanoVDB.h:372
nanovdb::is_const
Definition NanoVDB.h:385
nanovdb::is_const::value
static constexpr bool value
Definition NanoVDB.h:386
nanovdb::is_floating_point
C++11 implementation of std::is_floating_point.
Definition NanoVDB.h:414
nanovdb::is_floating_point::value
static const bool value
Definition NanoVDB.h:415
nanovdb::is_same
C++11 implementation of std::is_same.
Definition NanoVDB.h:357
nanovdb::is_same::value
static constexpr bool value
Definition NanoVDB.h:358
nanovdb::is_specialization
Metafunction used to determine if the first template parameter is a specialization of the class templ...
Definition NanoVDB.h:427
nanovdb::is_specialization::value
static const bool value
Definition NanoVDB.h:428
nanovdb::remove_const
Definition NanoVDB.h:399
nanovdb::InternalData::Tile
Definition NanoVDB.h:3429
nanovdb::InternalData::Tile::value
ValueT value
Definition NanoVDB.h:3430
nanovdb::InternalData::Tile::Tile
Tile(const Tile &)=delete
nanovdb::InternalData::Tile::operator=
Tile & operator=(const Tile &)=delete
nanovdb::InternalData::Tile::~Tile
~Tile()=delete
nanovdb::InternalData::Tile::Tile
Tile()=delete
This class cannot be constructed or deleted.
nanovdb::InternalData::Tile::child
int64_t child
Definition NanoVDB.h:3431