目录

OpenGL支持交互式输入设备的函数

GLU鼠标函数

GLUT键盘函数

OpenGL的菜单功能

创建GLUT菜单

创建和管理多个GLUT菜单

创建GLUT子菜单

修改GLUT菜单


OpenGL支持交互式输入设备的函数

在OpenGL程序中,交互设备输入由OpenGL Utility Toolkit(GLUT)中的子程序处理,ui那位这些子程序需要与一个窗口系统连接。对每一种设备指定一个程序(回调函数)来处理从该设备发生的输入。这些GLUT命令与其他的GLUT语句一起放置在main程序中。此外,来自基本库和GLU库的函数的组合也可以与GLUT的鼠标函数一起处理拾取输入。

GLU鼠标函数

用以下函数来指定一个鼠标指针在窗口之内并且一个鼠标按钮被按下或松开时调用的函数:

glutMouseFunc(mouseFcn);

这个名为mouseFcn的鼠标回调函数有四个参数:

void mouseFcn(GLint button,GLint action,GLint xMouse,GLint yMouse)

参数button的允许值为GLUT_LEFT_BUTTON、GLUT_MIDDLE_BUTTON和GLUT_RIGHR_BUTTON。

参数action指出哪种按钮行为来触发鼠标激活事件。允许值为GLUT_DOWN、GLUT_UP。取决于需要通过按下还是松开鼠标键来启动一个行为。

调用mouseFcn将返回鼠标在窗口中的位置坐标(xMouse,yMouse)。这是相对于窗口左上角的位置。xMouse是光标到窗口左边界的像素距离,yMouse是光标到窗口上边界的像素距离。

下面给出glutMouseFunc子程序的一个简单例子。在窗口中每次按下鼠标左键时,就在鼠标光标所在位置画一个尺寸为3的红点。

#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;
}

下一个例子用鼠标输入来选择直线段的端点位置。选中的直线段首尾相连,展示了交互构造一条折线的过程。

#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;
}

可以使用的另一个GLUT鼠标子程序是glutMotionFuc(fcnDoSomething);

fcnDoSomething函数有两个参数:

void fcnDoSomething(GLint xMouse, GLint yMouse)

其中(xMouse,yMouse)是当鼠标被移动并且按钮被按下时,鼠标光标相对于窗口左上角的位置。

类似地,当鼠标在窗口内移动而鼠标键并未按下时,也可以执行一些动作:

glutPassiveMotionFunc(fcnDoSomething);

GLUT键盘函数

对于键盘输入,用以下函数指定一个当键盘上的一个键被按下时调用的函数:

glutKeyboardFunc(keyFcn);

被指定的函数有三个参数:

void keyFcn(GLubyte key, GLint xMouse, GLint yMouse)

参数key的取值是一个字符值或者对应的ASCII编码。返回的鼠标光标在窗口内的位置坐标(xMouse,yMouse)是相对于窗口左上角的。当一个指定的按钮被按下时,就可以用鼠标位置来启动某些行为。

下面的代码给出一个简单的用键盘输入的曲线绘制程序。

#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;
}

可以使用以下命令指定对于功能键、方向键及其他特殊键的处理函数:

glutSpecialFunc(specialKeyFcn);

被指定的函数也有三个参数:

void specialKeyFcn(GLint specialKey,GLint xMouse,GLint yMouse)

specialKey从GLUT_KEY_F1到GLUT_KEY_F12。方向键的符号常量类似GLUT_KEY_UP和、GLUT_KEY_RIGHT。其他特殊键(如翻页、首尾和插入键)用GLUT_KEY_PAGE_DOWN、GLUT_KEY_HOME等指定。"backspace"、“delete”和“escape”键通过glutKeyboardFunc用它们的ASII编码指定分别未8、127和27.

以下代码展示一个同时支持鼠标、键盘和功能键的交互程序。

#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还包括多种向程序中添加简单的弹出式菜单的函数。使用这些函数可以设置和访问多种菜单和子菜单。GLUT菜单命令和其他GLUT函数一起放置在main程序中。

创建GLUT菜单

以下语句创建一个弹出式菜单:

