OpenGL是一個開放的系統,它是獨立於任何視窗系統或作業系統的。儘管它包含了許多圖形函數,但它卻沒有視窗函數,也沒有從鍵盤和滑鼠讀取事件的函數,所以要初學者寫出一個完整的圖形程式是相當困難的。另外,OpenGL圖形函數中只提供基本的幾何原形:點、線、多邊形,因此要建立基本的三維幾何體如球、錐體等,也很不容易。而OpenGL輔助庫就是為解決這些基本問題專門設計的,它提供了一些基本的視窗管理函數和三維圖形繪製函數,能協助初學者儘快進入OpenGL世界,掌握關鍵的三維圖形技術,體會其中奇妙的樂趣。但是,對於複雜的應用,這些函數遠遠不夠,只能作為參考。
6.1、輔助庫函數分類
這一節內容可以作為手冊查閱,初學者不必深究。
輔助庫函數大致分為六類:
6.1.1 視窗初始化和退出
相關函數有三個,它們在第一章已提到,這裡將詳細介紹:
void auxInitWindow(GLbyte *titleString)
開啟一個由auxInitDisplayMode()和auxInitPosition()指定的視窗。函數參數是視窗標題,視窗背景預設顏色是RGBA下的黑色或顏色表(color_index)下的0號調色盤的顏色。按下Escape鍵可以完成關掉視窗、結束程式、全部清屏三項功能。
void auxInitDisplayMode(GLbitfield mask)
設定視窗顯示模式。基本模式有RGBA或顏色表、單或雙緩衝,也可指定其他附加模式:深度、模板或累積緩衝(depth,stencil,and/or accumulation buffer)。參數mask是一組位標誌的聯合(取或),AUX_RGBA或AUX_INDEX、AUX_SINGLE或AUX_DOUBLE,以及其它有效標誌AUX_DEPTH、AUX_STENCIL或AUX_ACCUM。
void auxInitPosition(GLint x,GLint y,GLsizei width,GLsizei height)
設定視窗位置及大小。參數(x, y)為視窗的左上方點的螢幕座標,參數(width, height)為視窗的寬度和高度,單位為象素,預設值為(0, 0, 100, 100)。
6.1.2 視窗處理和事件輸入
當視窗建立後,且在進入主函數迴圈之前,應當登記以下列出的回呼函數(callback function):
void auxReshapeFunc(void(*function)(GLsizei,GLsizei))
定義視窗改變時形狀重定函數。參數function是一個函數指標,這個函數帶有兩個參數,即視窗改變後的新寬度和新高度。通常,function是glViewport(),顯示裁減後的新尺寸,重定義投影矩陣,以便使投影后映像的比例與視點匹配,避免比例失調。若不調用auxReshapeFunc(),預設重定物體形狀的函數功能是調用一個二維的正射投影矩陣。運用輔助庫,視窗將在每個事件改變後自動重新繪製。
void auxKeyFunction(GLint key,void(*function)(void))
定義鍵盤響應函數。參數function就是當按下key鍵時所調用的函數指標,輔助庫為參數key定義了幾個常量:AUX_0至AUX_9、AUX_A至AUX_Z、AUX_a至AUX_z、AUX_LEFT、AUX_RIGHT、AUX_UP、AUX_DOWN(方向鍵)、AUX_ESCAPE、AUX_SPACE或AUX_RETURN。
void auxMouseFunc(GLint button,Glint mode,void(*function)(AUX_EVENTREC *))
定義滑鼠響應函數。參數function就是當滑鼠以mode方式作用於button時所調用的函數。參數button有AUX_LEFTBUTTON、AUX_MIDDLEBUTTON或AUX_RIGHTBUTTON(以右手為標準)。參數mode代表滑鼠觸擊狀態,擊中時為AUX_MOUSEDOWN,釋放時為AUX_MOUSEUP。參數function必須帶一個參數,它是指向結構AUX_EVENNTREC的指標。當函數auxMouseFunc()被調用時將為這個結構分配相應的記憶體。通常用法類似如下:
void function(AUX_EVENTREC *event)
{
GLint x,y;
x=event->data[AUX_MOUSEX];
y=event->data[AUX_MOUSEY];
...
}
6.1.3 顏色表裝入
因為OpenGL本身沒有視窗系統,所以依賴於視窗系統的顏色映射就沒法裝入顏色尋找表。如果採用顏色表模式,就要用到輔助庫提供的用RGB值定義的單個色彩索引函數:
void auxSetOneColor(GLint index,GLfloat red,GLfloat green,GLfloat blue)
設定自訂色彩的索引。參數index即索引號,參數red、green、blue分別為紅、綠、藍值,範圍在(0~1)內。
6.1.4 三維物體繪製
每組三維物體包括兩種形式:網狀體(wire)和實心體(solid)。網狀體沒有平面法向,而實心體有,能進行光影計算,有光照時採用實心體模型。下面這些函數的 參數都是定義物體大小的,可以改變。
| 功能 |
函數 |
| 繪製球 |
void auxWireSphere(GLdouble radius) void auxSolidSphere(GLdouble radius) |
| 繪製立方體 |
void auxWireCube(GLdouble size) void auxSolidCube(GLdouble size) |
| 繪製長方體 |
void auxWireBox(GLdouble width,GLdouble height,GLdouble depth) void auxSolidBox(GLdouble width,GLdouble height,GLdouble depth) |
| 繪製環形圓紋面 |
void auxWireTorus(GLdouble innerRadius,GLdouble outerRadius) void auxSolidTorus(GLdouble innerRadius,GLdouble outerRadius) |
| 繪製圓柱 |
void auxWireCylinder(GLdouble radius,GLdouble height) void auxSolidCylinder(GLdouble radius,GLdouble height) |
| 繪製二十面體 |
void auxWireIcosahedron(GLdouble radius) void auxSolidIcosahedron(GLdouble radius) |
| 繪製八面體 |
void auxWireOctahedron(GLdouble radius) void auxSolidOctahedron(GLdouble radius) |
| 繪製四面體 |
void auxWireTetrahedron(GLdouble radius) void auxSolidTetrahedron(GLdouble radius) |
| 繪製十二面體 |
void auxWireDodecahedron(GLdouble radius) void auxSolidDodecahedron(GLdouble radius) |
| 繪製圓錐 |
void auxWireCone(GLdouble radius,GLdouble height) void auxSolidCone(GLdouble radius,GLdouble height) |
| 繪製茶壺 |
void auxWireTeapot(GLdouble size) void aucSolidTeapot(GLdouble size) |
| 表6-1 |
以上物體均以各自中心為原點繪製,所有座標都已單位化,可以縮放。
6.1.5 背景過程管理
void auxIdleFunc(void *func)
定義空閑狀態執行函數。參數func是一個指標,指向所要執行的函數功能。當它為零時,func執行無效。
6.1.6 程式運行
void auxMainLoop(void(*displayFunc)(void))
定義情境繪製迴圈函數。displayFunc指標指向情境繪製函數。當視窗需要更新或情境發生改變時,程式便調用它所指的函數,重新繪製情境。
6.2、輔助庫應用樣本
下面舉一個輔助庫的應用例子,testaux.c:
例6-1 輔助庫應用常式 testaux.c
#include "glos.h"
#include <GL/gl.h>
#include <GL/glaux.h>
void myinit(void);
void CALLBACK myReshape(GLsizei w,GLsizei h);
void CALLBACK display(void);
void myinit(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
void CALLBACK myReshape(GLsizei w,GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0);
else
glOrtho(-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void CALLBACK display(void)
{
glColor3f(1.0,1.0,0.0);
auxWireSphere(1.0);
glFlush();
}
void main(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("AUX_SAMPLE");
myinit();
auxReshapeFunc(myReshape);
auxMainLoop(display);
}
以上程式運行結果是在螢幕視窗內繪製一個黃色的網狀球體,這個程式充分體現了輔助庫的基本應用方法。
首先,在主函數中用輔助庫函數定義一個視窗auxInitWindow(),然後初始化顏色myinit(),這些在第一章中已說明。接下來是兩個十分重要的函數auxReshapeFunc()和auxMainLoop(),參數都是一個函數指標,指向的都是回呼函數(回呼函數定義用CALLBACK說明)。
前者是視窗形狀重定函數,參數指標指向函數myReshape(),它的兩個參數就是視窗的新寬度和新高度。然後用glViewport(0, 0, w, h)重定視口,並且在新視口內重新定義投影矩陣,
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0);
else
glOrtho(-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5,-10.0,10.0);
即先用glMatrixMode()說明當前矩陣操作與投影有關GL_PROJECTION,再用glLoadIdentity()將矩陣清為單位矩陣,避免受其它矩陣操作的幹擾;然後調用glOrtho()對物體進行正射投影,並且用判斷語句給出了兩種情況,使投影后映像的比例與視點匹配,避免比例失調。
再下來調用glMatrixMode()將矩陣操作改為對觀察物體有關的方式GL_MODELVIEW,同樣用glLoadIdentity()清矩陣。後者是主函數迴圈函數,參數指標指向函數display(),即繪製物體。當視窗需要更新或物體發生改變時,程式便調用它重新繪製。以上例子是輔助庫的最基本應用,複雜的應用將在後續的章節中詳細介紹。