上一篇: 成千上万个盒子
静极思动。
一尺之棰,日取其半,万世不竭。
飞矢不动。
动中有静,静中有动。
人活着,总要搞出点动静。
我召唤 POV Ray。
POV Ray 随一缕青烟飘然而至。这让我想起,上次他是化作一缕青烟消失了。不过,我并不觉得奇怪,就像他能用咒语画画也没让我觉得奇怪那样。
「有什么办法可以让盒子飞来飞去,而不是伴随或变成一缕青烟?」我问 POV Ray。
POV Ray 看着天上旗幡般的流云,沉思了一小会说,「要么你不动,它动,要么它不动,你动。不能只是心动。」
「让它动吧。我最近挺懒,总不能因为想看它转一圈,我要围着它走一圈吧。」
「可以。咒语是这样念的,
object {
foo
texture { foo_texture }
// ... 在此对 foo 的方位进行变换 ...
}
//
是注释语,它领起的语句,povray 会自动忽略。」
「那么就让盒子转一圈吧。」
「欲动先能静。先看看可以让它绕某个轴转某个角度的咒语。譬如,让它绕 Y 轴转 30 度,
object {
foo
texture { foo_texture }
rotate 30 * <0, 1, 0>
}
<0, 1, 0>
表示 Y 轴,不过,为了方便,也可以写成 y
,
object {
foo
texture { foo_texture }
rotate 30 * y
}
要让盒子绕 Y 轴转一圈,可以让旋转的角度可以从 0 到 360 度递增变化,每个角度生成一张图片,然后你只需要最后得到的图片依序看一遍,盒子就转了一圈。」
「有道理……现在我忽然觉得,世界安静一些也挺不错。」
「有一个变量,叫 clock
,它的存在像天选之子,可用于模拟一个会自动增大的旋转角度,譬如
object {
foo
texture { foo_texture }
rotate 360 * clock * y
}
因为 clock
变量能够自动从 0 逐渐变化到 1,所以 360 * clock
的意思就是从 0 度角逐渐变化到 360 度角。」
「静中果然是有动的。」我听见外面嘭嘭嘭三声巨响,刚才用一小段香和三个捻子很短的炮仗制作的定时炸弹终于被窗外静静的时光触发了,「我的炸弹,时间是一小段香控制的,你的闹钟是谁控制?」
「是 .ini 文件。假设用来画盒子的咒语都写在 foo.pov 文件,那么控制 clock
的咒语就写在 foo.ini 文件里,譬如
Input_File_Name=foo.pov
Initial_Frame=1
Final_Frame=60
Input_File_Name
将 foo.ini 文件和 foo.pov 文件关联了起来。n = (Final_Frame - Initial_Frame + 1)
的倒数 1/n
便是 clock
变量的增长速度,在本例中,即 1/60
。准备好 foo.ini 之后,执行
$ povray foo.ini
便可生成一系列图片,foo01.png、foo02.png、……foo60.png。图片中的编号,起始值是 Initial_Frame
,终止值是 Final_Frame
。」
「我明白了。用这个办法生成一组图片,然后把它们转化为动图,譬如 GIF 格式。」
POV Ray 点点头,旋转着,飞到了窗外,不见了。
我开始埋头写咒语,模拟他消失的样子。
首先,foo.pov 文件中画盒子的大部分咒语被我挪移到一份新建的文件 foo.inc 中了。foo.inc 的内容为
#declare foo_size = <0.3, 0.15, 0.10>;
#declare foo_texture = texture { pigment { color rgbt <0, 1, 0, 0.75> } }
#declare foo = box {
-0.5 * foo_size, 0.5 * foo_size
texture {foo_texture}
}
#declare v1 = <-0.5, 0.5, -0.5> * foo_size;
#declare v2 = v1 + ;
#declare v3 = v2 + <0, 0, foo_size.z>;
#declare v4 = v3 + <-foo_size.x, 0, 0>;
#declare v5 = v1 + <0, -foo_size.y, 0>;
#declare v6 = v2 + <0, -foo_size.y, 0>;
#declare v7 = v3 + <0, -foo_size.y, 0>;
#declare v8 = v4 + <0, -foo_size.y, 0>;
#declare bar_size = 0.01;
#declare bar_texture = texture { pigment { color Gray20 } }
#declare delta = bar_size * <0.5, 0.5, 0.5>;
#declare frame = object {
union {
box { v1 - delta, v2 + delta }
box { v2 - delta, v3 + delta }
box { v4 - delta, v3 + delta }
box { v1 - delta, v4 + delta }
box { v5 - delta, v6 + delta }
box { v6 - delta, v7 + delta }
box { v8 - delta, v7 + delta }
box { v5 - delta, v8 + delta }
box { v5 - delta, v1 + delta }
box { v6 - delta, v2 + delta }
box { v7 - delta, v3 + delta }
box { v8 - delta, v4 + delta }
}
texture { bar_texture }
}
这样一来,foo.pov 就如释重负:
#version 3.7;
#include "colors.inc"
global_settings {
assumed_gamma 1.0
}
#include "foo.inc"
object {
union {
object { foo }
object { frame }
}
rotate 45 * <1, 1, 1>
rotate 5 * 360 * clock * y
translate 20 * clock * z
}
#declare foo_front = -0.5 * z;
camera {
location foo_front
look_at <0, 0, 0>
}
#declare camera_upper_right = foo_front + <0.5, 0.5, -1>;
light_source {
camera_upper_right
color White
}
foo.ini 文件还是 POV Ray 给出的那样:
Input_File_Name=foo.pov
Initial_Frame=1
Final_Frame=60
然后,执行两条命令,可得到动图文件 foo.gif:
$ povray +A foo.ini
$ convert -delay 10 -loop 0 foo*.png foo.gif
convert
是 ImageMagick 提供的工具,可将一系列尺寸相同的图片合成为动图。
下一篇: 坐标变换