当图形中需要ray trace的物体的数目很大时(比如十万、百万、千万),这时我们就需要对图形生成的过程进行加速。
按照常规办法,需要判断每条光线和每一个物体的碰撞情况。这样一来,则需要耗费大量的时间。
为了缩短生成图形的时间,现在常用的加速技术有如下几种:层次包围体(Bounding Volume Hierarchies)、二叉空间分割树(Binary SpacePartition Trees)、八叉树(Octrees)、KD树(kd-trees)、规则网格(Regular Grids)。
在这里,我们主要学习“规则网格”加速技术的算法。
78.1 概述
什么是“规则网格”呢?
如上图a,需要ray trace的图形中包含多个不同的物体。我们就先用一个大的各边和坐标轴平行的长方体将所有的物体都包起来。这个“大长方体”被称为“网格(Grid)”。然后,将大长方体等分成小正方体(小正方体的个数和物体的个数成比例关系)。这种“小正方体”被称为“格子(Cell)”。
当一条光线穿过Grid时,其实光线穿过并不会穿过每一个Cell,而是穿过其中一部分Cell,如上图b中的阴影部分的Cell。所以,我们只考虑“阴影部分的Cell”。在物体个数很多时,则Cell的总数很多,这样只考虑“阴影部分的Cell”就能节约很多时间。
而且,我们还不用遍历所有“阴影部分的Cell”,只需要找到光线和物体的第一个撞击点(如上图b中的红色标注的点)即可停止遍历后面的“阴影部分的Cell”,这样又节约了很多时间。
简单来说,“规则网格”技术就是:先建立包含所有物体的大长方体;然后将大长方体规则地等分成小正方体;然后,建立物体和小正方体的对应关系;然后用光线撞击小正方体,进而找到光线和物体最近的撞击点。
78.2 算法分析
78.2.1 怎么建立包含所有物体的大长方体(Grid)
1,新建一个类Grid类,Grid类是继承Compound类(Compound类是继承GeometricObject类的)。所以,Grid类可以直接使用Compound类的成员方法add_objects()将所有物体加到Grid对象中。
2,建立包含所有物体的大长方体。
对于各边都和坐标轴平行的长方体,我们只需要知道长方体的前左下顶点P0和后右上顶点P1这两点的坐标,即可确定整个长方体。