计算机图形学 学习笔记 OpenGL图形用户界面和交互输入
目錄?
OpenGL支持交互式輸入設(shè)備的函數(shù)
GLU鼠標(biāo)函數(shù)
GLUT鍵盤(pán)函數(shù)
OpenGL的菜單功能
創(chuàng)建GLUT菜單
創(chuàng)建和管理多個(gè)GLUT菜單
創(chuàng)建GLUT子菜單
修改GLUT菜單
OpenGL支持交互式輸入設(shè)備的函數(shù)
在OpenGL程序中,交互設(shè)備輸入由OpenGL Utility Toolkit(GLUT)中的子程序處理,ui那位這些子程序需要與一個(gè)窗口系統(tǒng)連接。對(duì)每一種設(shè)備指定一個(gè)程序(回調(diào)函數(shù))來(lái)處理從該設(shè)備發(fā)生的輸入。這些GLUT命令與其他的GLUT語(yǔ)句一起放置在main程序中。此外,來(lái)自基本庫(kù)和GLU庫(kù)的函數(shù)的組合也可以與GLUT的鼠標(biāo)函數(shù)一起處理拾取輸入。
GLU鼠標(biāo)函數(shù)
用以下函數(shù)來(lái)指定一個(gè)鼠標(biāo)指針在窗口之內(nèi)并且一個(gè)鼠標(biāo)按鈕被按下或松開(kāi)時(shí)調(diào)用的函數(shù):
glutMouseFunc(mouseFcn);
這個(gè)名為mouseFcn的鼠標(biāo)回調(diào)函數(shù)有四個(gè)參數(shù):
void?mouseFcn(GLint button,GLint action,GLint xMouse,GLint yMouse)
參數(shù)button的允許值為GLUT_LEFT_BUTTON、GLUT_MIDDLE_BUTTON和GLUT_RIGHR_BUTTON。
參數(shù)action指出哪種按鈕行為來(lái)觸發(fā)鼠標(biāo)激活事件。允許值為GLUT_DOWN、GLUT_UP。取決于需要通過(guò)按下還是松開(kāi)鼠標(biāo)鍵來(lái)啟動(dòng)一個(gè)行為。
調(diào)用mouseFcn將返回鼠標(biāo)在窗口中的位置坐標(biāo)(xMouse,yMouse)。這是相對(duì)于窗口左上角的位置。xMouse是光標(biāo)到窗口左邊界的像素距離,yMouse是光標(biāo)到窗口上邊界的像素距離。
下面給出glutMouseFunc子程序的一個(gè)簡(jiǎn)單例子。在窗口中每次按下鼠標(biāo)左鍵時(shí),就在鼠標(biāo)光標(biāo)所在位置畫(huà)一個(gè)尺寸為3的紅點(diǎn)。
#include <GL/glut.h> GLsizei winWidth = 400, winHeight = 300;void Init() {glClearColor(0, 0, 1, 1);glMatrixMode(GL_PROJECTION);gluOrtho2D(0, 200, 0, 150); }void DisplayFcn() {glClear(GL_COLOR_BUFFER_BIT);glColor3f(1, 0, 0);glPointSize(3); }void WinReshapFcn(GLint newWidth, GLint newHeight) {glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, GLdouble(newWidth), 0, GLdouble(newHeight));winWidth = newWidth;winHeight = newHeight; }void PlotPoint(GLint x, GLint y) {glBegin(GL_POINTS);glVertex2f(x, y);glEnd(); }void MousePtPlot(GLint button, GLint action,GLint xMouse, GLint yMouse) {if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN){PlotPoint(xMouse, winHeight - yMouse);}glFlush(); }int main(int argc, char* argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(100, 100);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("MousePlotPoints");Init();glutDisplayFunc(DisplayFcn);glutReshapeFunc(WinReshapFcn);glutMouseFunc(MousePtPlot);glutMainLoop();return 0; }下一個(gè)例子用鼠標(biāo)輸入來(lái)選擇直線(xiàn)段的端點(diǎn)位置。選中的直線(xiàn)段首尾相連,展示了交互構(gòu)造一條折線(xiàn)的過(guò)程。
#include <GL/glut.h> #include <stdlib.h>GLsizei winWidth = 400, winHeight = 300; GLint endPtCtr = 0;class scrPt {public:GLint x, y; };void Init() {glClearColor(0, 0, 1, 1);glMatrixMode(GL_PROJECTION);gluOrtho2D(0, 200, 0, 150); }void DisplayFcn() {glClear(GL_COLOR_BUFFER_BIT); }void WinReshapFcn(GLint newWidth, GLint newHeight) {glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, GLdouble(newWidth), 0, GLdouble(newHeight));winWidth = newWidth;winHeight = newHeight; }void DrawLineSegement(scrPt endPt1, scrPt endPt2) {glBegin(GL_LINES);glVertex2f(endPt1.x, endPt1.y);glVertex2f(endPt2.x, endPt2.y);glEnd(); }void PolyLine(GLint button, GLint action,GLint xMouse, GLint yMouse) {static scrPt endPt1, endPt2;if (endPtCtr == 0){if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN){endPt1.x = xMouse;endPt1.y = winHeight - yMouse;endPtCtr = 1;}else{if (button == GLUT_RIGHT_BUTTON){exit (0);}}}else{if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN){endPt2.x = xMouse;endPt2.y = winHeight - yMouse;DrawLineSegement(endPt1, endPt2);endPt1 = endPt2;}else{if (button == GLUT_RIGHT_BUTTON){exit(0);}}}glFlush(); }int main(int argc, char* argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(100, 100);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("Draw Interactive Polylines");Init();glutDisplayFunc(DisplayFcn);glutReshapeFunc(WinReshapFcn);glutMouseFunc(PolyLine);glutMainLoop();return 0; }可以使用的另一個(gè)GLUT鼠標(biāo)子程序是glutMotionFuc(fcnDoSomething);
fcnDoSomething函數(shù)有兩個(gè)參數(shù):
void?fcnDoSomething(GLint xMouse, GLint yMouse)
其中(xMouse,yMouse)是當(dāng)鼠標(biāo)被移動(dòng)并且按鈕被按下時(shí),鼠標(biāo)光標(biāo)相對(duì)于窗口左上角的位置。
類(lèi)似地,當(dāng)鼠標(biāo)在窗口內(nèi)移動(dòng)而鼠標(biāo)鍵并未按下時(shí),也可以執(zhí)行一些動(dòng)作:
glutPassiveMotionFunc(fcnDoSomething);
GLUT鍵盤(pán)函數(shù)
對(duì)于鍵盤(pán)輸入,用以下函數(shù)指定一個(gè)當(dāng)鍵盤(pán)上的一個(gè)鍵被按下時(shí)調(diào)用的函數(shù):
glutKeyboardFunc(keyFcn);
被指定的函數(shù)有三個(gè)參數(shù):
void keyFcn(GLubyte key, GLint xMouse, GLint yMouse)
參數(shù)key的取值是一個(gè)字符值或者對(duì)應(yīng)的ASCII編碼。返回的鼠標(biāo)光標(biāo)在窗口內(nèi)的位置坐標(biāo)(xMouse,yMouse)是相對(duì)于窗口左上角的。當(dāng)一個(gè)指定的按鈕被按下時(shí),就可以用鼠標(biāo)位置來(lái)啟動(dòng)某些行為。
下面的代碼給出一個(gè)簡(jiǎn)單的用鍵盤(pán)輸入的曲線(xiàn)繪制程序。
#include <GL/glut.h> GLsizei winWidth = 400, winHeight = 300;void Init() {glClearColor(0, 0, 1, 1);glMatrixMode(GL_PROJECTION);gluOrtho2D(0, 200, 0, 150); }void DisplayFcn() {glClear(GL_COLOR_BUFFER_BIT);glColor3f(1, 0, 0);glPointSize(3); }void WinReshapFcn(GLint newWidth, GLint newHeight) {glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, GLdouble(newWidth), 0, GLdouble(newHeight));winWidth = newWidth;winHeight = newHeight; }void PlotPoint(GLint x, GLint y) {glBegin(GL_POINTS);glVertex2f(x, y);glEnd(); }void CurveDrawing(GLubyte curvePlotKey, GLint xMouse, GLint yMouse) {GLint x = xMouse;GLint y = winHeight - yMouse;switch (curvePlotKey){case 'c':PlotPoint(x, y);break;default:break;}glFlush(); }int main(int argc, char* argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(100, 100);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("MousePlotPoints");Init();glutDisplayFunc(DisplayFcn);glutReshapeFunc(WinReshapFcn);glutKeyboardFunc(CurveDrawing);glutMainLoop();return 0; }可以使用以下命令指定對(duì)于功能鍵、方向鍵及其他特殊鍵的處理函數(shù):
glutSpecialFunc(specialKeyFcn);
被指定的函數(shù)也有三個(gè)參數(shù):
void?specialKeyFcn(GLint specialKey,GLint xMouse,GLint yMouse)
specialKey從GLUT_KEY_F1到GLUT_KEY_F12。方向鍵的符號(hào)常量類(lèi)似GLUT_KEY_UP和、GLUT_KEY_RIGHT。其他特殊鍵(如翻頁(yè)、首尾和插入鍵)用GLUT_KEY_PAGE_DOWN、GLUT_KEY_HOME等指定。"backspace"、“delete”和“escape”鍵通過(guò)glutKeyboardFunc用它們的ASII編碼指定分別未8、127和27.
以下代碼展示一個(gè)同時(shí)支持鼠標(biāo)、鍵盤(pán)和功能鍵的交互程序。
#include <GL/glut.h> #include <stdlib.h>GLsizei winWidth = 400, winHeight = 300; GLint edgeLength = 10;void Init() {glClearColor(0, 0, 1, 1);glMatrixMode(GL_PROJECTION);gluOrtho2D(0, 200, 0, 150); }void DisplayFcn() {glClear(GL_COLOR_BUFFER_BIT);glColor3f(1, 0, 0); }void WinReshapFcn(GLint newWidth, GLint newHeight) {glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, GLdouble(newWidth), 0, GLdouble(newHeight));winWidth = newWidth;winHeight = newHeight; }void FillSquare(GLint button, GLint action,GLint xMouse, GLint yMouse) {GLint x1, y1, x2, y2;if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN){x1 = xMouse;y1 = winHeight - yMouse;x2 = x1 + edgeLength;y2 = y1 + edgeLength;glRecti(x1, y1, x2, y2);}else{if (button == GLUT_RIGHT_BUTTON){exit(0);}}glFlush(); }void EnlargeSqure(GLubyte sizeFactor, GLint xMouse, GLint yMouse) {switch (sizeFactor){case '2':edgeLength *= 2;break;case '3':edgeLength *= 3;break;case '4':edgeLength *= 4;break;default:break;} }void ReduceSqure(GLint reductionKey, GLint xMouse, GLint yMouse) {switch (reductionKey){case GLUT_KEY_F2:edgeLength /= 2;break;case GLUT_KEY_F3:edgeLength /= 4;break;default:break;} }int main(int argc, char* argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(100, 100);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("MousePlotPoints");Init();glutDisplayFunc(DisplayFcn);glutReshapeFunc(WinReshapFcn);glutMouseFunc(FillSquare);glutKeyboardFunc(EnlargeSqure);glutSpecialFunc(ReduceSqure);glutMainLoop();return 0; }OpenGL的菜單功能
GLUT還包括多種向程序中添加簡(jiǎn)單的彈出式菜單的函數(shù)。使用這些函數(shù)可以設(shè)置和訪(fǎng)問(wèn)多種菜單和子菜單。GLUT菜單命令和其他GLUT函數(shù)一起放置在main程序中。
創(chuàng)建GLUT菜單
以下語(yǔ)句創(chuàng)建一個(gè)彈出式菜單:
glutCreateMenu(menuFcn);
menuFcn是當(dāng)一個(gè)菜單項(xiàng)被選中時(shí)調(diào)用的函數(shù)的名字。這個(gè)函數(shù)有一個(gè)整型參數(shù)對(duì)應(yīng)于選中項(xiàng)的位置。
void menuFcn(GLint menuItemNumber)
一旦指定了菜單項(xiàng)被選中時(shí)調(diào)用的函數(shù),列在菜單上的菜單項(xiàng)也必須被指定。使用一系列的語(yǔ)句來(lái)設(shè)定每個(gè)菜單項(xiàng)的名稱(chēng)和位置。通用形式如下:
glutAddMenuEntry(charString, menuItemNumber);
參數(shù)charString 設(shè)定顯示在菜單上的文字;參數(shù)menuItemNumber設(shè)定該菜單項(xiàng)在菜單中的位置。
例如,下列語(yǔ)句創(chuàng)建一個(gè)具有兩個(gè)菜單項(xiàng)的菜單:
glutCreateMenu(menuFcn);
glutAddMenuEntry("First Menu Item",1);
glutAddMenuEntry("First Menu Item",2);
然后,必須通過(guò)以下函數(shù)指定來(lái)選擇菜單項(xiàng)的鼠標(biāo)鍵:
glutAttachMenu(button);
以下示例程序展示了如何創(chuàng)建和使用GLUT菜單。
#include <GL/glut.h>GLsizei winWidth = 400, winHeight = 400; GLfloat red = 1.0, green = 1.0, blue = 1.0; GLenum fillMode = GL_SMOOTH;void Init() {glClearColor(0.6, 0.6, 0.6, 1);glMatrixMode(GL_PROJECTION);gluOrtho2D(0, 300, 0, 300); }void FillOption(GLint selectedOption) {switch (selectedOption){case 1:fillMode = GL_FLAT;break;case 2:fillMode = GL_SMOOTH;break;}glutPostRedisplay(); }void DisplayTriangle() {glClear(GL_COLOR_BUFFER_BIT);glShadeModel(fillMode);glColor3f(red, green, blue);glBegin(GL_TRIANGLES);glVertex2i(280, 20);glVertex2i(160, 280);glColor3f(red, 0, 0);glVertex2i(20, 100);glEnd();glFlush(); }void ReshapFcn(GLint newWidth, GLint newHeight) {glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, GLdouble(newWidth), 0, GLdouble(newHeight));DisplayTriangle();glFlush(); }int main(int argc, char* argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(200, 200);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("Menu Example");Init();glutDisplayFunc(DisplayTriangle);glutCreateMenu(FillOption);glutAddMenuEntry("Solid-Color Fill", 1);glutAddMenuEntry("Color-Interpolation Fill", 2);glutAttachMenu(GLUT_RIGHT_BUTTON);glutReshapeFunc(ReshapFcn);glutMainLoop();return 0; }創(chuàng)建和管理多個(gè)GLUT菜單
當(dāng)一個(gè)菜單被創(chuàng)建時(shí),它被關(guān)聯(lián)到當(dāng)前的窗口。可以為一個(gè)窗口創(chuàng)建多個(gè)菜單,也可以為不同的窗口創(chuàng)建不同的菜單。每個(gè)菜單在創(chuàng)建時(shí)分配到一個(gè)整數(shù)標(biāo)識(shí)符。菜單標(biāo)識(shí)符按照菜單創(chuàng)建的順序從1開(kāi)始編號(hào)。glutCreateMenu子程序返回這個(gè)標(biāo)識(shí)符。可以用以下語(yǔ)句記錄新創(chuàng)建菜單的標(biāo)識(shí)符:
menuID = glutCreateMenu(menuFcn);
最新創(chuàng)建的菜單成為當(dāng)前窗口的當(dāng)前菜單。可以用以下命令激活一個(gè)菜單成為當(dāng)前窗口的當(dāng)前菜單:
glutSetMenu(menuID);
menuID對(duì)應(yīng)的菜單即成為當(dāng)前菜單。當(dāng)與此菜單關(guān)聯(lián)的鼠標(biāo)鍵在窗口內(nèi)按下時(shí),此菜單就會(huì)彈出。
以下命令用于清除一個(gè)菜單:
glutDestroyMenu(menuID);
如果menuID對(duì)應(yīng)的菜單是窗口的當(dāng)前菜單,那么即使存在其他的菜單,清除當(dāng)前菜單后該窗口也沒(méi)有當(dāng)前菜單。
以下函數(shù)用于獲得當(dāng)前窗口的當(dāng)前菜單的標(biāo)識(shí)符:
currentMenuID = glutGetMenu();
如果當(dāng)前窗口沒(méi)有菜單,或者之前的當(dāng)前菜單被glutDestroyMenu清除了,返回值為0。
創(chuàng)建GLUT子菜單
也可以將一個(gè)子菜單關(guān)聯(lián)到一個(gè)菜單上。首先,用glutCreateMenu創(chuàng)建子菜單并且列出子菜單項(xiàng);然后,將子菜單作為一個(gè)項(xiàng)添加到主菜單上。下列語(yǔ)句用于將一個(gè)子菜單添加到一個(gè)主菜單(或其他子菜單)的菜單項(xiàng)列表:
?glutAddSubMenu函數(shù)也可以用來(lái)將子菜單添加到當(dāng)前菜單。
下列例子展示了創(chuàng)建子菜單的過(guò)程。
#include <GL/glut.h>GLsizei winWidth = 400, winHeight = 400; GLfloat red = 1.0, green = 1.0, blue = 1.0; GLenum renderingMode = GL_SMOOTH;void Init() {glClearColor(0.6, 0.6, 0.6, 1);glMatrixMode(GL_PROJECTION);gluOrtho2D(0, 300, 0, 300); }void MainMenu(GLint renderingOption) {switch (renderingOption){case 1:renderingMode = GL_FLAT;break;case 2:renderingMode = GL_SMOOTH;break;}glutPostRedisplay(); }void ColorSubMenu(GLint colorOption) {switch (colorOption){case 1:red = 0; green = 0; blue = 1;break;case 2:red = 0; green = 1; blue = 0;break;case 3:red = 1; green = 1; blue = 1;break;}glutPostRedisplay(); }void DisplayTriangle() {glClear(GL_COLOR_BUFFER_BIT);glShadeModel(renderingMode);glColor3f(red, green, blue);glBegin(GL_TRIANGLES);glVertex2i(280, 20);glVertex2i(160, 280);glColor3f(1, 0, 0);glVertex2i(20, 100);glEnd();glFlush(); }void ReshapFcn(GLint newWidth, GLint newHeight) {glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, GLdouble(newWidth), 0, GLdouble(newHeight));DisplayTriangle();glFlush(); }int main(int argc, char* argv[]) {GLint subMenu;glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(200, 200);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("SubMenu Example");Init();glutDisplayFunc(DisplayTriangle);subMenu = glutCreateMenu(ColorSubMenu);glutAddMenuEntry("Blue", 1);glutAddMenuEntry("Green", 2);glutAddMenuEntry("White", 3);glutCreateMenu(MainMenu);glutAddMenuEntry("Solid-Color Fill", 1);glutAddMenuEntry("Color-Interpolation Fill", 2);glutAddSubMenu("Color", subMenu);glutAttachMenu(GLUT_RIGHT_BUTTON);glutReshapeFunc(ReshapFcn);glutMainLoop();return 0; }修改GLUT菜單
如果要改變用來(lái)選擇菜單的鼠標(biāo)鍵,首先要取消與當(dāng)前鼠標(biāo)鍵的關(guān)聯(lián),然后再關(guān)聯(lián)一個(gè)新的鍵。以下函數(shù)用于取消關(guān)聯(lián):
glutDetachMenu(mouseButton);
參數(shù)mouseButton是之前關(guān)聯(lián)到這個(gè)菜單的鼠標(biāo)鍵(左中右)的GLUT符號(hào)常量。取消關(guān)聯(lián)之后使用glutAttachMenu來(lái)將菜單與另一個(gè)按鈕關(guān)聯(lián)起來(lái)。
也可以改變一個(gè)已有菜單中的某些項(xiàng)。例如,可以用以下函數(shù)刪除當(dāng)前菜單中的一個(gè)項(xiàng):
glutRemoveMenuItem(itemNumber);
其中參數(shù)itemNumber被賦值為欲刪除菜單項(xiàng)的整數(shù)標(biāo)識(shí)符。
總結(jié)
以上是生活随笔為你收集整理的计算机图形学 学习笔记 OpenGL图形用户界面和交互输入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: layui中的动态表格
- 下一篇: 网络变压器的生产特性