從本節開始,我們使用SharpGL帶的VS2010擴展,來直接生成SharpGL工程。
如果你新建項目時,沒有看到下面的SharpGL項目,那麼請事先在SharpGL源代碼中找到一個叫 ”SharpGL 2.0 Visual Studio Extension“目錄 ,安裝名為 SharpGL.vsix的vs2010擴展, 然後重啟你的vs2010.
利用上面的SharpGL項目,直接生成一個完整的SharpGL工程,它帶有Opengl窗體控件,基本代碼已經都完成了, 你只需要修改3D繪圖部分的代碼就可以了。
生成的工程是還可以直接跑起來看到效果, 如下圖所示。
我們會看到了有個三稜體已經畫好了,並且還正在旋轉,下面還動態顯示了渲染的幀數。
我們在前二篇寫的代碼生成的三角形像是2D的,現在如上圖這樣的效果,就感覺很有立體感覺了。其實,兩者不一樣的只是因為這個工程默認已經進行了投影變換和視點變換。
當三維體放在世界坐標系中後,由於顯示器只能用二維圖像顯示三維休,因此必須要依賴投影來把三維體降低維數。
投影變換的目的就是定義了一個視景體,使得視景體外多余的部分不會顯示。
投影包括透視投影(perspective projection)和正視投影(orthographic projection)兩種。
上圖就是透視投影的效果,它符合人的觀察經驗,即離視點近的物體大,離視點遠的物體小,遠到極點就消失,成為滅點。就像筆直馬路的盡頭看上去就成為一個點。
我們看一下代碼中有關投影部分的代碼, 解釋一下相關功能函數的參數意義。
1 private void openGLControl_Resized(object sender, EventArgs e) 2 { 3 // TODO: Set the projection matrix here. 4 OpenGL gl = openGLControl.OpenGL; 5 gl.MatrixMode(OpenGL.GL_PROJECTION); 6 gl.LoadIdentity(); 7 8 gl.Perspective(20.0f, (double)Width / (double)Height, 0.01, 100.0); 9 gl.LookAt(-5, 5, -5, 0, 0, 0, 0, 1, 0); 10 11 gl.MatrixMode(OpenGL.GL_MODELVIEW); 12 }
創建透視效果的函數名和原型為:
Perspective(double fovy, double aspect, double zNerar, double zFar);
aspect是窗口的縱橫比
zNerar,zFar分別是近處和遠處的裁面位置。
fovy是控制視野在XY平面的角度,范圍是0--180度。你可以把它想象成是3dsmax中的相機鏡頭對應的視野參數。
下面的Perspective函數的示意圖中, 視角指的是參數fovy, aspect=w/h, zNerar為近平面距離, zFar為遠平面距離.
對於比較難以理解的參數fovy, 如果你仍然不是太明白,下面換個方式說明一下.
我們拿3dsmax的攝像機參數來做比喻(意義是類似的),上圖是我們使用15mm鏡頭(視野為100.389度)看到的效果。小鏡頭看到的視野更大。攝影裡面叫這種小鏡頭叫廣角鏡頭。
現在使用85mm的鏡頭(視野為23.913度),只可以看到物體的局部了。它的可視范圍變窄了。
那麼 Perspective()函數的fovy參數的意義就等同於鏡頭所代表的視野度數。
設置好投影變換後, 接下來還要設置視點變換.
設置視點變換的函數LookAt的原形為:
LookAt(double eyex, double eyey, double eyez, double centerx, double centery, double centerz, double upx, double upy, double upz);
這個函數是做視點變換用的,你可以認為它是設置攝像機的函數。
在opengl中,默認時視點定位於坐標系的原點,初使方向指向Z軸負方向,前面說過,默認的三維模形也是貼著世界坐標系的Z軸0的深度上放置的, 因此,如果不進行視點變換,則相當於攝像機正好貼著物體,什麼也看不見,這就是為什麼上節的代碼裡面要有一句代碼gl.Translate()用於把把物體往Z軸負方向移動一定距離的原因。
我們還是以3dsmax中的攝像機來類比。下面的示意圖中,我們使用的是一種被稱為”目標攝像機“的相機,之所以這麼稱謂,是因為為這個攝像機帶一個目標點可以調節。
前三個參數 eyex, eyey, eyez 表示攝像機本身位於世界坐標系中的位置。
在3dsmax中,攝像機的位置可以任意平移的.
上圖我們放置的位置是XY軸剛好對著世界坐標系的原點。Z軸朝正方向走了老遠。因為攝像機離物體遠了,因此可以正常看到物體。
上圖中,攝像機的XYZ都遠離了物體做了變換,相當於在圍繞三維體進行觀察。
當中三個參數 centerx, centery, centerz 相當於調整了3dsmax目標攝像機的目標點位置。
如上圖所示, 改變目標點的位置也有類似圍繞觀察對象的效果。並且,這個目標點在Z軸上相對於物體的距離是沒有什麼意義的,主要意義是在XY上的變化上。這一點讀者可以自己去試驗。
最後三個參數 upx, upy, upz相當於在旋轉3dsmax目標攝像機。
不過這個參數的值並不是角度值,而是向量,數值的大小沒意義,正負值才有意義。
在3dsmax中,攝像機是可以任意角度旋轉的。
但是在Lookat()函數中這最後三個參數, upx,upy 只能在上下,左右,45度這幾個角度中變換,而且upz取值似乎沒什麼意義。
解釋完這兩個函數,我們用程序繪制一個三角形來測試一下上述視點變換和投影變換的效果。
上圖是視野為20的效果,可以看到三角形看上去大些了。
視野改為60,三角形看上去小些了。
以上結果和上面分析Perspective()函數的fovy參數時結論是一致的。
現在我們改動LookAt的前三個參數,三角形正對著我們顯示了。
現在我們改變LookAt的最後三個參數,Y向量改為-1,相當於攝像機旋轉向下180度,結果三角形朝下了。
為了節約下載空間,以後的源代碼中,筆者都把SharpGL的三個dDLL文件都刪除了。
請你自己把這三個dll文件拷貝到: ”Dependencies“, "bin\debug\" 這兩個目錄中去。再打開工程。
以後不在贅述。
本文源代碼下載