(本文未经许可禁止转载)

           

背景

OpenVDB是一个得过很多学术奖的流体模拟单元Voxel数据结构,因其目前免费开源,在电影界各大主流电影特效制作软件(如Maya,Houdini)中广泛流传使用。

我第一次接触这个数据结构是在学习Houdini的阶段的时候了解到VDB,通过实际操作感受,VDB的某些Filter的计算速度和存储体积都比Houdini内置数据格式Volumn优秀。

最近,因工程设计需要,想要摆脱Houdini框架依赖,开发自己想要的流体编辑器。就决定利用先前开发PixelsWorld的经验,自己在电脑上搭建自己的OpenVDB工作站。现在网上关于OpenVDB搭建的外文手册少之又少,更别提中文的了。希望这篇文章能多多少少帮助到致力于开发OpenVDB的相关人士。

这篇文章只针对OpenVDB 7.0.0(后续版本的搭建请参考官方手册

MAC端的搭建流程

首先我觉得想要开发这种东西的人应该都掌握了科学上网CMakeHomebrew大法,就不赘述了。

♪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.cppMakefile

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$ 
       

(本文未经许可禁止转载)

   

发表回复