背景
OpenVDB是一个得过很多学术奖的流体模拟单元Voxel数据结构,因其目前免费开源,在电影界各大主流电影特效制作软件(如Maya,Houdini)中广泛流传使用。
我第一次接触这个数据结构是在学习Houdini的阶段的时候了解到VDB,通过实际操作感受,VDB的某些Filter的计算速度和存储体积都比Houdini内置数据格式Volumn优秀。
最近,因工程设计需要,想要摆脱Houdini框架依赖,开发自己想要的流体编辑器。就决定利用先前开发PixelsWorld的经验,自己在电脑上搭建自己的OpenVDB工作站。现在网上关于OpenVDB搭建的外文手册少之又少,更别提中文的了。希望这篇文章能多多少少帮助到致力于开发OpenVDB的相关人士。
这篇文章只针对OpenVDB 7.0.0(后续版本的搭建请参考官方手册)
MAC端的搭建流程
首先我觉得想要开发这种东西的人应该都掌握了科学上网、CMake和Homebrew大法,就不赘述了。
♪1:搭建依赖项目
brew install cmake # CMake
brew install ilmbase # IlmBase
brew install openexr # OpenEXR
brew install tbb # TBB
brew install zlib # zlib
brew install boost # Boost
brew install boost-python # Boost-python
brew install python # Python
brew install numpy # NumPy
brew install cppunit # CppUnit
brew install glfw # GLFW
brew install doxygen # Doxygen
♯1:搭建Blosc
其实这里还需要blosc
库。但是OpenVDB说:
Blosc 1.16 is only available through Homebrew and currently requires manual installation for 1.5.
也就是Homebrew提供的blosc是很前面的版本了。但我觉得,一开始的话,为了快速写一个OpenVDB的hello world,大家可以用Homebrew安装(因为我测试Homebrew下的Blosc能正常编译一个简单的hello VDB程序,反正之后还能卸载)。
用Homebrew安装:
brew install c-blosc
如果后面你觉得OpenVDB适合你,你确实需要OpenVDB搭建进你的工程,请使用下面指令安装Blosc
git clone https://github.com/Blosc/c-blosc.git
cd c-blosc
git checkout tags/v1.5.0 -b v1.5.0
mkdir build
cd build
cmake ..
make -j4
make install
cd ../..
上面的指令也不一定能一直管用,如果不行需要参考Blosc官方的README.md
♪2:安装OpenVDB库
git clone https://github.com/AcademySoftwareFoundation/openvdb.git
cd openvdb
mkdir build
cd build
cmake ..
make -j4
make install
这里报错的话,一般是指令
cmake ..
检测到某个依赖没安装上去,按照报错信息填补即可。若仍有报错,请参考这里
♪3:编译Hello world
做一个HelloVDB
文件夹,放入main.cpp
和Makefile
mkdir helloVDB
cd helloVDB
touch main.cpp Makefile
在main.cpp里面写入
#include <openvdb/openvdb.h>
#include <iostream>
int main()
{
// Initialize the OpenVDB library. This must be called at least
// once per program and may safely be called multiple times.
openvdb::initialize();
// Create an empty floating-point grid with background value 0.
openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create();
std::cout << "Testing random access:" << std::endl;
// Get an accessor for coordinate-based access to voxels.
openvdb::FloatGrid::Accessor accessor = grid->getAccessor();
// Define a coordinate with large signed indices.
openvdb::Coord xyz(1000, -200000000, 30000000);
// Set the voxel value at (1000, -200000000, 30000000) to 1.
accessor.setValue(xyz, 1.0);
// Verify that the voxel value at (1000, -200000000, 30000000) is 1.
std::cout << "Grid" << xyz << " = " << accessor.getValue(xyz) << std::endl;
// Reset the coordinates to those of a different voxel.
xyz.reset(1000, 200000000, -30000000);
// Verify that the voxel value at (1000, 200000000, -30000000) is
// the background value, 0.
std::cout << "Grid" << xyz << " = " << accessor.getValue(xyz) << std::endl;
// Set the voxel value at (1000, 200000000, -30000000) to 2.
accessor.setValue(xyz, 2.0);
// Set the voxels at the two extremes of the available coordinate space.
// For 32-bit signed coordinates these are (-2147483648, -2147483648, -2147483648)
// and (2147483647, 2147483647, 2147483647).
accessor.setValue(openvdb::Coord::min(), 3.0f);
accessor.setValue(openvdb::Coord::max(), 4.0f);
std::cout << "Testing sequential access:" << std::endl;
// Print all active ("on") voxels by means of an iterator.
for (openvdb::FloatGrid::ValueOnCIter iter = grid->cbeginValueOn(); iter; ++iter) {
std::cout << "Grid" << iter.getCoord() << " = " << *iter << std::endl;
}
}
♭♪3:试编译
注意
下面的代码在你的电脑上100%不能运行,你需要把
zzstarsound
改成你自己的用户名
,如果仍然报错,请确认对应include位置确实有文件夹。
g++ -c -o main.o main.cpp -Wall -std=c++11 -O2 -I/Users/zzstarsound/openvdb/include
g++ -o helloVDB main.o -Wl,-rpath,/Users/zzstarsound/openvdb/lib -L/Users/zzstarsound/openvdb/lib -L/usr/local/Cellar/tbb/2019_U9/lib -L/usr/local/Cellar/ilmbase/2.3.0/lib -lopenvdb -ltbb -lHalf
♪4:执行
./helloVDB
运行结果
Testing random access:
Grid[1000, -200000000, 30000000] = 1
Grid[1000, 200000000, -30000000] = 0
Testing sequential access:
Grid[-2147483648, -2147483648, -2147483648] = 3
Grid[1000, -200000000, 30000000] = 1
Grid[1000, 200000000, -30000000] = 2
Grid[2147483647, 2147483647, 2147483647] = 4
♪5:制作Makefile
上面的编译指令很长,我们需要用Makefile
为我们节省敲编译代码的时间。我制作的Makefile如下:
你仍然需要把
zzstarsound
换成你自己的用户名
# Makefile, by ZzStarSound
PROGRAM=helloVDB
CFLAGS=-Wall -std=c++11 -O2
OPENVDBINC=-I/Users/zzstarsound/openvdb/include
OUTERLIBINC=-Wl,-rpath,/Users/zzstarsound/openvdb/lib -L/Users/zzstarsound/openvdb/lib -L/usr/local/Cellar/tbb/2019_U9/lib -L/usr/local/Cellar/ilmbase/2.3.0/lib
LINKOUTERDY=-lopenvdb -ltbb -lHalf
OBJS=main.o
.PHONY: all
all: $(PROGRAM)
$(PROGRAM):$(OBJS)
g++ -o $@ $^ $(OUTERLIBINC) $(LINKOUTERDY)
@echo $(PROGRAM) Successfully generated!
main.o:main.cpp
g++ -c -o $@ $< $(CFLAGS) $(OPENVDBINC)
.PHONY: clean
clean:
$(RM) $(PROGRAM) $(OBJS)
这样每次编译只需要输入make
即可。运行结果:
输入代码
make
和./helloVDB
ZzStarSunddeMBP:src zzstarsound$ make
g++ -c -o main.o main.cpp -Wall -std=c++11 -O2 -I/Users/zzstarsound/openvdb/include
g++ -o helloVDB main.o -Wl,-rpath,/Users/zzstarsound/openvdb/lib -L/Users/zzstarsound/openvdb/lib -L/usr/local/Cellar/tbb/2019_U9/lib -L/usr/local/Cellar/ilmbase/2.3.0/lib -lopenvdb -ltbb -lHalf
helloVDB Successfully generated!
ZzStarSunddeMBP:src zzstarsound$ ./helloVDB
Testing random access:
Grid[1000, -200000000, 30000000] = 1
Grid[1000, 200000000, -30000000] = 0
Testing sequential access:
Grid[-2147483648, -2147483648, -2147483648] = 3
Grid[1000, -200000000, 30000000] = 1
Grid[1000, 200000000, -30000000] = 2
Grid[2147483647, 2147483647, 2147483647] = 4
ZzStarSunddeMBP:src zzstarsound$
顺带一提make clean
可以清空生成文件。
ZzStarSunddeMBP:src zzstarsound$ make clean
rm -f helloVDB main.o
ZzStarSunddeMBP:src zzstarsound$