glutCreateMenu(menuFcn);

menuFcn是当一个菜单项被选中时调用的函数的名字。这个函数有一个整型参数对应于选中项的位置。

void menuFcn(GLint menuItemNumber)

一旦指定了菜单项被选中时调用的函数,列在菜单上的菜单项也必须被指定。使用一系列的语句来设定每个菜单项的名称和位置。通用形式如下:

glutAddMenuEntry(charString, menuItemNumber);

参数charString 设定显示在菜单上的文字;参数menuItemNumber设定该菜单项在菜单中的位置。

例如,下列语句创建一个具有两个菜单项的菜单:

glutCreateMenu(menuFcn);

glutAddMenuEntry("First Menu Item",1);

glutAddMenuEntry("First Menu Item",2);

然后,必须通过以下函数指定来选择菜单项的鼠标键:

glutAttachMenu(button);

以下示例程序展示了如何创建和使用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;
}

创建和管理多个GLUT菜单

当一个菜单被创建时,它被关联到当前的窗口。可以为一个窗口创建多个菜单,也可以为不同的窗口创建不同的菜单。每个菜单在创建时分配到一个整数标识符。菜单标识符按照菜单创建的顺序从1开始编号。glutCreateMenu子程序返回这个标识符。可以用以下语句记录新创建菜单的标识符:

menuID = glutCreateMenu(menuFcn);

最新创建的菜单成为当前窗口的当前菜单。可以用以下命令激活一个菜单成为当前窗口的当前菜单:

glutSetMenu(menuID);

menuID对应的菜单即成为当前菜单。当与此菜单关联的鼠标键在窗口内按下时,此菜单就会弹出。

以下命令用于清除一个菜单:

glutDestroyMenu(menuID);

如果menuID对应的菜单是窗口的当前菜单,那么即使存在其他的菜单,清除当前菜单后该窗口也没有当前菜单。

以下函数用于获得当前窗口的当前菜单的标识符:

currentMenuID = glutGetMenu();

如果当前窗口没有菜单,或者之前的当前菜单被glutDestroyMenu清除了,返回值为0。

创建GLUT子菜单

也可以将一个子菜单关联到一个菜单上。首先,用glutCreateMenu创建子菜单并且列出子菜单项;然后,将子菜单作为一个项添加到主菜单上。下列语句用于将一个子菜单添加到一个主菜单(或其他子菜单)的菜单项列表:

glutAddSubMenu函数也可以用来将子菜单添加到当前菜单。

下列例子展示了创建子菜单的过程。

#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菜单

如果要改变用来选择菜单的鼠标键,首先要取消与当前鼠标键的关联,然后再关联一个新的键。以下函数用于取消关联:

glutDetachMenu(mouseButton);

参数mouseButton是之前关联到这个菜单的鼠标键(左中右)的GLUT符号常量。取消关联之后使用glutAttachMenu来将菜单与另一个按钮关联起来。

也可以改变一个已有菜单中的某些项。例如,可以用以下函数删除当前菜单中的一个项:

glutRemoveMenuItem(itemNumber);

其中参数itemNumber被赋值为欲删除菜单项的整数标识符。

