OpenVDB: nanovdb/NanoVDB.h Source File

OpenVDB 10.0.1

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