要说在《三体》这本著名的科幻小说中挑选几个令人印象深刻、血脉膨胀的科幻元素和场景,那 水滴攻击和 二向箔降维打击肯定能上榜。
图注:水滴
今天我们就来讲一讲 降维打击——如何实现对地球“从三维向二维跌落”。
在《三体》中, 太阳系被一小片二向箔攻击由三维降至二维的场景描述实在是太吸引人了有没有:
“这是第一个跌入二维的固态行星,与海王星和土星想象比,二维地球的“年轻”更加清晰精致……”,听起来如此有诗意的描述,激发了不少读者的无限想象,一位重度科幻迷的B站Up主 Ele实验室便是其中一个,起初他想象的三体降维是这样的:
啪的一声!三维变成二维……
啊这……有点儿草率了。
那下面这样呢?
这种剥橘子的方法显然也不太行。
其实,以上这两种想法最大的问题就是只考虑了地球的表面。就像我们在玩游戏穿模时看到的那样,目前主流的三维建模技术采用的都是三角面,组成物体的表面,而至于物体的内部则只是空的而已。
但地球其实是一个实心的球体,从内到外依次是地核、地漫、地壳和地表。
这就有点复杂了。
那么该如何实现对三维物体降维攻击呢?
几天前,这位B站UP主在用threejs框架编写程序时,无意间发现了一个Demo,
它大概这个样子:
和大多数人一样,Up主起初也以为这个密集恐惧者看了流泪、贪吃蛇爱好者见了狂喜的线条,只是一个简单的数学分析。
但研究之后,他发现这其实是大名鼎鼎的 希尔伯特曲线。
正是借助这条曲线,Up主成功实现了对三体的降维打击。
希尔伯特曲线
我们先来了解一下什么是“希尔伯特曲线”?
早在19世纪时数学界就掀起了一阵用一维直线填满二维平面的热潮,换句话说就是找到一维和二维的一个映射,起初是意大利数学家皮亚诺,没错,就是时不时出现在高等数学教材里的老伙计:
他提出了一种能够填满平面的曲线皮亚诺曲线,紧接着是德国数学家希尔伯特提出了另外一种希尔伯特曲线,这也就是本文要介绍的Up主用来完成降维打击的工具。
希尔伯特曲线是这样的:这是一个平面正方形,先把它画为4等份,可以使用这样一条曲线遍历所有的四个小块,这就是一阶的希尔伯特曲线。
之后每个小块可以再划分为4等份。如果还想得到一个能够遍历出所有小块的曲线,可先把4个小区域内各自画出一阶希尔伯特曲线。
然后把下面两个分别旋转90度和-90度再把它们连起来,这就是二阶的希尔伯特曲线。
同样的道理我们可以得到三阶、四阶、五阶希尔伯特曲线等等。
而当阶数趋近于无穷的时候,我们就可以认为曲线“填满了”整个平面:
只有当这时候才是真正意义上的希尔伯特曲线,而之前阶数达不到不无穷的情况,姑且可以称作 “伪希尔伯特曲线”。
通过遍历这个曲线我们就可以得到平面上所有的点,虽然希尔波特的曲线取无穷大的时候,在数学上还有很多争议,但是对于离散系统的计算机来说,这已经很Nice了。
那么,希尔伯特曲线如何实现降维?
举个栗子:
这是一张64×64像素的图片,每个像素刚好是一个小方块。
我们可以用伪希尔伯特曲线穿过这些像素块,然后从线的出口处像糖葫芦一样向外拉扯这些像素,这样一来二维图片就变成了一维的:
当然由于我们无法做到无穷,这只是一种近似。
不过,这种降维方式的好处是希尔伯特的曲线在遍历的时候能够保证二维平面局部相邻的点在被扯成一维的时候像素点还是相邻的,从而降维后的图案就有自然过渡的效果。
三维降维打击
按照上面的原理,我们就可以开始着手对三维世界的物体进行二维打击了。
此时就要让希尔伯特的曲线的三维结构登场了,它长下面这个样子:
同理,如果用一个足够极限的三维希尔伯特的曲线去贯穿一个三维物体,就可以足够近似的遍历出三维物体的每个点:
但是就像上文所说的一样,目前主流的三维建模方式都是通过三角面去组成一个物体的空壳,即物体的内部是空的,那么这个问题该如何解决呢?
在这里Up主提出,其实除了空壳子,对应二维图片中像素的概念,也可以采用一个叫做 “体素”的方案来建模三维物体。
体素的概念很简单,就是类似游戏《我的世界》中一个个不同颜色的基本立方块,通过不同的堆叠方式产生不同的物体,这些小立方块越小,物体的细节也就越好。
当立方块大小无限趋近于零的时候,也就达到了真实世界物体应有的样子了:
考虑到这种建模方式比较消耗计算资源,Up主在这里只采用了五阶的三维希尔伯特曲线,并产生了 262,144个体素点。
另外Up主参考地球的内部构造用程序快速生成了地球的地核、地幔和地壳。
但要生成拥有大陆和海洋的复杂地表就要稍微麻烦了。
首先要读取一张地球贴图的各点像素,然后用球形贴图算法采样这些像素点映射到球面,再用体素方块堆叠成这些点。
最后我们就能得到一个由体素块构成的、同时具有外部和内部细节的三维地球。