计算机图形学 学习笔记 OpenGL图形用户界面和交互输入相关推荐

  1. 计算机图形学 学习笔记(七):二维图形变换:平移,比例,旋转,坐标变换等

    接上文 计算机图形学 学习笔记(六):消隐算法:Z-buffer,区间扫描线,Warnock,光栅图形学小结 在图形学中,有两大基本工具:向量分析,图形变换.本文将重点讲解向量和二维图形的变换. 5. ...

  2. 计算机图形学 学习笔记(八):三维图形变换:三维几何变换,投影变换(平行/ 透视 投影)

    接上文 计算机图形学 学习笔记(七):二维图形变换:平移,比例,旋转,坐标变换等 通过三维图形变换,可由简单图形得到复杂图形,三维图形变化则分为三维几何变换和投影变换. 6.1 三维图形几何变换 三维 ...

  3. 计算机图形学 学习笔记(五):多边形裁剪(Suther land-Hodgeman),文字裁剪

    接上文 计算机图形学 学习笔记(四):直线裁剪算法:Cohen-Suther land,中点分割法,Liang-Barsky 光栅图形学算法 3.4 多边形裁剪 之前上一篇文章中,我们介绍了直线段的裁 ...

  4. 计算机图形学 学习笔记(四):直线裁剪算法:Cohen-Suther land,中点分割法,Liang-Barsky

    接上文 计算机图形学 学习笔记(三):多边形的区域填充算法,反走样算法 光栅图形学算法 本文主要讲解直线裁剪算法. 裁剪 使用计算机处理图形信息时,计算机内部存储的图形往往比较大,而屏幕显示的知识图形 ...

  5. 计算机图形学 学习笔记(九):曲线曲面(一):参数曲线、参数几何代数形式

    接上文 计算机图形学 学习笔记(八):三维图形变换:三维几何变换,投影变换(平行/ 透视 投影) 计算机图形学三大块内容:光栅图形显示(前面已经介绍完了 1-8).几何造型技术.真实感图形显示.光栅图 ...

  6. GAMES101-现代计算机图形学学习笔记(作业03)

    GAMES101-现代计算机图形学学习笔记(作业03) Assignment 03 GAMES101-现代计算机图形学学习笔记(作业03) 作业 作业描述 思路 原课程视频链接以及官网 b站视频链接: ...

  7. GAMES101-现代计算机图形学学习笔记(作业07)

    GAMES101-现代计算机图形学学习笔记(作业07) Assignment 07 GAMES101-现代计算机图形学学习笔记(作业07) 作业 作业描述 思路 结果 原课程视频链接以及官网 b站视频 ...

  8. GAMES101-现代计算机图形学学习笔记(作业02)

    GAMES101-现代计算机图形学学习笔记(作业02) Assignment 02 GAMES101-现代计算机图形学学习笔记(作业02) 作业 作业描述 需要补充的函数 思路 结果 原课程视频链接以 ...

  9. GAMES101-现代计算机图形学学习笔记(作业01)

    GAMES101-现代计算机图形学学习笔记(作业01) Assignment 01 GAMES101-现代计算机图形学学习笔记(作业01) 作业 作业描述 需要补充的函数 思路 结果 原课程视频链接以 ...

最新文章

  1. 嵌入式Linux设备驱动程序:在运行时读取驱动程序状态
  2. go语言学习(7)锁
  3. 一、WPF 2个datagrid之间同步进度条
  4. 天了噜!定义static字段还有顺序要求?
  5. Java笔记-AnnotationConfigApplicationContext在Spring中的例子
  6. Data URL和图片,及Data URI的利弊
  7. oracle如何检索文件,从Oracle数据库检索文件的示例
  8. 非对称卷积—Asymmetric Convolutions
  9. 关于JVM中YGC的来龙去脉
  10. linux_network
  11. 织梦php me,GitHub - czmz/DedeCMSv5: 中国专业的PHP网站内容管理系统-织梦内容管理系统...
  12. LeetCode(8) - String to Integer (atoi)
  13. 一、CC2530简介
  14. 大数据发展呈现十大趋势
  15. 【Scrum模式语言15】发布计划(Release Plan)
  16. win7开机弹计算机,win7开机弹出Windows Installer窗口的解决方法
  17. linux 操作系统root账号被锁定的两种解决方法
  18. 2022年亚太地区大学生数学建模竞赛/2022年亚太杯ABCD题思路
  19. 单片机设计一个十字路口交通灯模拟控制系统(51单片机实训)
  20. 淘宝店铺层级划分规则是什么?如何去玩转?

热门文章

  1. 如何理解电容的充放电过程?
  2. vue调用摄像头拍照
  3. React Native资源汇总
  4. MATLAB_GUI项目 自然场景下限速标志识别
  5. 阿里云邮件服务器怎么设置才能在QQ邮箱访问,互发邮件?
  6. Excel:通过简称查找全称,VLOOKUP函数
  7. 网络编排:基本概念及解读(1)
  8. AnyChat开发流程指南
  9. 计算机实操考试题库和答案,计算机一级操作题库及答案
  10. 公式字母上方法的波浪线~如何添加