void gluLookAt ( eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz);
void glOrtho ( left, right, bottom, top, zNear, zFar);
正投影的视景体是这么定义的:
仅以eye,center和up为参考点的长方体。这里Ortho的6个参数均自带正负号。
例子: eye = [ 80, 0, 0 ] ,center=[ 80, 0, -1 ]说明从eye看向center点,up=[ 0, 1, 0 ] glOrtho ( -10, 20, 0, 30, 10, 20),表示的视景体是[ 70, 100 ]*[ 0, 30 ]*[ -10, -20 ]。注意到本例中eye并不在视景体里面。
红点是eye,蓝色箭头是看的方向(也就是center-up),视景体是ABCDEFGH,最后在屏幕上显示的是将EFGH面压向ABCD(就是说是从ABCD面看向这个视景体)。
再给几个例子。eye = [0,0,0],center = [1,1,0],up = [ -1, 1, 0],glOrtho = [ -20, 20, -10, 10, -5, 5 ]
eye在原点,看向center这个点,头顶朝up。那么ABCDEFGH为视景体,EFGH是left面,ABCD是right面,ABFE是zNear面,DCGH是zFar面,BCGF是bottom面,ADHE是top面。ABDC在 z = 20,EFGH在 z = -20 , ABFE和DCGH都垂直于center-eye这个向量。最后在显示器上的是从ABFE看这个视景体,即将DCGH压向ABFE。
对于上面的例子,仅将center改成(-1, -1, 0),即与图中的center方向相反,则EFGH是right面,ABCD是left面,ABFE是zFar面,DCGH是zNear面,BCGF是bottom面,ADHE是top面
以上,知道怎么定义视景体了:假设人站在eye处,眼睛看向center这个点,头顶朝着up这个点。这3个值固定后你的头也就完全固定住了。left和right分别确定了头左右2边范围,注意,头左边的值是负的!也就是说,如果left= -10,right=10表示从头左边10到头右边10的范围,但是当left=5,right=10,表示的却是头右边5到10的范围。bottom和top表示头下方和上方的范围,bottom = -10, top=10,说明从头下面10到头上面10,bottom = 5, top=10,表示头上面5到10。zNear和zFar表示头(眼睛)后前的范围,zNear = -10, zFar=10,表示从眼睛后面10到眼睛前面10,zNear = 5, zFar=10,表示从眼前5到10。注意,上面的顺序都可以交换,比如left=5,right=10和left=10,right=5,表示的左右范围都是一样的,并且这个改变不会影响你的观察结果,但是!建议按从左到右,从下到上,从后到前的顺序。最终的观察方向是由LookAt函数决定,Ortho只是在LookAt给定的条件下创建可视区域(视景体)。
gluPerspective也和上面的Ortho差不多。gluPerspective( fovy, aspect, zNear, zFar ),他和Ortho不同的是zNear和zFar必须大于0,也就是说在LookAt条件下(如不显示调用,仍有默认值),只能是在眼睛前面的视景体,不能裁剪到眼睛后面,至于zNear和zFar是否一定要求 Near > Far 这个我没试过,但是在编程的时候还是这么认为吧,免得出错。
注意:
1、GL编程中,有这样的要求:视点变换在模型变换之前指定,但投影变换和视口变换可以在绘图之前的任意时候指定。世界坐标系中v点由3D到2D(这里2D不是屏幕坐标,若到屏幕还要经过视口变换)是经过变换:ProjectinMatrix * ModelViewMatrix * v,LookAt是ModelViewMatrix一部分,Ortho和Perspective都是ProjectinMatrix的一部分。