OpenVDB is a library comprising a compact 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, constructive solid geometry (CSG), discretization of partial differential equations, voxelization of polygons, skinning of particles, volumetric compositing and sampling. The technical details of VDB are described in the paper "VDB: High-Resolution Sparse Volumes with Dynamic Topology".
OpenVDB is released under the Mozilla Public License Version 2.0, which is a free, open source, and detailed software license developed and maintained by the Mozilla Foundation. It is characterized as a hybridization of the modified BSD license and GNU General Public License (GPL) that seeks to balance the concerns of proprietary and open source developers. For more information about this license, see the Mozilla FAQ.
Yes, developers who wish to contribute code to be considered for inclusion in the OpenVDB distribution must first complete this Contributor License Agreement and submit it to DreamWorks (directions are in the CLA).
The typical reasons to adopt OpenVDB are if you are storing sparse data and/or if you are performing sparse computations. OpenVDB is also effectively unbounded, which makes it very convenient for applications where the topology of the data is dynamic or unknown. Unlike many existing sparse data structures, OpenVDB is also optimized for numerical simulations, multithreaded volume compositing, near real-time boolean CSG operations, fast random and sequential data access and voxelization of points and polygons.
We currently use a major.minor.patch version numbering system, and with every release of OpenVDB we change one or more of the three numbers. The patch number is incremented for new features and bug fixes that change neither the API nor the file format of the library nor the ABIs of the
Transform classes and their constituent classes. The minor version is incremented for releases that change the API without changing the
Transform ABIs, and for releases that change the file format in such a way that older files can still be read. The major version is incremented when the
Transform ABIs change, or when the file format changes in a non-backward-compatible way (which should be rare). No release of OpenVDB guarantees ABI compatibility across the entire library, but rather only for the
Transform classes, and primarily to allow third-party app plugins compiled against different versions of the library to coexist and exchange data.
Yes! OpenVDB is specifically developed to be highly customizable. That is, the user can define the sizes of all the nodes at each level of a tree as well as the number of tree levels and the data type of values stored in the tree. However, note that since OpenVDB makes extensive use of C++ templating, configurations are fixed at compile time rather than at run time. This is a fundamental design characteristic of OpenVDB, and it leads to very high performance, thanks to techniques like inlining and template metaprogramming.
No! While OpenVDB can conceptually be configured as a (height-balanced) octree, it is much more than an octree or N-tree. Whereas octrees and N-trees have fixed branching factors of respectively two and N in each coordinate direction, OpenVDB's branching factors typically vary between tree levels and are only limited to be powers of two. To understand why and also learn about other unique features of OpenVDB, refer to the paper in ACM Transactions on Graphics.
No! Don't let the fact that OpenVDB can represent and operate so well on level sets mislead you into thinking that it is limited to or even focusing on this special type of sparse volumetric application. OpenVDB was developed for general-purpose volumetric processing and numerical simulation, and we have even had success using it for volumetric applications that traditionally call for blocked or dense grids. However, the fact remains that narrow-band level sets play an essential role in many volumetric applications, and this explains why OpenVDB includes so many tools and algorithms specifically for level sets.
Let's first stress that the term "adaptive grid" is somewhat ambiguous. Some use it to mean a grid that can store data sampled at adaptive voxel sizes typically derived from a so-called "refinement oracle", whereas others mean multiple grids with different fixed voxel sizes all sampling the same data. An example of the former is an octree and of the latter is a mipmap. Since OpenVDB stores both data values and child nodes at each level of the tree, it is adaptive only in the first sense, not the second. The level of adaptivity or refinement between the tree levels is defined by the branching factors of the nodes, which are fixed at compile time.
Over the years VDB has been interpreted to mean different things, none of which are very descriptive: "Voxel Data Base", "Volumetric Data Blocks", "Volumetric Dynamic B+tree", etc. In early presentations of VDB we even used a different name, "DB+Grid", which was abandoned to emphasize its distinction from similarly named, but different, existing sparse data structures like DT-Grid or DB-Grid. The simple truth is that "VDB" is just a name. :-)
It might surprise you that the
Grid class doesn't directly provide access to voxels via their coordinates. Instead, the recommended procedure is to ask the grid for a "value accessor", which is an accelerator object that performs bottom-up tree traversal using cached information from previous traversals. Caching greatly improves performance, but it is inherently not thread-safe. However, a single grid may have multiple value accessors, so each thread can safely be assigned its own value accessor. Uncached—and therefore slower, but thread-safe—random access is possible through a grid's tree, for example with a call like
OpenVDB stores voxel data in a tree with a fixed maximum height (chosen at compile time), with a root node that has a dynamic branching factor, with internal nodes that have fixed branching factors, and with leaf nodes of fixed dimensions. Values can be stored in nodes at all levels of the tree. Values stored in leaf nodes correspond to individual voxels; all other values correspond to "tiles" (see below).
Every value in a grid has a binary state that we refer to as its "active state". The interpretation of this binary state is application-specific, but typically an active (on) value is "interesting" in some sense, and an inactive (off) value is less interesting or uninteresting. For example, the values in a narrow-band level set are all active, and values outside the narrow band are all inactive. Active states of values are stored in very compact bit masks that support sparse iteration, so visiting all active (or inactive) values in a grid can be done very efficiently.
Values stored in nodes of type
LeafNode (which, when they exist, have a fixed depth), correspond to individual voxels. These are the smallest addressable units of index space.
Values stored in nodes of type
InternalNode correspond to regions of index space with a constant value and active state and with power of two dimensions. We refer to such regions as "tiles". By construction, tiles have no child nodes.
A tree's background value is the value that is returned whenever one accesses a region of index space that is not explicitly represented by voxels or tiles in the tree. Thus, you can think of the background value as the default value associated with an empty tree. Note that the background value is always inactive!
Yes and no. If you're asking if OpenVDB can safely be used in a multithreaded application then the answer is a resounding yes. In fact, many of the tools included in OpenVDB are multithreaded (using Intel's Threading Building Blocks library). However, like virtually all data structures that employ caching and allocate-on-insert, certain operations in OpenVDB are not thread-safe in the general sense. In particular, it is not safe to retrieve voxels from a grid while another thread is inserting voxels. For multithreaded insertion operations we typically assign a separate grid to each thread and then merge the grids as threads terminate. This technique works remarkably well: because OpenVDB is sparse and hierarchical, merging is very efficient. For more details, please consult the OpenVDB Cookbook and Appendix B in the Transactions on Graphics paper.
Yes, to within available memory and the 32-bit precision of the coordinates used to index voxels. And OpenVDB supports signed coordinates, unlike most existing sparse data structures, so there are almost no restrictions on the available grid resolution or the index range of OpenVDB grids.
OpenVDB is very different from existing sparse data structures that you are likely to have heard of. Foremost it is hierarchical (unlike DT-Grid and Field3D), supports simulations and dynamic topology (unlike GigaVoxels), is effectively unbounded (unlike Field3D), and offers fast random and sequential voxel access.
This depends a lot on your application of dense grids and your configuration of OpenVDB. Clearly, if you are storing or processing sparse data, OpenVDB will offer a smaller memory footprint and faster (sparse) data processing. However, even in some cases where both data and computation are dense, OpenVDB can offer benefits like improved CPU cache performance due to its underlying blocking and hierarchical tree structure. Exceptions are of course algorithms that expect dense data to be laid out linearly in memory, or applications that use very small grids. The simple truth is only a benchmark comparison can tell you the preferred data structure, but for what it's worth it is our experience that for the volumetric applications we encounter in production, OpenVDB is almost always superior.
We are continuing to expand the OpenVDB toolset and improve its performance. In the near future we plan to add OpenVDB Maya plugins, Python bindings to more library tools, support for accelerated particle storage and lookup, level set morphing and measures (e.g. area and volume), more rendering options, a fluid pressure solver, improved methods for particle skinning, asynchronous I/O, optimization by means of SIMD instructions, out-of-core support, advection of densities (vs. level sets) and much more. We would very much like to hear your suggestions and preferences.
If you have bug reports or ideas for improvements or new features, please contact us! If you want to contribute code, please see our License page.