這是susu給我的一份關于glut的示例代碼,裡面涉及到的内容有:用glut來完成菜單管理,文本顯示,顯示清單,材質,光照,多視窗顯示,滑鼠事件處理,鍵盤事件處理,菜單事件處理,視窗建立,縮放,銷毀,動畫播放,定時器等功能,運作效果如圖:
我分成幾個部分來對代碼進行分析:
1,指令行參數檢查
void checkArgs(int argc, char *argv[])
{
int argp;
GLboolean quit = GL_FALSE;
GLboolean error = GL_FALSE;
#define AA argv[argp]
argp = 1;
while (argp < argc)
{
if (match(AA, "-help"))
{
commandLineHelp();
quit = GL_TRUE;
}
else if (match(AA, "-version"))
printf(VERSIONLONG "\n");
else if (match(AA, "-auto"))
{//自動運作
demoMode = GL_TRUE;
else if (match(AA, "-scale"))
{//放縮
argp++;
scaleFactor = atof(argv[argp]);//設定縮放因子
else
{//出錯處理
fprintf(stderr, "Unknown arg: %s\n", AA);
error = GL_TRUE;
}
argp++;
}
GLboolean match(char *arg, char *t)
if (strstr(t, arg))
return GL_TRUE;
else
return GL_FALSE;
}
if (error)
commandLineHelp();
exit(1);
if (quit)
exit(0);
這裡match函數考慮到-help可能被輸入為-h等形式,是以用的是strstr而不是strcmp來進行字元串的比對。
2,視窗的縮放
通過對視窗原點和大小的調整就可以實作視窗的縮放。
int pos[MAXWIN][2] =
{//各個視窗的左上角坐标
{50, 150}, /* win 0 */
{450, 150}, /* win 1 */
{50, 600}, /* win 2 */
{450, 600}, /* win 3 */
{10, 10}, /* subwin 4 (relative to parent win 0) */
{300, 400}, /* help win 5 */
{850, 150}, /* cmap win 6 */
{850, 600}, /* cmap win 7 */
{250, 450} /* text win 8 */
};
int size[MAXWIN][2] =
{//各個視窗大小(寬度,高度)
{350, 350}, /* win 0 */
{350, 350}, /* win 1 */
{350, 350}, /* win 2 */
{350, 350}, /* win 3 */
{200, 200}, /* subwin 4 */
{700, 300}, /* help win 5 */
{350, 350}, /* cmap win 6 */
{350, 350}, /* cmap win 7 */
{800, 450} /* text win 8 */
void scaleWindows(float scale)
{//放縮初始視窗大小和位置
int i;
for (i = 0; i < MAXWIN; i++)
pos[i][0] = pos[i][0] * scale;//x坐标
pos[i][1] = pos[i][1] * scale;//y坐标
size[i][0] = size[i][0] * scale;//寬度
size[i][1] = size[i][1] * scale;//高度
3,設定顯示模式、
Int型的數組modes用來記錄各個模式位的值(0或者1),進而表明視窗是否支援這種模式。displayMode |= glutMode[i];通過這樣的按位或運算最終獲得視窗的顯示模式。
int modes[MODES] ={0};
modes[RGBA] = 1;
modes[DOUBLEBUFFER] = 1;
modes[DEPTH] = 1;
setInitDisplayMode()
void setInitDisplayMode(void)
{//設定初始顯示模式
displayMode = 0;
for (i = 0; i < MODES; i++) {
if (modes[i]) {
/* printf("Requesting %s \n", modeNames[i]); */
displayMode |= glutMode[i];//進行按位或運作,
glutInitDisplayMode(displayMode);
createMenu6();
if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
warning("This display mode not supported\n");
4,菜單管理
menu1到menu8這8個int型變量用來儲存建立的菜單項,并且menu2到menu8都作為menu1的子菜單加入到menu1中。
建立菜單
5,建立視窗
本文中建立的視窗有4種類型,第1種是普通的RGB視窗,用來顯示要繪制的圖形,第2種是第1種視窗的子視窗(類似于“畫中畫”的效果),第3種是文本視窗和幫助視窗,第4種是顔色索引視窗。設定好視窗的顯示模式,并根據儲存的視窗大小和位置建立完視窗後,就可以對視窗進行OpenGL繪制的初始化工作,這是在gfxInit函數中完成的,最後就是為視窗加上各種事件處理函數。
建立視窗
為每個視窗初始化OpenGL時,首先通過redefineShapes為視窗建立其顯示清單,然後渲染其背景矩陣,接着進行投影變換和視圖變換,為了簡單起見,作者采用了預設的白色光源來進行材質和光源位置的設定,最後就是啟用光照并設定視窗的背景顔色。
OpenGL初始化
6,動畫效果
我在MFC中是通過設定一個定時器,并且在定時方法中修改旋轉角度來重新整理螢幕的,進而實作動畫旋轉的效果,在這裡作者把這部分代碼放到視窗的空閑事件處理函數中進行。每次執行時角度都進行了變換,并且通知視窗強制其重繪。
/* idleFunc - GLUT idle func callback - animates windows */
void idleFunc(void)
if (!leftDown && !middleDown)//旋轉角度加1
angle += 1;
angle = angle % 360;
if (winId[i] && winVis[i] && !winFreeze[i])
glutSetWindow(winId[i]);
glutPostRedisplay();//強制重畫
7,自動示範
這裡采用了一個小的技巧來實作多個視窗連續建立的自動示範功能。通過執行目前的動作後,為下一個應該接着發生的動作設定一個定時器,進而實作動作之間的接連發送效果。
旋轉動畫
8,圖形繪制代碼部分
所有視窗都使用drawScene來繪制其圖形,隻是各個視窗調用的顯示清單不同而已,這通過各個視窗的辨別符來進行差別,并且通過調用trackBall(APPLY, 0, 0, 0, 0);來繪制滑鼠左鍵控制的結果(旋轉後的角度或者平移後的距離),如果視窗還有文本要顯示,則調用showText來顯示文本資訊。
圖形繪制代碼
9.文本顯示
這裡有兩種文本的顯示方式,第一種采用位圖字型來顯示文本,第二種采用Stroke 字型來顯示文本。
void textString(int x, int y, char *msg, void *font)
{//顯示文本,x,y是起始坐标,msg:要顯示的文本,font:顯示的字型
glRasterPos2f(x, y);//定位位圖字型
while (*msg)
glutBitmapCharacter(font, *msg);
msg++;
/* strokeString - Stroke font string */
void strokeString(int x, int y, char *msg, void *font)
glPushMatrix();
glTranslatef(x, y, 0);
glScalef(.04, .04, .04);
while (*msg)
glutStrokeCharacter(font, *msg);
glPopMatrix();
10,顯示清單
顯示清單由于是已經編譯好的代碼段,是以可以加快程式的速度。這裡每種要繪制的圖形(如球,茶壺等)都有實體和虛體兩種模式可以選擇。
顯示清單
11,滑鼠事件處理
這裡滑鼠有三種控制方式,1)左鍵進行旋轉。2)中鍵進行xy平面的平移。3)左鍵+中鍵進行關于Z軸的平移(産生縮放的效果)。滑鼠的事件模式這裡有RESET,MOUSEBUTTON,APPLY, MOUSEMOTION四種,其中RESET是用來對清空以往的操作,讓圖形回到原點處。MOUSEBUTTON是滑鼠按下激發的,用來記錄下滑鼠的位置,MOUSEMOTION是滑鼠按下後并移動滑鼠時,用來計算旋轉的角度或者平移的距離,而最終這些變換後産生的效果的繪制是APPLY發生的,在這裡進行了實際的旋轉和平移動作。
滑鼠控制
最後,代碼中還加入了對空間球,圖形闆,撥号按鍵盒的事件處理支援。