Lighthouse3d.com >> GLUT Tutorial >> Subwindows >> Creating and Destroying Subwindows
利用GLUT我們可以定義子窗體,例如切分主窗體到不同區域,每個子窗體有自己的OpenGL上下文和回調函數.一個可行的程序是可以同時提供幾種相同場景的視覺.
為了創建子窗體,我們可以使用glutCreateSubWindow函數,原型如下:
int glutCreateSubWindow(int parentWindow, int x, int y, int width, int height);
parentwindow - 父窗體的ID
x, y - 子窗體的左上角,相對於父窗體的原始
width, height - 子窗體的大小
父窗體的ID是創建父窗體時的返回值.下面代碼顯示了關系:
mainWindow = glutCreateWindow("SnowMen from Lighthouse3D"); ... subWindow1 = glutCreateSubWindow(mainWindow, 10,10,100,100);
一個子窗體也是變成其它子窗體的父窗體.根據GLUT的說明文檔,窗體可以任意嵌套.
前面說過,一個子窗體有自己的OpenGL上下文,如果我們要用VBOs時,需要為每個窗體和子窗體創建它們.回調函數也一樣.
最低限度我們必須用glutDisplayFunc函數為每個窗體注冊顯示函數.我們還必須為每個窗體注冊光標更改和鼠標事件控制的回調函數,如果我們要用到這些特性的話.彈出菜單也分配給一個特定的窗體.注意的是,空閑函數只有一個.
假定我們要創建三個視覺.一個主鏡頭,另一個是頂部視覺,在主鏡頭的中間,第三個是在旁邊,也是在主鏡頭的中間.下面是例圖:

下面是初始化必需的一個更完整的版本.我們創建了函數來注冊回調和演示一些OpenGL初始化,用到所有子窗體中.我們也聲明了三個變量來保存窗體和子窗體的ID,稍后會用到.
int mainWindow, subWindow1,subWindow2,subWindow3; ... void init() { glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); // register callbacks glutIgnoreKeyRepeat(1); glutKeyboardFunc(processNormalKeys); glutSpecialFunc(pressKey); glutSpecialUpFunc(releaseKey); glutMouseFunc(mouseButton); glutMotionFunc(mouseMove); } int main(int argc, char **argv) { // init GLUT and create main window glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(800,800); mainWindow = glutCreateWindow("Lighthouse3D - GLUT Tutorial"); // callbacks for main window glutDisplayFunc(renderScene); glutReshapeFunc(changeSize); glutIdleFunc(renderSceneAll); init(); // sub windows subWindow1 = glutCreateSubWindow(mainWindow, border,border,w-2*border, h/2 - border*3/2); glutDisplayFunc(renderScenesw1); init(); subWindow2 = glutCreateSubWindow(mainWindow, border,(h+border)/2,w/2-border*3/2, h/2 - border*3/2); glutDisplayFunc(renderScenesw2); init(); subWindow3 = glutCreateSubWindow(mainWindow, (w+border)/2,(h+border)/2,w/2-border*3/2,h/2 - border*3/2); glutDisplayFunc(renderScenesw3); init(); // enter GLUT event processing cycle glutMainLoop(); return 1; }
上面的代碼創建了三個子窗體.每個子窗體都用戶顯示同一個場景的不同視點.頂部的子窗體顯示自由移動的鏡頭,從頂端觀察底部的左邊到右邊.
當窗體創建后,無論窗體還是子窗體,都會變成當前窗體(獲得焦點).所有回調會被注冊到當前新創建窗體,除了空閑函數之外,之前說過該函數是整個應用程序唯一的.
注意我們要調用initScene函數來為所有子窗體初始化OpenGL上下文.還要注意我們只為主窗體注冊一次重整函數.
子窗體不用時可以關閉.用到的函數是glutDestroyWindow.
void glutDestroyWindow(int windowIdentifier)
windowIdentifier - 創建窗體時的返回值
該函數會關閉窗體和它包含的子窗體,還有它綁定的所有OpenGL上下文.
下一節我們會探討重整函數和渲染函數.
