摘 要:針對OpenGL不包含窗口管理和事件檢測等功能的缺陷,GLUT(OpenGL Utility Toolkit)工具包對窗口和事件的管理工作進行標準化和簡化。簡要介紹GLUT的主要功能和安裝方法,給出一個基于GLUT的程序框架,詳細分析基于回調(diào)函數(shù)的事件管理、變換順序及堆棧操作、坐標系等技術(shù)。為更復(fù)雜的圖形程序設(shè)計提供基礎(chǔ)。
關(guān)鍵詞:GLUT程序框架;回調(diào)函數(shù);變換順序;堆棧操作
中圖分類號:TP391.9
文獻標識碼:B
文章編號:1004—373X(2008)04—071—03
OpenGL是國際上通用的開放式三維圖形標準,他包含大量高效的繪制函數(shù),具有移植性好、開放等優(yōu)點。Open—GL獨立于窗口系統(tǒng)和操作系統(tǒng),因此他沒有建立并管理窗口的函數(shù),也沒有檢測鼠標鍵盤事件的函數(shù)。但是在圖形程序中,不論是微軟的Windows還是Unix等,圖形均在窗口中展現(xiàn),因此圖形程序必須至少打開一個窗口。并且,圖形程序一般均有交互功能,包括使用人員和圖形程序之間的交互,以及圖形程序接受操作系統(tǒng)或窗口系統(tǒng)提供的服務(wù)。因此,在具體的操作系統(tǒng)和窗口系統(tǒng)下進行OpenGL圖形程序設(shè)計時,設(shè)計人員把相當多的時間與精力花費在窗口建立和管理、事件檢測與處理等與虛擬仿真關(guān)系并不緊密的環(huán)節(jié)上。例如在Windows下,設(shè)計人員必須關(guān)聯(lián)繪制描述表RC和設(shè)備描述表DC,必須設(shè)置超過20個元素的象素格式。在微軟基礎(chǔ)類庫MFC下,設(shè)計人員必須了解更為復(fù)雜的消息映射、類型識別、動態(tài)生成、命令傳遞等。這些不但增加了圖形程序開發(fā)的工作量,而且影響了圖形程序開發(fā)的效率。
GLUT(OpenGL Utility Toolkit)是Mark Kilgard開發(fā)的OpenGL實用工具包,他對窗口和事件的管理工作進行了標準化和簡化,而且被移植到各種OpenGL實現(xiàn)中,包括X窗口系統(tǒng)和微軟的視窗系統(tǒng)。利用GLUT開發(fā)OpenGL圖形程序,可以使設(shè)計人員以GLUT提供的程序框架為基礎(chǔ),集中精力進行圖形開發(fā),從而提高程序設(shè)計效率。
1 GLUT主要功能
GLUT提供了許多實用的功能,如多視窗的繪制、回調(diào)函數(shù)驅(qū)動的事件管理、支持多種輸入設(shè)備(鍵盤、鼠標、空間球等)、空閑事件與定時器、下拉式菜單管理、三維幾何模型繪制、位圖與字體等。下面介紹常用的一些功能。
1.1 窗口初始化
包括4個函數(shù)。函數(shù)glutInit用于初始化并處理命令行參數(shù)。函數(shù)glutlnitDisplayMode用于初始化顯示模式,如顏色為RGBA模式還是索引模式,使用單緩存還是雙緩存,是否使用深度緩存、模板緩存及累積緩存等。函數(shù)glutInitWindowPosition指定窗口左上角在屏幕上的位置。函數(shù)glutlnitWindowSize指定窗口的大小,以象素為單位。
1.2 事件處理
只有一個函數(shù)glutMainLoop,他用于顯示創(chuàng)建的窗口,處理輸入的事件,觸發(fā)回調(diào)函數(shù),進入循環(huán)直到程序退出。
1.3 窗口和菜單管理
窗口管理包含18個函數(shù),用于建立、銷毀窗口及可能的子窗口,管理和設(shè)置窗口的屬性。其中比較重要的如函數(shù)glutCreateWindow,用于建立一個新的頂層窗口,函數(shù)glutCreateSubWindow建立一個子窗口,函數(shù)glutPos—tRedisplay用于提醒glutMainLoop調(diào)用注冊的顯示回調(diào)函數(shù),函數(shù)glutSwapBuffers用于交換當前窗口的前后緩沖。菜單管理用以設(shè)計簡單的下拉式菜單,包含11個函數(shù),如創(chuàng)建菜單函數(shù)glutCreateMenu,glutAddMenuEntry,設(shè)置當前菜單glutSetMenu等函數(shù)。
1.4 回調(diào)函數(shù)注冊
GLUT中有20個回調(diào)函數(shù),用于響應(yīng)用戶事件。最重要的回調(diào)函數(shù)是glutDisplayFunc,當GLUT認為需要重新顯示窗口內(nèi)容時,都將執(zhí)行這一函數(shù)注冊的回調(diào)函數(shù)。另外一些重要的回調(diào)函數(shù)注冊函數(shù)有,函數(shù)glutRe—shapeFunc用于注冊窗口大小改變這一事件發(fā)生時GLUT將調(diào)用的函數(shù)。glutKeyboardFunc和glutMouseFunc用于注冊鍵盤和鼠標事件發(fā)生時的回調(diào)函數(shù)。函數(shù)glutMo—tionFunc注冊鼠標移動事件的回調(diào)函數(shù)。這3個函數(shù)用于人機交互處理。在沒有其他事件處理時,GLUT將調(diào)用函數(shù)glutIdleFunc注冊的函數(shù),而函數(shù)glutTimerFunc則注冊處理定時器事件的函數(shù)。
1.5幾何建模函數(shù)
OpenGL繪圖函數(shù)只能生成點、直線、多邊形等簡單的幾何圖元,GLUT提供了18個創(chuàng)建三維物體的函數(shù)。利用他們可以創(chuàng)建9種三維物體,如圓錐體、立方體、球體等,每一物體有線框和實體2種方式。
2 GLUT的安裝
在WindowsXP/Visual C++6.0下進行GLUT編程時,首先要進行OpenGL的基本設(shè)置,然后再進行GLUT設(shè)置。
2.1 OpenGL基本設(shè)置
進行OpenGI,基本設(shè)置時,必須加入3個OpenGL庫,分別是opengl32.lib,glu32.lib和glaux.lib。具體的方法是在Visual C++6.0環(huán)境中,依次選擇“項目”,“設(shè)置”,“鏈接”,“對象/庫模塊”,然后添加\"opengl32.lib glu32.libglaux.lib”,必須注意3個文件之間的分隔符不是逗號而是空格。在程序開發(fā)時,必須包含2個OpenGL頭文件,即gl.h和glu.h。在Visual C++6.0中,還需要在這兩個文件之前包含頭文件windows.h,這是因為在gl.h和glu.h中使用了一些在windows.h中定義的宏。
2.2 GLUT的安裝
GLUT的安裝包括3項內(nèi)容。
(1)將glut32.dll文件復(fù)制到操作系統(tǒng)的System32或System目錄下;
(2)將glut.h文件復(fù)制到Visual C++安裝目錄下的Include\GI.文件夾下;
(3)將glut32.lib文件復(fù)制到到Visual C++安裝目錄下的Lib文件夾下;
上述設(shè)置結(jié)束后,在編程應(yīng)用中,將頭文件glut.h包含在gl.h和glu.h之后即完成GLUT的安裝設(shè)置。
3 GLUT的程序框架
基于GLUT的OpenGL圖形程序包含了主函數(shù),顯示回調(diào)函數(shù)display和窗口大小改變時的回調(diào)函數(shù)re—shape,一個相對完整的GLUT程序基本框架如下所示。
為使結(jié)構(gòu)清晰,將一次性設(shè)置放在一個函數(shù)init中,可在init函數(shù)中設(shè)置諸如打開光源、深度測試等。在主函數(shù)中,調(diào)用顯示回調(diào)函數(shù)display以在必要時重新顯示窗口圖形,回調(diào)函數(shù)reshape響應(yīng)窗口大小改變這一事件。最后調(diào)用函數(shù)glutMainLoop進入事件處理循環(huán)直到程序結(jié)束。
4 值得注意的問題
4.1 事件管理
GLUT中事件管理相當方便。即只要在主函數(shù)中注冊相應(yīng)的回調(diào)函數(shù),然后在回調(diào)函數(shù)中編寫響應(yīng)事件的代碼即可。例如對于得理鼠標事件的回調(diào)函數(shù)mouse,先調(diào)用函數(shù)glutMoseFunc對mouse進行注冊:glutMouseFunc(mouse);然后在注冊的回調(diào)函數(shù)mouse中編寫響應(yīng)事件的代碼即可:
GLUT中注冊函數(shù)的原型有一致的格式,即glut***Fune,同時回調(diào)函數(shù)的返回值均為void型,一致的格式有助于提高程序開發(fā)的效率。
4.2 變換過程
在OpenGL中模型從建立到顯示于計算機屏幕上要經(jīng)過一系列的變換。這一過程包括視點變換、模型變換、投影變換和視口變換。在GLUT程序框架中,明確給出這4種變換的函數(shù)調(diào)用。
在display中給出視點變換和模型變換。視點變換調(diào)用的是實用函數(shù)gluLookAt,其參數(shù)分別定義視點位置、視線方向和向上方向。由于視點變換可以由模型變換的反方向變換來模擬完成,因此,視點變換和模型變換可以用一個變換模式。即在reshape函數(shù)中以參數(shù)GL MOD—ELVIEW調(diào)用函數(shù)glMatrixMode。對于模型變換,上述框架中為縮放變換,即通過調(diào)用glSalef函數(shù)完成,也可以根據(jù)需要進行平移變換,即調(diào)用glTranslate函數(shù)。
在reshape函數(shù)中給出了投影變換和視口變換。投影變換有正投影和透視投影2種方式,框架中給出的是正投影、調(diào)用函數(shù)glOrtho、透視投影調(diào)用函數(shù)glFrutrum、或者調(diào)用gluPerspectvie函數(shù),用以設(shè)置投影體的位置和大小。視口變換其實是一種比例變換,用以將投影映射到計算機屏幕上。另外必須注意的是,GLUT的屏幕坐標系與OpenGL有所不同:OpenGL的屏幕坐標系原點在窗口左下角,x軸向右,y軸向上;而GLUT屏幕坐標系原點在窗口左上角,x軸向右但y軸向下。
4.3 兩個坐標系
通常在圖形程序中要對模型進行多種變換,變換順序不同,變換結(jié)果也不相同。這是因為變換的本質(zhì)是矩陣乘法,而矩陣乘法不滿足交換率。因此變換的順序是圖形程序開發(fā)時必須注意的一個重要問題。
對于變換有2種考慮方法:一種是在全局坐標系,另一種是局部坐標系。在全局坐標系下考慮變換時,模型的平移和旋轉(zhuǎn)均是針對全局坐標系的,此時全局坐標系固定不動,變換的是模型的大小或位置。這一方式有助于確定變換后的模型在全局坐標系中的絕對位置,但缺點是,程序代碼與變換順序相反,即如果要先平移后旋轉(zhuǎn),則在程序代碼中先調(diào)用glRotatef函數(shù)后調(diào)用glTranslate函數(shù)。在局部坐標系下考慮變換時,設(shè)想局部坐標系是固接于模型上的,因此變換過程中模型和坐標系均是變化的。在此情況下,模型的變換是圍繞局部坐標系的,這一方法的優(yōu)點是,程序代碼與變換順序相同。這在開發(fā)諸如機器人等圖形程序時相當方便。但這一方法的不足之處是,由于坐標系隨模型同時變換,當存在不均勻的縮放變換時,即模型沿各坐標軸的縮放系數(shù)不一樣時,坐標系各軸同樣進行了縮放,這一縮放影響到后續(xù)的平移變換。針對這一情況可以利用堆棧操縱函數(shù)解決,即利用glPushMatrix函數(shù)保存當前狀態(tài),而用glPopMatrix函數(shù)恢復(fù)當前狀態(tài)。
4.4 動畫實現(xiàn)
動畫是圖形程序的重要特色之一。動畫實現(xiàn)有多種方式,例如在GLUT程序框架中不斷改變視點位置即可達到動畫效果,或者不斷改變模型位置和方向也可以實現(xiàn)。在GLUT中可以利用空閑時間注冊函數(shù)glutldel—Fune或定時器注冊函數(shù)glutTimerFunc實現(xiàn)動畫功能。為了提高刷新效率,可以利用GLUT提供的前后緩存交換繪制函數(shù)glutSwapBuffers,此時要在顯示模式函數(shù)中開啟雙緩存選項GLUT DOUBLE。
5 結(jié) 語
本文介紹了GLUT的基本功能和安裝設(shè)置,他可以讓設(shè)計人員集中精力進行圖形程序設(shè)計。給出GLUT程序框架,詳細介紹了框架中矩陣變換在程序中的具體實現(xiàn),變換順序?qū)ψ儞Q結(jié)果的影響。詳細介紹了坐標變換在全局坐標系和局部坐標系下的考慮方式及各自特點。在此框架基礎(chǔ)上,可以進行更復(fù)雜的圖形程序開發(fā)。