背景
OpenVDB是一個(gè)得過很多學(xué)術(shù)獎(jiǎng)的流體模擬單元Voxel數(shù)據(jù)結(jié)構(gòu)某抓,因其目前免費(fèi)開源,在電影界各大主流電影特效制作軟件(如Maya,Houdini)中廣泛流傳使用乌叶。
我第一次接觸這個(gè)數(shù)據(jù)結(jié)構(gòu)是在學(xué)習(xí)Houdini的階段的時(shí)候了解到VDB,通過實(shí)際操作感受柒爸,VDB的某些Filter的計(jì)算速度和存儲(chǔ)體積都比Houdini內(nèi)置數(shù)據(jù)格式Volumn優(yōu)秀准浴。
最近,因工程設(shè)計(jì)需要捎稚,想要擺脫Houdini框架依賴乐横,開發(fā)自己想要的流體編輯器。就決定利用先前開發(fā)PixelsWorld的經(jīng)驗(yàn)今野,自己在電腦上搭建自己的OpenVDB工作站∑瞎現(xiàn)在網(wǎng)上關(guān)于OpenVDB搭建的外文手冊(cè)少之又少,更別提中文的了条霜。希望這篇文章能多多少少幫助到致力于開發(fā)OpenVDB的相關(guān)人士催什。
這篇文章只針對(duì)OpenVDB 7.0.0(后續(xù)版本的搭建請(qǐng)參考官方手冊(cè))
MAC端的搭建流程
首先我覺得想要開發(fā)這種東西的人應(yīng)該都掌握了科學(xué)上網(wǎng)、CMake和Homebrew大法宰睡,就不贅述了蒲凶。
?1:搭建依賴項(xiàng)目
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
其實(shí)這里還需要blosc
庫。但是OpenVDB說:
Blosc 1.16 is only available through Homebrew and currently requires manual installation for 1.5.
也就是Homebrew提供的blosc是很前面的版本了拆内。但我覺得豹爹,一開始的話,為了快速寫一個(gè)OpenVDB的hello world矛纹,大家可以用Homebrew安裝(因?yàn)槲覝y試Homebrew下的Blosc能正常編譯一個(gè)簡單的hello VDB程序臂聋,反正之后還能卸載)。
用Homebrew安裝:
brew install c-blosc
如果后面你覺得OpenVDB適合你,你確實(shí)需要OpenVDB搭建進(jìn)你的工程孩等,請(qǐng)使用下面指令安裝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
這里報(bào)錯(cuò)的話,一般是指令
cmake ..
檢測到某個(gè)依賴沒安裝上去肄方,按照?qǐng)?bào)錯(cuò)信息填補(bǔ)即可冰垄。若仍有報(bào)錯(cuò),請(qǐng)參考這里
?3:編譯Hello world
做一個(gè)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%不能運(yùn)行虹茶,你需要把
zzstarsound
改成你自己的用戶名
,如果仍然報(bào)錯(cuò)隅要,請(qǐng)確認(rèn)對(duì)應(yīng)include位置確實(shí)有文件夾蝴罪。
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:執(zhí)行
./helloVDB
運(yùn)行結(jié)果
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
為我們節(jié)省敲編譯代碼的時(shí)間步清。我制作的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
即可要门。運(yùn)行結(jié)果:
輸入代碼
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$