OpenVDB 是Vlometric Dynamic B+ tree like 的缩写,作为梦工厂的开源体渲染解决的方案,发展到今天它已经不仅仅是一种体素存储格式了,还包含了各种无所不包的工具,包括体素转mesh,mesh转体素,各种加速工具,Viewer和一个简单的volume renderer等. 不过VDB的文档至今仍然十分不完善,写这个cookbook是为了记录自己的学习过程. 第一篇就先讨论VDB的各种概念和它本身的代码特点.
1. Tree & Grid
OpenVDB的理论基础和数据结构特点都在 Ken Museth 的这篇paper里
http://www.museth.org/Ken/Publications_files/Museth_TOG13.pdf
强烈推荐阅读,而我对OpenVDB存储结构的总结就是:
- Height balanced N-tree with Hash map
也就是说VDB是类似八叉树一样的树形结构,但是VDB的branching factor每层不同,保证了随机访问不需要查找很多层,而对于root节点VDB使用了Hashmap 加速. 和数据库中常用的B+ 树一样,VDB也有Internal Node Leaf Node 等各层节点,而真正的体素值,是存储于Leaf Node上的.
OpenVDB的voxel值的存储分成inactive和active两种状态,这一特点在表示某些特殊类型的体积数据时会很有用,下面会说到.
所以VDB里最基础的结构也就是openvdb::tree. VDB是一个TML heavily used 的库,而在定义各种tree时VDB也是用模板参数确定树的结构的. 例如最常用的FloatTree:
typedef tree::Tree4<float, 5, 4, 3>::Type FloatTree;
这是一个四层的树(root node; Internal node; Internal node; Leaf node),每层的branching factor为 5,4,3.(这也是VDB规定的一般的树形结构).
而Grid则是VDB对Tree类型的封装,加上了BBox等非常重要的信息. 可以由Grid得到Tree(Grid.tree()).
2.Tile, Voxel, and Background Values
一般而言voxel是存储在LeafNode里用(i,j,k)这样的index索引的值,不过一个非LeafNode也可以有value, 也就是tile value. 比如一个InterNode(888)有tile value 1,也就是相当于一个888的均匀的值为1的立方体. 一个Grid的Background value是指当你的(i,j,k)索引索引不到Node或者Voxel时返回给你的值
3.Level set & fog
OpenVDB 经常用来表示和存储的就是Level sets 和 fog volumes. 利用上面说到的voxel的两种状态,Level set水平集是由一个外部区域(voxel为inactive,并且到levelset平面有正的距离(常量)),一个内部区域(voxel也为inactive,到levelset平面有负的距离(常量)),和一个非常狭窄的Active voxels的平面构成. level set 适合表示水面等形状的体积数据
Fog volume也由类似的三部分区域构成,只不过对于fog volume. 内部体素的值都是1,外部体素的值都为0.
4.Iterators
访问树形结构的iterators. OpenVDB提供了三种:
- Tree:ValueIter : 访问每个value一次,也就是上面所说的tile 或者是 voxel,同时也提供了得到Bounding box的方法
- Tree::LeafIter : 只访问树的最底层也就是Leaf Node.
- Tree::NodeIter : 访问每个Node一次,可以方便得到Node的所有信息.
5.Value Accessor
OpenVDB一个很大的优势就是加速了体素的随机访问,Value Accessor就是很方便的查询(i,j,k)坐标的体素, 同时还提供了方法能把world space坐标转化为Index space coordinates, 可以非常方便的访问体素, 用Gird.getAccessor()可以很方便的拿到ValueAccessor类.
ValueAccessor是拥有cache based acceleration的,因此当多个线程访问同一个grid的时候,需要给每个线程都分配一个Accessor.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。