/** @mainpage OpenVDB The @b OpenVDB library comprises a hierarchical data structure and a suite of tools for the efficient manipulation of sparse, possibly time-varying, volumetric data discretized on a three-dimensional grid. It is based on VDB, which was developed by Ken Museth at DreamWorks Animation, and it offers an effectively infinite 3D index space, compact storage (both in memory and on disk), fast data access (both random and sequential), and a collection of algorithms specifically optimized for the data structure for common tasks such as filtering, CSG, compositing, sampling and voxelization from other geometric representations. The technical details of VDB are described in the paper “VDB: High-Resolution Sparse Volumes with Dynamic Topology”. @b OpenVDB is maintained by the Academy Software Foundation (ASWF). It was originally developed at DreamWorks Animation, primarily by - Ken Museth - Peter Cucka - Mihai Aldén - David Hill See the @subpage changes "Release Notes" for what’s new in this version of @b OpenVDB. See the @subpage dependencies "Dependencies" page for @b OpenVDB requirements. See @subpage build "Building OpenVDB" for information on building @b OpenVDB. See the @subpage overview "Overview" for an introduction to the library. See @subpage transformsAndMaps "Transforms and Maps" for more discussion of the transforms used in @b OpenVDB. See the @subpage faq "FAQ" for frequently asked questions about @b OpenVDB. See the @subpage codeExamples "Cookbook" to get started using @b OpenVDB. See @subpage points "OpenVDB Points" to store point data using @b OpenVDB. See @subpage python "Using OpenVDB in Python" to get started with the @b OpenVDB Python module. @if OPENVDB_AX See @subpage openvdbax "OpenVDB AX" for the AX documentation. @endif @if OPENVDB_HOUDINI See the @subpage houdini "Houdini Cookbook" for help on implementing Houdini nodes. @endif @if NANOVDB See @subpage NanoVDB_MainPage "NanoVDB" for the NanoVDB documentation. @endif Contributors, please familiarize yourselves with our @subpage codingStyle "coding standards". @page overview OpenVDB Overview @section Contents - @ref secOverview - @ref secTree - @ref subsecTreeConfig - @ref secSparsity - @ref subsecValues - @ref subsecInactive - @ref secSpaceAndTrans - @ref subsecVoxSpace - @ref subsecWorSpace - @ref subsecTrans - @ref secGrid - @ref secToolUtils - @ref secIterator - @ref subsecTreeIter - @ref subsecNodeIter - @ref subsecValueAccessor - @ref subsecTraversal @section secOverview Introduction This document is a high-level summary of the terminology and basic components of the OpenVDB library and is organized around two key motivating concepts. First, OpenVDB is designed specifically to work efficiently with sparse volumetric data locally sampled at a high spatial frequency, although it will function well for dense volumetric data. From this follows the need for a memory efficient representation of this sparsity and the need for fast iterators (and other tools) that respect sparsity. Second, data storage is separated from data interpretation. OpenVDB uses unit-less three-dimensional integer coordinates to address the sparse data, but introduces a unit-less continuous index space for interpolation, along with a transform to place the data in physical space. When manipulating data in OpenVDB, the three essential objects are (1) the @vdblink::tree::Tree Tree@endlink, a B-tree-like three-dimensional data structure; (2) the @vdblink::math::Transform Transform@endlink, which relates voxel indices @ijk to physical locations @xyz in @ref subsecWorSpace “world” space; and (3) the @vdblink::Grid Grid@endlink, a container that associates a @b Tree with a @b Transform and additional metadata. For instancing purposes (i.e., placing copies of the same volume in multiple locations), the same tree may be referenced (via smart pointers) by several different Grids, each having a unique transform. We now proceed to discuss the @b Tree and ideas of sparsity in some detail, followed by a briefer description of the different spaces and transforms as well as some of the tools that act on the sparse data. @section secTree The Tree In OpenVDB the @b Tree data structure exists to answer the question What value is stored at location @ijk in three-dimensional index space? Here i, j and k are arbitrary signed 32-bit integers, and the data type of the associated value (float, bool, vector, etc.) is the same for all @ijk. While the @b Tree serves the same purpose as a large three-dimensional array, it is a specially designed data structure that, given sparse unique values, minimizes the overall memory footprint while retaining fast access times. This is accomplished, as the name suggests, via a tree-based acceleration structure comprising a @vdblink::tree::RootNode RootNode@endlink, @vdblink::tree::LeafNode LeafNode@endlinks and usually one or more levels of @vdblink::tree::InternalNode InternalNode@endlinks with prescribed branching factors. @subsection subsecTreeConfig Tree Configuration The tree-based acceleration structure can be configured in various ways, but with the restriction that for a given tree all the LeafNodes are at the same depth. Conceptually, the @b RootNode and InternalNodes increasingly subdivide the three-dimensional index space, and the LeafNodes hold the actual unique voxels. The type of a @b Tree encodes both the type of the data to be stored in the tree (float, bool, etc.) and the tree’s node configuration. In practice a four-level (root, internal, internal, leaf) configuration is standard, and several common tree types are defined in openvdb.h. For example, @code using FloatTree = tree::Tree4::Type; using BoolTree = tree::Tree4::Type; @endcode These predefined tree types share the same branching factors, which dictate the number of children of a given node. The branching factors (5, 4, 3) are specified as base two logarithms and should be read backwards from the leaf nodes up the tree. In the default tree configuration, each @b LeafNode holds a three-dimensional grid of 23 voxels on a side (i.e., an 8×8×8 voxel grid). Internally, the @b LeafNode is said to be at “level 0” of the tree. At “level 1” of this tree is the first @b InternalNode, and it indexes a 24×24×24 = 16×16×16 grid, each entry of which is either a @b LeafNode or a constant value that represents an 8×8×8 block of voxels. At “level 2” is the second @b InternalNode in this configuration; it in turn indexes a 25×25×25 = 32×32×32 grid of level-1 InternalNodes and/or values, and so the @b InternalNode at level 2 subsumes a three-dimensional block of voxels of size 32×16×8 = 4096 on a side. Unlike the InternalNodes and LeafNodes, the @b RootNode (“level 3” for the default configuration) is not explicitly restricted in the number of children it may have, so the overall index space is limited only by the range of the integer indices, which are 32-bit by default. @section secSparsity Sparse Values and Voxels Like a tree’s node configuration, the type of data held by a tree is determined at compile time. Conceptually the tree itself employs two different notions of data sparsity to reduce the memory footprint and at the same time accelerate access to its contents. The first is largely hidden from the user and concerns ways in which large regions of uniform values are compactly represented, and the second allows for fast sequential iteration, skipping user-specified “uninteresting” regions (that may or may not have uniform values). @subsection subsecValues Tile, Voxel, and Background Values Although the data in a tree is accessed and set on a per-voxel level (i.e., the value at @ijk) it need not be internally stored in that way. To reduce the memory footprint and accelerate data access, data values are stored in three distinct forms internal to the tree: voxel values, tile values, and a background value. A voxel value is a unique value indexed by the location of a voxel and is stored in the @b LeafNode responsible for that voxel. A tile value is a uniform value assigned to all voxels subsumed by a given node. (For example, a tile Value belonging to an @b InternalNode at level 1 is equivalent to a constant-value cube of voxels of the same size, 8×8×8, as a @b LeafNode.) The tile value is returned when a request is made for the data associated with any @ijk location within the uniform tile. The background value is a unique value (stored at the root level) that is returned when accessing any @ijk location that does not resolve to either a tile or a @b LeafNode. @subsection subsecInactive Active and Inactive Voxels Any voxel or tile can be classified as either @b active or @b inactive. The interpretation of this state is application-specific, but generally active voxels are “interesting” and inactive somehow less so. The locations of active values may be sparse in the overall voxel topology, and OpenVDB provides @ref secIterator "iterators" that access active values only (as well as iterators over inactive values, all values, and general topology). An example of active vs. inactive: the voxels used to store the distance values of a narrow-band level set (i.e., close to a given surface) will be marked as active while the other (“far”) voxel locations will be marked as inactive and will generally represent regions of space with constant distance values (e.g., two constant distance values of opposite sign to distinguish the enclosed inside region from the infinite outside or background embedding). The @vdblink::tree::Tree::prune() prune@endlink method replaces with tile values any nodes that subsume voxels with the same values and active states. The resulting tree represents the same volume, but more sparsely. @section secSpaceAndTrans Coordinate Systems and Transforms The sampled data in the tree is accessed using signed index coordinates @ijk, but associating each indicial coordinate with a specific physical location is the job of a @b Transform. A simple linear transform assumes a lattice-like structure with a fixed physical distance Δ between indices, so that @xyz = (Δi, Δj, Δk). @subsection subsecVoxSpace Index Space To simplify transformations between physical space and lattice index coordinates, a continuous generalization of the index lattice points called index space is used. For example, index space coordinate (1.0, 1.0, 1.0) corresponds to the same point as (1,1,1) in the index lattice, but (1.5,1.0,1.0) also has meaning as halfway between the index coordinates (1,1,1) and (2,1,1). Index space can be used in constructing interpolated data values: given an arbitrary location in physical space, one can use a transform to compute the point in index space (which need not fall on an exact integer index) that maps to that location and locally interpolate from values with neighboring index coordinates. @subsection subsecWorSpace World Space The interpretation of the data in a tree takes place in world space. For example, the tree might hold data sampled at discrete physical locations in world space. @b Transform methods such as @vdblink::math::Transform::indexToWorld() indexToWorld@endlink and its inverse @vdblink::math::Transform::worldToIndex() worldToIndex@endlink may be used to relate coordinates in the two continuous spaces. In addition, methods such as @vdblink::math::Transform::worldToIndexCellCentered() worldToIndexCellCentered@endlink actually return lattice points. @subsection subsecTrans Transforms and Maps A @vdblink::math::Transform Transform @endlink provides a context for interpreting the information held in a tree by associating a location in world space with each entry in the tree. The actual implementation of the @b Transform is managed by a @vdblink::math::MapBase Map@endlink object, which is an encapsulation of a continuous, mostly invertible function of three variables. A @b Map is required to provide @vdblink::math::MapBase::applyMap() applyMap@endlink and @vdblink::math::MapBase::applyInverseMap() applyInverseMap@endlink methods to relate locations in its domain to its range and vice versa. A @b Map is also required to provide information about its local derivatives. For more on these classes, see the @subpage transformsAndMaps "Transforms and Maps" page. @section secGrid The Grid For many applications, it might not be necessary ever to operate directly on trees, though there are often significant performance improvements to be gained by exploiting the tree structure. The @vdblink::Grid Grid@endlink, however, is the preferred interface through which to manage voxel data, in part because a grid associates with a tree additional and often necessary information that is not accessible through the tree itself. A @vdblink::Grid Grid@endlink contains smart pointers to a @vdblink::tree::Tree Tree@endlink object and a @vdblink::math::Transform Transform@endlink object, either or both of which might be shared with other grids. As mentioned above, the transform provides for the interpretation of voxel locations. Other grid metadata, notably the grid class, the vector type and the world space/local space toggle, affect the interpretation of voxel values. OpenVDB is particularly well-suited (though by no means exclusively so) to the representation of narrow-band level sets and fog volumes. A narrow-band level set is represented by three distinct regions of voxels: an @b outside (or background) region of inactive voxels having a constant, positive distance from the level set surface; an @b inside region of inactive voxels having a constant, negative distance; and a thin band of active voxels (normally three voxels wide on either side of the surface) whose values are signed distances. Similarly, a fog volume is represented by an outside region of inactive voxels with value zero, an inside region of active voxels with value one, and a thin band of active voxels, with values typically varying linearly between zero and one, that separates the inside from the outside. Identifying a grid as a level set or a fog volume, by setting its @vdblink::GridClass grid class@endlink with @vdblink::Grid::setGridClass() setGridClass@endlink, allows tools to invoke alternative implementations that are better-suited or better-optimized for those classes. For example, resampling (in particular, scaling) a level set should normally not be done without updating its signed distance values. The @vdblink::tools::resampleToMatch() resampleToMatch@endlink tool automatically recomputes signed distances for grids that are identified as level sets. (The lower-level @vdblink::tools::GridResampler GridResampler@endlink does not, but it is optimized for level set grids in that it transforms only voxels in the narrow band and relies on @vdblink::Grid::signedFloodFill() signed flood fill@endlink to reconstruct the inside and outside regions.) Other tools whose behavior is affected by the grid class include the @vdblink::tools::divergence() divergence@endlink operator (which has an alternative implementation for @ref sStaggered "staggered velocity" grids), the @vdblink::tools::volumeToMesh() volume to mesh@endlink converter, and the @vdblink::tools::fillWithSpheres() sphere packing@endlink tool. In addition, a number of level-set-specific tools, such as the @vdblink::tools::LevelSetTracker level set tracker@endlink, throw exceptions when invoked on grids that are not identified as level sets. It is important, therefore, to set a grid’s class appropriately. When a vector-valued grid is transformed or resampled, it is often necessary for the transform to be applied not just to voxel locations but also to voxel values. By default, grids are identified as “world-space”, meaning that if the grid is vector-valued, its voxel values should be transformed. Alternatively, voxel values of grids identified as “local-space”, via @vdblink::Grid::setIsInWorldSpace() setIsInWorldSpace@endlink, do not undergo transformation. A world-space grid’s @vdblink::VecType vector type@endlink, specified with @vdblink::Grid::setVectorType() setVectorType@endlink, may be invariant, covariant or contravariant, which determines how transforms are applied to the grid’s voxel values (for details see, for example, Covariance and contravariance of vectors [Wikipedia]). The @vdblink::tools::transformVectors() transformVectors@endlink tool can be used to apply a transform to a grid’s voxel values, and it handles all of the supported vector types. A grid can optionally be assigned @vdblink::Grid::setName() name@endlink and @vdblink::Grid::setCreator() creator@endlink strings. These are purely informational, though it might be desirable to name grids so as to easily select which ones to read from files that contain multiple grids. In the absence of grid names, or at least of unique names, OpenVDB’s file I/O routines recognize an ordinal suffix: “[0]” refers to the first unnamed grid, “[1]” refers to the second, and so on, and “density[0]” and “density[1]” refer to the first and second grids named “density”. Also of interest for file I/O is a grid’s “@vdblink::Grid::setSaveFloatAsHalf() save float as half@endlink” setting, which allows it to be written more compactly using 16-bit floating point values rather than full-precision values. Finally, during file output certain statistics are computed and stored as per-grid metadata. These include the grid’s index-space active voxel bounding box, its active voxel count and its memory usage in bytes. This information can also be @vdblink::io::File::readAllGridMetadata() retrieved@endlink efficiently from a file. @section secToolUtils Utilities and Tools OpenVDB provides utility functions and classes for the manipulation of grids and the data they hold. Tools such as those found in GridOperators.h compute vector quantities from scalar data or vice-versa. Other tools perform filtering (Filter.h and LevelSetFilter.h) and interpolation (Interpolation.h) as well as sampling (GridTransformer.h), compositing and constructive solid geometry (Composite.h), and other transformations (ValueTransformer.h). OpenVDB also supports advanced finite difference computations through a variety of local support stencils (Stencils.h). @section secIterator Iterators OpenVDB provides efficient, often multithreaded, implementations of a large variety of morphological, filtering and other algorithms that address common data manipulation tasks on three-dimensional grids. For more specialized tasks, OpenVDB provides lower-level data accessors that enable fast iteration over all or selected voxels and over the elements of a @b Tree. These take several forms: iterator classes of various types, functor-based @b visitor methods, and the @vdblink::tree::ValueAccessor ValueAccessor@endlink, an accelerator for indexed @ijk voxel lookups. Iterator classes follow a fairly consistent naming scheme. First, the @b CIter and @b Iter suffixes denote @const and non-@const iterators, i.e., iterators that offer, respectively, read-only and read/write access to the underlying tree or node. Second, iterators over tile and voxel values are denoted either @b On, @b Off or @b All, indicating that they visit only active values, only inactive values, or both active and inactive values. So, for example, @b Tree::ValueOnCIter is a read-only iterator over all active values (both tile and voxel) of a tree, whereas @b LeafNode::ValueAllIter is a read/write iterator over all values, both active and inactive, of a single leaf node. OpenVDB iterators are not STL-compatible in that one can always request an iterator that points to the beginning of a collection of elements (nodes, voxels, etc.), but one usually cannot request an iterator that points to the end of the collection. (This is because finding the end might require a full tree traversal.) Instead, all OpenVDB iterators implement a @b test method that returns @c true as long as the iterator is not exhausted and @c false as soon as it is. Typical usage is as follows: @code using GridType = openvdb::FloatGrid; GridType grid = ...; for (GridType::ValueOnCIter iter = grid.cbeginValueOn(); iter.test(); ++iter) ... @endcode or more compactly @code for (auto iter = grid.cbeginValueOn(); iter; ++iter) ... @endcode Note that the naming scheme for methods that return “begin” iterators closely mirrors that of the iterators themselves. That is, @b Grid::cbeginValueOn returns a @c const iterator to the first of a grid’s active values, whereas @b LeafNode::beginValueAll returns a non-const iterator to the first of a leaf node’s values, both active and inactive. (@c const overloads of begin* methods are usually provided, so that if the @b Grid is itself @c const, Grid::begin* will actually return a @c const iterator. This makes it more convenient to use these methods in templated code.) Finally, note that modifying the tree or node over which one is iterating typically does not invalidate the iterator, though it might first need to be incremented to point to the next existing element (for example, if one deletes a child node to which the iterator is currently pointing). @subsection subsecTreeIter Tree Iterators @anchor treeValueIterRef @par Tree::ValueIter Tree-level value iterators traverse an entire tree, visiting each value (tile or voxel) exactly once. (It is also possible to restrict the traversal to minimum and maximum levels of the tree.) In addition to the methods common to all OpenVDB iterators, such as @b test and @b next, a @b Tree::ValueIter provides methods that return the depth in the tree of the node within which the iterator is pointing (the root node has depth 0) and the @ijk axis-aligned bounding box of the tile or voxel to which it is pointing, and methods to get and set both the value and the active state of the tile or voxel. See the @vdblink::tree::TreeValueIteratorBase TreeValueIteratorBase @endlink class for the complete list. @anchor treeLeafIterRef @par Tree::LeafIter By convention in OpenVDB, voxels in the narrow band of a narrow-band level set are stored only at the leaf level of a tree, so to facilitate the implementation of level set algorithms that operate on narrow-band voxels, OpenVDB provides an iterator that visits each @b LeafNode in a tree exactly once. See the @vdblink::tree::LeafIteratorBase LeafIteratorBase@endlink class for details, and also the related @vdblink::tree::LeafManager LeafManager@endlink acceleration structure. @anchor treeNodeIterRef @par Tree::NodeIter A node iterator traverses a tree in depth-first order, starting from its root, and visits each node exactly once. (It is also possible to restrict the traversal to minimum and maximum node depths—see the @vdblink::tree::NodeIteratorBase NodeIteratorBase @endlink class for details.) Like the tree-level value iterator, the node iterator provides methods that return the depth in the tree of the node to which the iterator is pointing (the root node has depth 0) and the @ijk axis-aligned bounding box of the voxels subsumed by the node and all of its children. @par Naturally, a node iterator also provides access to the node to which it is pointing, but this is complicated somewhat by the fact that nodes of the various types (@b RootNode, @b InternalNode and @b LeafNode) do not inherit from a common base class. For efficiency, OpenVDB generally avoids class inheritance and virtual functions in favor of templates, allowing the compiler to optimize away function calls. In particular, each node type is templated on the type of its children, so even two InternalNodes at different levels of a tree have distinct types. As a result, it is necessary to know the type of the node to which a node iterator is pointing in order to request access to that node. See the @ref sNodeIterator "Cookbook" for an example of how to do this. @subsection subsecNodeIter Node Iterators Less commonly used than tree-level iterators (but found in the implementations of some of the narrow-band level set algorithms referred to @ref treeLeafIterRef "above") are node-level iterators. A node value iterator visits the values (active, inactive or both) stored in a single @b RootNode, @b InternalNode or @b LeafNode, whereas a node child iterator visits the children of a single root or internal node. (Recall that non-leaf nodes store either a tile value or a child node at each grid position.) @subsection subsecValueAccessor Value Accessor When traversing a grid by @ijk index in a spatially coherent pattern, such as when iterating over neighboring voxels, request a @vdblink::tree::ValueAccessor ValueAccessor@endlink from the grid (with @vdblink::Grid::getAccessor() Grid::getAccessor@endlink) and use the accessor’s @vdblink::tree::ValueAccessor::getValue() getValue@endlink and @vdblink::tree::ValueAccessor::setValue() setValue@endlink methods, since these will usually be significantly faster (a factor of three is typical) than accessing voxels directly in the grid’s tree. The accessor records the sequence of nodes visited during the most recent access; on the next access, rather than traversing the tree from the root node down, it performs an inverted traversal from the deepest recorded node up. For neighboring voxels, the traversal need only proceed as far as the voxels’ common ancestor node, which more often than not is the first node in the sequence. Multiple accessors may be associated with a single grid. In fact, for multithreaded, read-only access to a grid, it is recommended that each thread be assigned its own accessor. A thread-safe, mutex-locked accessor is provided (see @vdblink::tree::ValueAccessorRW ValueAccessorRW@endlink), but the locking negates much of the performance benefit of inverted traversal; and because it is the accessor object that is thread-safe, not the grid, concurrent reads and writes are not safe unless all threads share a single accessor. All accessors associated with a grid must be cleared after any operation that removes nodes from the grid’s tree, such as pruning, CSG or compositing. For those and other built-in operations, this is done automatically via a callback mechanism, but developers must be careful to call @vdblink::tree::Tree::clearAllAccessors() Tree::clearAllAccessors@endlink whenever deleting nodes directly. @subsection subsecTraversal Tree Traversal To be written */