DIY 多面体镜面万花筒

前几天在网上看到了一位艺术家 Anthony James 的展览作品,使用多面体和镜子生成万花筒的效果,觉得很有意思:

这个作品的大致原理是:

  1. 多面体的外壳是透明的玻璃,内表面铺有反光膜。
  2. 多面体的每条边朝向内部的一侧安装了 LED 光源。
  3. 光源的光线在内部反复反射,每次反射时大部分光线会被反光膜反射回内部,一部分光线穿过外壳被外部观察到,就看到了层层叠叠的万花筒图案。

YouTube 上有个博主手把手地展示了怎样从头 DIY 一个这样的模型:视频地址。我表示这顿操作虽然看着不算难,但对我这种懒人来说还是有点过于折腾了。

不过没关系,咱可以编程实现呀,不就是把多面体的数据算出来,然后光线追踪渲染么。折腾了一周左右,分别用 taichi 和 glsl 各自实现了一个版本:[代码地址],做出来的效果和真实视频中的样子也差不了多少:

上面的动画演示的是菱形十二面体 (rhombic dodecahedron),它有个独特之处是自身在镜子反射下成的像可以密铺整个空间 (space filling)。这样的多面体其实非常少,正方体当然是其中之一,但是其它的正多面体 (正四面体、正八面体、正十二面体、正二十面体) 都不行。

这个代码可以渲染绝大部分的 uniform polyhedron 及其对偶,入口函数为

1
2
3
4
5
6
7
generate_polytope_data(
coxeter_diagram,
trunc_type,
extra_relations=(),
snub=False,
dual=False
):

各参数含义如下:

  • coxeter_diagram 是多面体对称群对应的 Coxeter-Dynkin 图。
  • trunc_type 设置多面体的截断类型。
  • extra_relations 用于指定星状多面体所需的额外生成关系 (目前的渲染代码不太支持这种多面体)。
  • snub 选择是否是手性多面体。
  • dual 选择是否渲染对偶多面体。

关于这些参数的具体解释,以及怎样通过它们计算多面体的数据,请参考我之前的一篇文章

代码中使用的多面体数据其实就是把每个面的三维坐标根据顶点个数分别放在不同的 vec3[] 数组里面,你也可以将任何其它多面体的数据代入来观察效果,比如多面体 Gyrobifastigium 1 给出的效果如下所示:


  1. 感谢陈浩老师告知,我才知道有这么个名字诡异的多面体。↩︎

 | 

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器