前两天用 Python 语言写了个小工具 Hamal,可以将一些朴素的数据文件转化为 POV-Ray 场景文件,然后进行光线跟踪渲染,从而实现数据的可视化。有关 Hamal 的用法,详见 「Hamal 指南」。
昨晚想给娃做一个伪全息投影的玩具,就是 4 张三角形的透明塑料片拼接成一个金字塔,然后用手机播放网上下载来的初音未来的伪全息视频,将屏幕画面投射到这个金字塔的四个面上。
制作这种金字塔的教程,百度一下,铺天盖地。淘宝上也有成品,不过,自己制作起来并不困难,要点就是金字塔底边框是一个正方形,边长与手机屏幕相同,并且金字塔的每个面与底边框围成的平面之间的夹角为 45 度角。硬一些的塑料板会更方便制作。
难度稍微大一些的是伪全息视频的制作,应该有这方面的专业软件。不过,由于我刚写了 Hamal,踌躇满志,文风开始进入不严肃模式。我决定投身演艺界,拍摄一部伪全息舞台剧。我围观了最近的演艺圈新闻,看看谁有潜力拿小金人。斯坦福兔子以一幅傲视群雌的姿态出现在我的视野……
斯坦福兔子最近化名为 foo.asc,潜伏在 github.com 山里。不够,他把自己隐居的事告诉了不止一个娱记。这种事,我只知道李白干过。我不远万里前往 github 山,许以重金和美貌的母兔子,将它请了回来:
$ wget https://github.com/liyanrui/hamal/blob/master/data/foo.asc
然后我开始写剧本,规划舞台布置以及照明等问题:
$ hamal foo.asc
没办法,整个拍摄团队就老哥我一个。
剧本与拍摄草案很快就就出来了。剧本太长,这里就不显摆了,它就在我的硬盘里躺着,文件名叫 foo.inc。舞台布置与照明的草案 foo.pov 的内容如下:
#version 3.7;
#include "colors.inc"
background {color White}
global_settings {assumed_gamma 1.0}
#declare model_center = <8.315960, 8.015419, -6.846305>;
#declare model_radius = 12.512303;
#declare view_center = model_center;
camera {
orthographic
location <0, 0, -2 * model_radius> + model_center * z
look_at <0, 0, 0>
translate view_center
}
light_source {
model_center + <0, 0, -10 * model_radius>
color rgb <1.000000, 1.000000, 1.000000>
shadowless
}
#declare point_size_of_foo = 0.031281;
#include "foo.inc"
object {
foo
pigment {
color rgb <0.03, 0.2, 0.4>
}
}
斯坦福兔子抓过 foo.pov 看了看,又扔到了一边,你傻啊,舞台背景怎么能是白色呢?
那我就改成黑色:
background {color Black}
兔子又看了看,鄙夷地说,我是着妆是白色的,而不是脏兮兮的灰蓝色!
那我就改成白色:
object {
foo
pigment {
color White
}
}
兔子又看了看,没再说话。
那我们就开始拍吧!兔子先生,请你在上台,转一圈!
兔子没有动。兔子先生……请你……它居然发火了,老哥,你业余的吧!转圈是随便转的吗?一切都要设计,精心设计!
好吧,我从 foo.pov 里删掉了
object {
foo
pigment {
color rgb <0.03, 0.2, 0.4>
}
}
然后又很耐心地用了 5 分钟的时间,给它设计了一套很精确很复杂很繁琐的转圈说明:
#declare offset_dist = 1.3 * model_radius;
// 正面
object {
foo
translate -model_center
rotate clock * 360 * y
translate model_center
translate -offset_dist * y
pigment {
color White
}
}
// 背面
object {
foo
translate -model_center
rotate 180 * y
rotate 180 * z
rotate -clock * 360 * y
translate model_center
translate offset_dist * y
pigment {
color White
}
}
// 右面
object {
foo
translate -model_center
rotate -90 * y
rotate -90 * z
rotate clock * 360 * x
translate model_center
translate -offset_dist * x
pigment {
color White
}
}
// 左面
object {
foo
translate -model_center
rotate 90 * y
rotate 90 * z
rotate -clock * 360 * x
translate model_center
translate offset_dist * x
pigment {
color White
}
}
兔子看了看 foo.pov,又一次没再说话。
好,那我们开拍!兔子没有动。我只好再说一遍,开拍!它还是没动。
对,还没有场记,不得不再客串一下。
在硬盘上,在 foo.inc 与 foo.pov 所在的目录里创建了场记单 foo.ini,让兔子转一圈需要拍 60 帧,于是我在 foo.ini 里写下了
Input_File_Name = foo.pov
Initial_Frame = 1
Final_Frame = 60
然后我说,开拍!
兔子说,你还没启动摄像机!
好吧,
$ povray foo.ini
刷唰唰唰,四台摄像机启动了起来,它们从舞台的四面同时拍摄。兔子走上台,按照 foo.pov 里的说明,开始漫不经心的转圈……
上面的是「视频」是我用 imagemagick 工具箱里的 convert 命令用 60 帧图片合成的动图:
$ convert -delay 10 -loop 0 foo*.png foo.gif
第一场,拍完后,把之前谈好的片酬给了兔子。它去找母兔子制造斐波那契数列了,而我只好与一个身无分文的我惺惺相惜。
看来,要拍下一场,要么靠打赏,要么找风投啊……
后记:
由于我觉得伪全息投影比较好玩,所以我在 Hamal 中增加了这一功能,上述的繁琐过程(除了获取数据文件的步骤),现在可归结为三条命令:
$ hamal --holography foo.asc
$ povray foo.ini
$ convert -delay 10 -loop 0 foo*.png foo.gif