C#應用視頻教程2.4 OPENGL虛擬仿真介紹
這一部分我們首先實現視圖控制(包括了平移/旋轉/縮放),前面我們已經講過,通過lookat一個函數,或者通過translate+rotate兩個函數,都能實現視圖的控制(兩個函數的方式比較簡單,但是通用性不夠,因為這個更像是畫布就像去參觀賣房子的模型,你可以把模型隨便上下左右移動翻轉看外面,但是如果要像第一人稱視角到房子裏面爬窗戶,上房頂,鉆地道,這種視角肯定是不夠的。可以想象CS遊戲中,整個地圖場景必然是唯一的,每個遊戲玩家都可以控制一組視角,視角的lookat九個參數不同導致了可以仰望,俯瞰,左右掃等等,有興趣的讀者可以去仔細研究實現方法)
?
然而能用按鈕控制還是不夠方便,很多時候我們需要像Solidworks軟件這樣能夠用鼠標鍵盤控制,我自己設定的一些簡單規則:
鼠標可以控制視圖前後左右翻轉
按住Shift+鼠標可以控制視圖前後左右平移
鼠標滾輪可以控制視圖縮放
按住Ctrl,鼠標滾輪可以控制視圖繞Z旋轉
?
根據這些規則,我們需要在控件初始化的時候添加一組事件綁定(註意要用C#自動補全的方式做,不然後面的參數你不知道怎麽寫的,比如綁定到KeyDown事件,響應的是KeyEventArgs e,我們可以采集到鍵盤的按鍵,如果你自己寫就不知道是什麽參數類型了)
?
這些事件的綁定你也可以在主窗口中選中指定的控件,查看他所有的事件,雙擊進去(但是不符合面向對象的寫法,假如我們完善了這個類以後要寫一個新的項目,難道你每次拖完了這個OPENGL的控件,然後切換到這裏,一個一個把事件雙擊進去生成,然後再復制粘貼代碼?肯定效率很低,比較好的做法是自己定義一個類,然後每次初始化只要把這個OPENGLControl類型傳遞過去,所有的事件響應就一次完成了)
?
在這麽多的事件響應中,我們先來看比較簡單的幾組,鼠標移入和鼠標移出是判斷鼠標是否在控件上的(為了防止在鼠標在窗口的其他地方點擊按鈕,操作也會影響視圖,我們定義只要鼠標離開了控件,則全局變量設置為false,就不再修改視圖了)。鼠標按下和鼠標擡起來是為了定義是否采集鼠標當前位置的(也是為了防止誤判,假定如果鼠標在控件內部移動,只有左鍵按下之後的移動操作才會產生影響,不按按鈕移動鼠標也不修改視圖,當然每次MouseDown的時候都要刷新一下當前的位置=記錄之前的位置)
?
鼠標移動的事件是真正產生效果的事件,我們每次鼠標往某個方向運動,如果期望視圖跟著發生改變,則實際上只要捕捉鼠標前後位置的差異,然後疊加到Translate或者Rotate的三個參數上即可(註意其實是兩個參數,因為我們是在二維的電腦屏幕上模擬三維的效果,鼠標只會有X,Y的數值,所以也只能映射到XY的平移或者繞XY的旋轉,所以後面會增加一些額外的規則定義Z的平移-縮放,Z的旋轉-旋轉視圖
?
講到縮放視圖,最方便的是用鼠標滾輪實現,鼠標滾輪上滾和下滾,e.Delta數值是正的和負的,為了防止太大的時候縮放的太快,所以如果已經ViewChangeTranslate很小,就縮放的再慢一點(也可以做成一個函數,越遠越小則縮放越快,這樣更符合用戶體驗)繞Z軸旋轉還是比較重要的,為了防止規則太多,我還是用鼠標滾輪實現(需要先按下Ctrl鍵),到這裏基本的視圖控制就完成了。
?
然後深入理解一下PushMatrix和PopMatrix方法,假定我們要繪制一個小型的機器人,僅僅用三個六面體來表示機器人的頭部和兩個手臂(註意盡量繪制一個小模塊的時候用一組push和pop包起來),我們後面詳細介紹具體繪制過程
?
在繪制基本物體的時候,註意不管你的物體尺寸多少,你的畫筆是保持不變的(僅僅Translate和Rotate可以修改畫筆的位置和姿態),所以我可以人為地調節紅色立方體塊的大小
?
接下來繪制手臂,如果期望手臂正好貼在紅色立方體塊的兩個,那麽就必須要把畫筆平移到下一個要繪制的立方體的底面中心位置(我們暫時還不考慮姿態,後面會講姿態的文字,如果不使用Rotate,則姿態將始終保持垂直於畫布),註意仔細體會畫筆挪動到新的位置之後的效果
?
在繪制B手臂的時候,如果直接從繪制A手臂的地方挪過去也可以(再平移整個紅色立方體的寬度就行了),但是只是對於簡單的幾何物體可以這樣做,如果繪制非常復雜的多邊形,很多時候我們自己也不知道畫筆在哪了,所以有必要從上一步畫筆還沒開始動的地方接著畫(因為B手臂跟A手臂是對稱的, 所以只要把某些Translate的正負號改一改就行了)下圖中從X-X1和X-X2過程基本類似,對稱(這也是編程中比較重要的化歸思想,不要產生新的問題,X1直接到X2就是新的問題,哪怕比X-X2更簡單,因為我們已經有了X-X1的經驗可以套用,就可以直接X-X2)
?
讓整個動畫元素動起來,其實只要把一些變量添加到整個繪制過程就可以了(我在這裏只是做了簡單的演示,比如兩個手臂的擺動,實際上你也可以為機器人添加腿,眼睛,腰部等等)
?
最後套用一點運動控制的思想,讓兩個旋轉的臂從A點走到B點,要求同時走到位(還是要考慮比較多的因素的,比如AB兩點沒有差距,或者只有一個旋轉臂有差距),大體思路可以概括成:
1 采集起點和終點的差值(數組)
2 獲取差值數組中的最大值(最遠距離)
3 根據給定的速度求總的時間(最遠距離/給定速度)
4 根據總的時間重新求每個軸的速度(每個軸的前後距離/總時間)
5 在線程中執行運動(用計時器,每隔一定時間生成一個新的時間,並用S=S0 + V*t的公式計算每次新的位置)
?
總結:到此為止OPENGL的簡單介紹就結束了,網上有大量的代碼介紹OPENGL的仿真(C++的比較多,因為C#相對於C++的性能還是差很多,所以大型的遊戲,3D處理軟件都會用C++作為最終的編程執行工具,可能C#是嵌套的上層交互用的),但是並不妨礙我們通過C#加深對OPENGL的理解(核心思想沒有變,而且C#的開發,驗證效率更高)。讀者需要掌握:
1 理解OPENGL的基本繪圖過程,平移,旋轉,縮放的
2 理解OPENGL繪制基本物體,組合物體的原理,比如小型的擺臂機器人實現原理
3 查看網上的高手的代碼,針對某一些具體的功能做深入的研究,OPENGL除了能繪制二維三維的物體,還能做動力學仿真,模型的渲染等,學好這部分內容還是很有意義的
?
?
更多教學視頻和資料下載,歡迎關註以下信息:
我的優酷空間:
http://i.youku.com/acetaohai123
?
我的在線論壇:
http://csrobot.gz01.bdysite.com/
?
問題交流:
QQ:910358960
郵箱:[email protected]
?
?
C#應用視頻教程2.4 OPENGL虛擬仿真介紹