2

简介

Hamal 是一份 Python 3 脚本,可将点集、无向图、曲线、矢量场、网格曲面等三维几何数据转化为 POV-Ray 场景文件。也就是说,Hamal 不生产数据,也不负责图形渲染,它只能算是一个数据格式转换器,面向对 POV-Ray 有一些了解并且希望使用 POV-Ray 对上述三维几何图形进行光线追踪渲染的人。

安装

$ git clone https://github.com/liyanrui/hamal.git
$ cd hamal
$ chmod +x hamal
$ sudo install hamal /usr/local/bin

点集

待渲染的三维点集数据应当存储在 ASCII 编码的文本文件中,并且文件的每一行文本都是三维点坐标的字面值,例如:

1.2 3.3 5.4
0.1 2.2 8.5
... ... ...

现在假设三维点集数据文件为 foo.asc,通过以下命令可将其转换为 POV-Ray 场景文件 foo.pov 与 foo.inc:

$ hamal foo.asc

这条命令会在当前目录生成 foo.pov 与 foo.inc,前者为视图文件,后者为 POV-Ray 模型文件,使用 povray 命令可基于 foo.pov 与 foo.inc 对点集进行渲染:

$ povray foo.pov

渲染结果为当前目录下的位图文件 foo.png。例如:

斯坦福兔子

Hamal 默认的点的尺寸是 0.0025,下面这条命令可将其设置为 0.005:

$ hamal --point-size=0.005 foo.asc

再次使用 povray 处理新生成的 foo.png,结果可得:

斯坦福兔子

注:事实上,当点的尺寸设为 x 时,点在 POV-Ray 中的实际尺寸是 x * r,r 为点集近似最小外接球的半径。

点集是下文所述的无向图、矢量场以及网格的「实体」。

无向图

对于点集数据文件 foo.asc,假设我们算出了它对应点集的欧几里得最小支撑树(EMST)——EMST 是树,也是无向图。假设 EMST 的数据被保存到 foo-graph.asc 文件,该文件的每一行都是 EMST 的一条边的两个端点,只不过存储的不是点坐标,而是 foo.asc 文件中对应点坐标的行号,只不过 foo.asc 第一行的行号从 0 开始。将 foo.asc 视为 C 语言中的 n 行 3 列的二维数组可能会更好理解一些。例如:

0 1
1 15677
15677 12881
12881 12849
... ...

要绘制无向图,在将无向图数据转换为 POV-Ray 的过程中,需要载入点集数据文件与无向图数据文件:

$ hamal --graph=foo-graph.asc foo.asc

然后使用 povray 对新的 foo.pov 进行处理,便可得到 EMST 的渲染结果:

EMST

结果似乎与上文所示的点集模型的渲染结果差不多,这实际上是因为点集非常密集所致。若修改 foo.pov,让相机距离点集更近一些,便可以看清 EMST 的局部分支。

打开 foo.pov,将

camera {
  location <0, 0, -2 * model_radius> + model_center * z
  look_at <0, 0, 0>
  translate view_center
}

修改为:

camera {
  location model_center * z
  look_at <0, 0, 0>
  translate view_center
}

上述修改,意味着将相机沿 z 轴正方向移动了 2 * model_radius 个单位,即让相机重复靠近 EMST。重新用 povray 处理 foo.pov,可得:

local emst

点的尺寸与先的宽度似乎太大了一些,可以将它们设置的小一些,可以在使用 hamal 生成 POV-Ray 场景文件时将它们的尺寸设置的小一些,例如:

$ hamal --graph=foo-graph.asc --point-size=0.001 --line-width=0.0005 foo.asc

结果可得:

local emst

曲线

将一条曲线离散化处理,形成一组首尾相连的线段,这样就可以构成无向图,然后利用上一节渲染无向图的方法进行曲线的渲染。

下图是一条 3 次 Bezier 曲线的渲染结果:

clipboard.png

矢量场

矢量场,就是一组矢量,这组矢量的起点即上文所述的点集文件,例如 foo.asc,而它们的终点存储在矢量场文件中,例如 foo-vector-field.asc。矢量场文件的格式与点集文件相同。

下面的命令可以将矢量场转化为 POV-Ray 场景文件:

$ hamal --vector-field=foo-vector-field.asc --point-size=0.001 --line-width=0.0005 foo.asc

像上一节那样修改 foo.pov 文件,拉近相机与模型之间的距离,结果可得:

矢量场

网格

为了便于演示,下面的命令使用了 qhull 为一组随机点集构建了凸包,然后将凸包数据(三角网格文件)转换为 POV-Ray 场景文件并交由 povray 进行渲染:

$ rbox 100 W0 > points.asc
$ qhull QJ i < points.asc TO hull.asc
$ sed -i '1,2d' points.asc
$ sed -i '1d' hull.asc
$ hamal --object=hull --mesh=hull.asc --point-size=0.03 points.asc
$ povray +P hull.pov

hamal 的 --object 选项用于设定 POV-Ray 模型的文件名(不包含扩展名)。

结果可得到如下图所示的渲染结果:

凸包与共面点

内幕

见「Python 邂逅 POV-Ray」与「趴边去!」。


garfileo
6k 声望1.9k 粉丝

这里可能不会再更新了。