1. 数学分析
为什么我们要画2D直线,要做2D的直线-矩形裁剪?原因很简单,无论游戏世界是2D的还是3D的,最终都要投影到玩家的屏幕上,3D的东西最终要是要投影到视平面上。所以3D游戏仍然有很多东西要在2D视平面上做。对于3D游戏的裁剪就有两种方法:一是在3D空间做裁剪,利用视域体的各个面与三角形中直线的关系来做,这叫做立方体空间裁剪;另一种是,把3D物体先投影在2D视平面上,然后在视平面上对2D直线做矩形裁剪,叫作图像空间裁剪。三角形都是由直线组成的,屏幕是矩形的,所以用矩形裁剪一条直线是非常重要的,而且也不是想当然的简单的,也有很多因素要考虑。
1) 直线被矩形裁剪的四种情况
直线被矩形裁剪只有以下4种情况,如图:
2) 裁剪的核心问题?
我们来看看,裁剪的核心问题是什么:
如上图,两个端点分别为p0,p1的直线线段,被某一矩形裁剪。裁剪的过程是给定输入值x0,y0,x1,y1和矩形RECT,输出被裁剪后的直线两端点p0',p1'的坐标x0',y0',x1',y1'。
通过观察上图,我们可以知道,我们其实就在求两条直线的交点,一条是红线,一条是矩形的某个边。这让我们想起了几何学时的几种直线表示形式,然后求交点就是解一个方程组的过程。这没有错,但是我们可以走捷径,因为矩形的某个边不是水平线,就是垂直线,所以这第二条直线的表示非常简单。垂直线是x = c,水平线是y = c。
我们来表示一下这条红线。比如我们用点斜式:
斜率m = (y2 - y1) / (x2 - x1)
点斜式: y - y1 = m * (x - x1)
整理后,用y表示x:
x = (y - y1) / m + x1
也可以用x表示y:
y = m * (x - x1) + y1
所以与某个矩形的边的交点,可以把那个边线的表示形式直接代入,即可求得。
3) Cohen-Sutherland
上面我们解决了核心问题,那就是如何求交点。而Cohen-Sutherland算法为我们解决了另一个文章开头所说的问题,就是如何处理直线与矩形之间的4种关系。
该算法虽然简单,但极其精妙,后面会讲如何精妙!它把空间分成了各个部分,并赋予了相应的位代码,所以只使用少量的if语句,并且还是位运算,根据直线的两端点,即可判断出是上面哪种关系,如图:
如果你想感动一下,那一定要非常仔细的研究这个图了。
首先,我们看红色代码的部分,请不要看那个黑色的十进制code,中间裁剪矩形的代码是0000。正左方、正右方、正下方、正上方分别是:
0001
0010
0100
1000
即,他们每个是其中的一个位标记,所以可以通过两两做或操作(|),来得到斜着的4个角的代码(绿色)。
首先,根据这些特性,我们可以做一些工作了&