碎碎念:
最近老是出去玩,感觉要收收心,但也感觉应该出去走走。向来平衡都不太好找。
刚接触OpenGL,还算是比较顺利的配好了环境,比opencv要好配。差不多就是把几个文件之类的加进来就可以。(之前也记录了一下)
这里呢,也记录一下opengl的学习过程,我感觉是记录大于分享(水平还远达不到分享二字的份量)。下面就开始叭(以案例和代码形式)。
opengl的第一课
(#include
1.窗口、绘制的回调函数
// GLUT头文件
#include //包含了 glut.h//中包含了&
#include
void myDrawing(void) {
//清除颜色缓冲区
printf("$\n");
glClearColor(0.0, 0.0, 1.0f, 0.0); //设置背景清除蓝色
glClear(GL_COLOR_BUFFER_BIT); //执行清除
//以线框形式绘制一个茶壶
glRotatef(90, 1.0f, 1.0f, 0.0f); //旋转 -- <缩放窗口>
//glutWireTeapot(0.5f); //线框犹他壶
//glutWireSphere(0.5f, 24, 24); //线框球面
glutWireTorus(0.25f, 0.6, 30, 25); //线框球面
glFlush(); //强制绘图
}
// 主函数
int main(int argc, char **argv) {
glutInit(&argc, argv);
//对GLUT进行初始化
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//产生一个名为"Hello"的绘制窗口, //使用缺省值
glutCreateWindow("Hello");
//注册绘制函数
glutDisplayFunc(myDrawing);
//主消息循环
glutMainLoop(); //进入消息循环
return 0;
}
看主函数:
1.glutInit(&argc, argv) : 这句话,怎么说呢,就是不加它,编译会通过,但是运行的时候出现:freeglut ERROR: Function
called without first calling 'glutInit'. (小白还不懂,那就老式加上叭)
2.glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB) : 用于设置窗口的显示样式
GLUT_SINGLE表示使用单缓冲模式,即每次绘制完成后直接显示在屏幕上,但可能会导致闪烁。GLUT_RGB表示使用RGB的颜色绘制模式。
3.glutCreateWindow("Hello"): 创建一个窗口,并将其命名为“Hello”
4.glutDisplayFunc(myDrawing):用于注册一个回调函数,该函数在窗口需要重新绘制时被调用。当窗口首次创建或需要更新内容时,绘制函数将会被自动调用,从而实现你期望的可视化效果。
5.glutMainLoop():当glutMainLoop()被调用时,程序将进入一个无限循环,等待用户的交互事件,例如鼠标、键盘、窗口大小调整等等。每次事件发生时,GLUT 将会调用注册的回调函数来处理该事件。然后,程序将重新绘制窗口内容并等待下一个事件的发生。
回调函数(这里是绘制函数myDrawing)
绘制结果:
(点击一下鼠标,或者移动窗口,等操作,都会执行一次绘制的回调函数)
2.初始化窗口的大小和位置
#include
// 绘制函数声明 <========== NEW!!!
void myDrawing(void);
int main(int argc, char **argv) {
glutInit(&argc, argv);
//对GLUT进行初始化
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//设置绘制窗口大小 <========== NEW!!!
glutInitWindowSize(300, 300);
//设置绘制窗口的位置 <========== NEW!!!
glutInitWindowPosition(100, 100);
//产生一个名为"Hello"的绘制窗口
glutCreateWindow("Hello");
//注册绘制函数
glutDisplayFunc(myDrawing);
//主消息循环
glutMainLoop(); //进入消息循环
return 0;
}
// 绘制函数定义 <========== NEW!!!
void myDrawing(void) {
//清除颜色缓冲区
glClearColor(1.0, 1.0f, 0.0f, 0.0f); //设置背景清除色--黄色
glClear(GL_COLOR_BUFFER_BIT); //执行清除
以线框形式绘制一个茶壶
glRotatef(45, 1.0f, 0.0f, 0.0f); //旋转
glutWireTeapot(0.55f); //犹他壶
//glutWireSphere(0.5f, 20, 20); //线框球面
glFlush();
}
新增知识点:
1.声明在前,函数的定义在后
2.glutInitWindowSize(300, 300) : 用于设置窗口的初始尺寸为300像素宽度和300像素高度。
3.glutInitWindowPosition(100, 100) : 设置窗口的初始位置,窗口的实际位置可能会受到操作系统和窗口管理器的限制和调整。
绘制结果:
3.改变窗口大小时的回调函数
#include
#include
int width, height; //全局变量
void myDraw(void);
void myReshape(int _width, int _height);
///
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400, 400); //窗口大小
glutInitWindowPosition(0, 0); //窗口位置
glutCreateWindow("Hello");
glutDisplayFunc(myDraw);
glutReshapeFunc(myReshape); //<=========
glutMainLoop();
return 0;
}
///
void myReshape(int _width, int _height) {
width = _width; // <<==============NEW!!!
height = _height; // <<==============NEW!!!
std::cout<<"Width: "<
新增知识点:
1.glutReshapeFunc(myReshape): 改变窗口大小时的回调函数
2.回调函数myReshape,将每一次改变后的窗口大小打印下来
绘制结果:
4.点击键盘上普通键('a'或'1')时的回调函数
#include
#include
///
// 函数声明
void myDrawing(void);
// 键盘字符键事件处理函数声明 <==========NEW!!!
void myKeyboard(unsigned char _key, int _x, int _y); //注意参数形式!!!!
///
int main(int argc, char **argv) {
glutInit(&argc, argv);
//对GLUT进行初始化
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//设置绘制窗口大小
glutInitWindowSize(300, 300);
//设置绘制窗口的位置
glutInitWindowPosition(400, 0);
//产生一个名为"Hello"的绘制窗口
glutCreateWindow("Hello");
//注册绘制函数
glutDisplayFunc(myDrawing);
//注册键盘字符键事件处理函数 <==========NEW!!!
glutKeyboardFunc(myKeyboard);
//主消息循环
glutMainLoop(); //进入消息循环
return 0;
}
///
// 图形绘制函数
void myDrawing(void) {
//清除颜色缓冲区
glClearColor(0.0, 0.0, 1.0f, 0.0); //设置背景清除蓝色
glClear(GL_COLOR_BUFFER_BIT); //执行清除
//以线框形式绘制一个茶壶
//glRotatef(45, 1.0f, 0.0f, 0.0f); //旋转
glutWireTeapot(0.5f); //犹他壶
//glutWireSphere(0.5f, 20, 20); //线框球面
glFlush();
}
///
// 键盘事件处理函数 <==========NEW!!!
void myKeyboard(unsigned char _key, int _x, int _y) {
if (_key=='A' || _key=='a')
std::cout<<" ==> ";
std::cout<<_key<<" is pressed at ["<<_x<<","<<_y<<"]\n";
}
新增知识点:
1.glutKeyboardFunc(myKeyboard) : 点击键盘中“普通键”时的回调函数
2.回调函数myKeyboard,第一个参数是点击的值、第二个参数是点击位置的x坐标、第三个参数是点击位置的y坐标
绘制结果:
5.点击键盘上特殊键('->'或'F5')时的回调函数
#include
#include
///
// 函数声明
void myDrawing(void); //绘图函数
void myKeyboard(unsigned char _key, int _x, int _y); //键盘字符键事件处理函数
// 键盘功能键事件处理函数 <==========NEW!!!
void mySpecialKey( int _key, int _x, int _y);
void mySpecialKeyH(int _key, int _x, int _y);
///
int main(int argc, char **argv) {//对GLUT进行初始化
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//设置绘制窗口大小
glutInitWindowSize(300, 300);
//设置绘制窗口的位置
glutInitWindowPosition(400, 0);
//产生一个名为“Hello”的绘制窗口
glutCreateWindow("Hello");
//注册绘制函数
glutDisplayFunc(myDrawing);
//注册键盘字符键事件处理函数
glutKeyboardFunc(myKeyboard);
//注册键盘功能键事件处理函数 <==========NEW!!!
glutSpecialFunc(mySpecialKey);
//主消息循环
glutMainLoop(); //进入消息循环
return 0;
}
///
// 图形绘制函数
void myDrawing(void) {
//清除颜色缓冲区
glClearColor(0.0, 0.0, 1.0f, 0.0); //设置背景清除蓝色
glClear(GL_COLOR_BUFFER_BIT); //执行清除
//以线框形式绘制一个茶壶
//glRotatef(45, 1.0f, 0.0f, 0.0f); //旋转
glutWireTeapot(0.5f); //犹他壶
//glutWireSphere(0.5f, 20, 20); //线框球面
glFlush();
}
///
// 键盘事件处理函数
void myKeyboard(unsigned char _key, int _x, int _y) {
std::cout<<_key<<" is pressed at ["<<_x<<","<<_y<<"]\n";
}
///
// 功能键事件处理函数 <==========NEW!!!
void mySpecialKey(int _key, int _x, int _y) {
switch (_key) {
case GLUT_KEY_LEFT:
std::cout<<"LEFT_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_UP:
std::cout<<"UP_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_RIGHT:
std::cout<<"RIGHT_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_DOWN:
std::cout<<"DOWN_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_HOME:
std::cout<<"HOME is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_END:
std::cout<<"END is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_INSERT:
std::cout<<"INSERT is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F1:
std::cout<<"F1 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F2:
std::cout<<"F2 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F3:
std::cout<<"F3 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F4:
std::cout<<"F4 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F5:
std::cout<<"F5 is pressed at ["<<_x<<","<<_y<<"]\n";
//取消键盘字符键事件处理函数 <==========NEW!!!
glutSpecialFunc(NULL);
break;
case GLUT_KEY_F6:
std::cout<<"F6 is pressed at ["<<_x<<","<<_y<<"]\n";
//取消键盘功能键事件处理函数 <==========NEW!!!
glutSpecialFunc(mySpecialKeyH);
break;
}
}
///
// 功能键事件处理函数 <==========NEW!!!
void mySpecialKeyH(int _key, int _x, int _y) {
std::cout<<"-----------Special Key: "
<<_key <<" is pressed at ["<<_x<<","<<_y<<"]\n";
if (_key==GLUT_KEY_F6) {
std::cout<<"-----------Exchange Special-Key Handler...\n";
glutSpecialFunc(mySpecialKey);
}
}
新增的知识点:
1.glutSpecialFunc(mySpecialKey): 点击键盘中“特殊键”时的回调函数
2.回调函数mySpecialKey:不同的_key值,使用switch进行不同的case。其中,如果按下的是F5,执行glutSpecialFunc(NULL),取消键盘字符键事件处理函数 ;如果按下的是F6,执行glutSpecialFunc(mySpecialKeyH),之后就再执行另一个回调函数mySpecialKeyH。
3.回调函数mySpecialKeyH:要想再换回去(mySpecialKey),按下F6键。
(这也在一定程度上说明,相同操作触发的回调函数可以不同,可以换)
绘制结果:
按下F5之后,执行了 glutSpecialFunc(NULL),再按下其他的特殊键,也不会执行什么了。
按下F6之后,执行了glutSpecialFunc(mySpecialKeyH),就相当于换了一个回调函数。
6. 鼠标事件处理的回调函数
#include
#include
///
// 函数声明
void myDrawing(void); //绘图函数
void myKeyboard(unsigned char _key, int _x, int _y); //键盘字符键事件处理函数
void mySpecialKey(int _key, int _x, int _y); //键盘功能键事件处理函数
// 鼠标事件处理函数 <======================NEW!!!
void myMouse(int _button, int _state, int _x, int _y);
///
int main(int argc, char **argv) {
glutInit(&argc, argv);
//对GLUT进行初始化
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//设置绘制窗口大小
glutInitWindowSize(300, 300);
//设置绘制窗口的位置
glutInitWindowPosition(400, 0);
//产生一个名为"Hello"的绘制窗口
glutCreateWindow("Hello");
//注册绘制函数
glutDisplayFunc(myDrawing);
//注册键盘字符键事件处理函数
glutKeyboardFunc(myKeyboard);
//注册键盘功能键事件处理函数
glutSpecialFunc(mySpecialKey);
//注册鼠标事件处理函数 <==========NEW!!!
glutMouseFunc(myMouse);
//主消息循环
glutMainLoop(); //进入消息循环
}
///
// 图形绘制函数
void myDrawing(void) {
//清除颜色缓冲区
glClearColor(0.0, 0.0, 1.0f, 0.0); //设置背景清除蓝色
glClear(GL_COLOR_BUFFER_BIT); //执行清除
//以线框形式绘制一个茶壶
//glRotatef(45, 1.0f, 0.0f, 0.0f); //旋转
glutWireTeapot(0.5f); //犹他壶
//glutWireSphere(0.5f, 20, 20); //线框球面
glFlush();
}
///
// 鼠标事件处理函数 <==========NEW!!!
void myMouse(int _button, int _state, int _x, int _y) {
//_button与_state是独立的, 根据需要进行组合
switch (_button) {
case GLUT_LEFT_BUTTON:
std::cout<<"LEFT <= mouse button is pressed, "; break;
case GLUT_MIDDLE_BUTTON:
std::cout<<"MIDD || mouse button is pressed, "; break;
case GLUT_RIGHT_BUTTON:
std::cout<<"RIGH => mouse button is pressed, "; break;
}
if (_state)
std::cout<<"UP at ["<<_x<<","<<_y<<"]\n";
else
std::cout<<"DOWN at ["<<_x<<","<<_y<<"]\n";
}
///
// 键盘事件处理函数
void myKeyboard(unsigned char _key, int _x, int _y) {
std::cout<<_key<<" is pressed at ["<<_x<<","<<_y<<"]\n";
}
///
// 功能键事件处理函数
void mySpecialKey(int _key, int _x, int _y) {
switch (_key) {
case GLUT_KEY_LEFT:
std::cout<<"LEFT_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_UP:
std::cout<<"UP_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_RIGHT:
std::cout<<"RIGHT_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_DOWN:
std::cout<<"DOWN_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_HOME:
std::cout<<"HOME is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_END:
std::cout<<"END is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_INSERT:
std::cout<<"INSERT is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F1:
std::cout<<"F1 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F2:
std::cout<<"F2 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F3:
std::cout<<"F3 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F4:
std::cout<<"F4 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F5:
std::cout<<"F5 is pressed at ["<<_x<<","<<_y<<"]\n";
//取消键盘字符键事件处理函数
glutKeyboardFunc(NULL); //<<==================== NEW !!!
break;
case GLUT_KEY_F6:
std::cout<<"F6 is pressed at ["<<_x<<","<<_y<<"]\n";
//取消键盘功能键事件处理函数
glutSpecialFunc(NULL); //<<==================== NEW !!!
break;
}
}
新增的知识点:
1.glutMouseFunc(myMouse) : 鼠标事件处理的回调函数(鼠标左键、中键、右键)
2.回调函数myMouse:四个参数,第一个int _button代表的是点击的是鼠标的哪个键(左键、中键、右键),int _state代表的是状态(按下DOWN、松开UP),int _x代表x坐标,int _y代表y坐标.
绘制结果:
7.多窗口
第一种方法:
///
#include
#include
///
// 声明四个绘制函数
void myDrawSphere(void); //球
void myDrawTeapot(void); //壶
void myDrawTorus(void); //环
void myDrawIcos(void); //体
///
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400, 400);
glutInitWindowPosition(0, 0);
//解释OGL/GLUT体系中的状态栈结构
int mainWin = glutCreateWindow("Hello");
glutCreateSubWindow(mainWin, 0, 0, 200, 200); // <========== NEW!!!
glutDisplayFunc(myDrawSphere);
glutCreateSubWindow(mainWin, 200, 0, 200, 200);
glutDisplayFunc(myDrawTeapot);
glutCreateSubWindow(mainWin, 0, 200, 200, 200);
glutDisplayFunc(myDrawTorus);
glutCreateSubWindow(mainWin, 200, 200, 200, 200);
glutDisplayFunc(myDrawIcos);
glutSetWindow(mainWin); // <========== NEW!!!
glutDisplayFunc(myDrawSphere);
glutMainLoop();
}
///
void myDrawSphere(void) {
glClearColor(0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glRotatef(30, 1.0f, 1.0f, 1.0f);
glutWireSphere(0.8f, 20, 20);
glFlush(); // <========== NEW!!!
}
///
void myDrawTeapot(void) {
glClearColor(1.0, 1.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glutWireTeapot(0.5f);
glFlush();
}
///
void myDrawTorus(void) {
glClearColor(0.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glutWireTorus(0.3f, 0.6f, 20, 30);
glFlush();
}
///
void myDrawIcos(void) {
glClearColor(1.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glRotatef(30, 1.0f, 1.0f, 1.0f);
glutWireIcosahedron();
glFlush();
}
新增的知识点:
1. int mainWin = glutCreateWindow("Hello") : 主窗口,这里需要返回值
2.glutCreateSubWindow(mainWin, 0, 0, 200, 200) : 子窗口,其主窗口为mainWin,位置(0,0),大小(200,200)
窗口放在一个栈的结构中!!
3.glutDisplayFunc(myDrawSphere):栈顶上窗口的回调函数
4.glutSetWindow(mainWin) : 将mainWin放到栈顶上
第二种方法:
///
#include
#include
///
// 四个绘制函数
void myDrawSphere(void); //球
void myDrawTeapot(void); //壶
void myDrawTorus(void); //环
void myDrawIcos(void); //体
///
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400, 400);
glutInitWindowPosition(0, 0);
int mainWin = glutCreateWindow("Hello");
int subWin1 = glutCreateSubWindow(mainWin, 0, 0, 200, 200);
int subWin2 = glutCreateSubWindow(mainWin, 200, 0, 200, 200);
int subWin3 = glutCreateSubWindow(mainWin, 0, 200, 200, 200);
int subWin4 = glutCreateSubWindow(mainWin, 200, 200, 200, 200);
glutSetWindow(subWin1);
glutDisplayFunc(myDrawSphere);
glutSetWindow(subWin2);
glutDisplayFunc(myDrawTorus);
glutSetWindow(subWin3);
glutDisplayFunc(myDrawTorus);
glutSetWindow(subWin4);
glutDisplayFunc(myDrawSphere);
glutSetWindow(mainWin);
glutDisplayFunc(myDrawSphere);
glutMainLoop();
}
///
void myDrawSphere(void) {
glClearColor(0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glRotatef(30, 1.0f, 1.0f, 1.0f);
glutWireSphere(0.8f, 20, 20);
glFlush(); // <========== NEW!!!
}
///
void myDrawTeapot(void) {
glClearColor(1.0, 1.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glutWireTeapot(0.5f);
glFlush();
}
///
void myDrawTorus(void) {
glClearColor(0.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glutWireTorus(0.3f, 0.6f, 20, 30);
glFlush();
}
///
void myDrawIcos(void) {
glClearColor(1.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glRotatef(30, 1.0f, 1.0f, 1.0f);
glutWireIcosahedron();
glFlush();
}
绘制结果:
8.project中 分文件编写
这个和常规的并没有什么不同
9.菜单
GLUT_H0_Callbacks.h
#ifndef GLUT_H0_CALLBACKS_H_INCLUDED
#define GLUT_H0_CALLBACKS_H_INCLUDED
///
#include
#include
///
// 函数声明
void myDrawing(void); //绘图函数
void myKeyboard(unsigned char _key, int _x, int _y); //键盘字符键事件处理函数
void mySpecialKey(int _key, int _x, int _y); //键盘功能键事件处理函数
void myMouse(int _button, int _state, int _x, int _y); //鼠标事件处理函数
#endif // GLUT_H0_CALLBACKS_H_INCLUDED
CLUT_H0_Callbacks.cpp
///
#include "GLUT_H0_Callbacks.h" //加入头文件
///
// 图形绘制函数
void myDrawing(void) {
//清除颜色缓冲区
glClearColor(0.0, 0.0, 1.0f, 0.0); //设置背景清除蓝色
glClear(GL_COLOR_BUFFER_BIT); //执行清除
//以线框形式绘制一个茶壶
//glRotatef(45, 1.0f, 0.0f, 0.0f); //旋转
glutWireTeapot(0.5f); //犹他壶
//glutWireSphere(0.5f, 20, 20); //线框球面
glFlush();
}
///
// 鼠标事件处理函数
void myMouse(int _button, int _state, int _x, int _y) {
switch (_button) {
case GLUT_LEFT_BUTTON:
std::cout<<"LEFT <= mouse button is pressed, "; break;
case GLUT_MIDDLE_BUTTON:
std::cout<<"MIDD || mouse button is pressed, "; break;
case GLUT_RIGHT_BUTTON:
std::cout<<"RIGH => mouse button is pressed, "; break;
}
if (_state)
std::cout<<"UP at ["<<_x<<","<<_y<<"]\n";
else
std::cout<<"DOWN at ["<<_x<<","<<_y<<"]\n";
}
///
// 键盘事件处理函数
void myKeyboard(unsigned char _key, int _x, int _y) {
std::cout<<_key<<" is pressed at ["<<_x<<","<<_y<<"]\n";
}
///
// 功能键事件处理函数
void mySpecialKey(int _key, int _x, int _y) {
switch (_key) {
case GLUT_KEY_LEFT:
std::cout<<"LEFT_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_UP:
std::cout<<"UP_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_RIGHT:
std::cout<<"RIGHT_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_DOWN:
std::cout<<"DOWN_ARROW is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_HOME:
std::cout<<"HOME is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_END:
std::cout<<"END is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_INSERT:
std::cout<<"INSERT is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F1:
std::cout<<"F1 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F2:
std::cout<<"F2 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F3:
std::cout<<"F3 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F4:
std::cout<<"F4 is pressed at ["<<_x<<","<<_y<<"]\n";
break;
case GLUT_KEY_F5:
std::cout<<"F5 is pressed at ["<<_x<<","<<_y<<"]\n";
//NEW!!!: 取消键盘字符键事件处理函数
glutKeyboardFunc(NULL);
break;
case GLUT_KEY_F6:
std::cout<<"F6 is pressed at ["<<_x<<","<<_y<<"]\n";
//NEW!!!: 取消键盘功能键事件处理函数
glutSpecialFunc(NULL);
break;
}
}
GLUT_H0_Menu.h
#ifndef GLUT_H0_MENU_H_INCLUDED
#define GLUT_H0_MENU_H_INCLUDED
///
//用于产生菜单的函数
void myCreateMenu(void); // <============ NEW!!!
// 用于处理菜单事件的函数
void myMenuManager(int _item); // <============ NEW!!!
#endif // GLUT_H0_MENU_H_INCLUDED
GLUT_H0_Menu.cpp
///
// 加上必要的头文件 <============== NEW!!!
#include
#include
#include "GLUT_H0_Menu.h"
///
// 菜单生成函数 <============== NEW!!!
void myCreateMenu(void) {
//生成子菜单0
int subMenu0 = glutCreateMenu(myMenuManager); //<=====子菜单0
//添加两个子菜单项
glutAddMenuEntry("SubItem0", 100); //<=====菜单项, 标识码
glutAddMenuEntry("SubItem1", 101); //<=====菜单项, 标识码
//生成子菜单1
int subMenu1 = glutCreateMenu(myMenuManager); //<=====子菜单1
//添加两个子菜单项
glutAddMenuEntry("SubItem0", 200);
glutAddMenuEntry("SubItem1", 201);
//产生主菜单
glutCreateMenu(myMenuManager); //<=====主菜单
//向主菜单添加菜单项
glutAddMenuEntry("Main Menu", '\0'); //<=====菜单项
glutAddMenuEntry("---------------", '\0'); //<=====菜单项
//将两个子菜单添加到主菜单中
glutAddSubMenu("SubMenu-0", subMenu0); //<=====链上子菜单0
glutAddSubMenu("SubMenu-1", subMenu1); //<=====链上子菜单1
glutAddMenuEntry("Exit", 99);
//将(弹出式)菜单附着在特定的鼠标键上
glutAttachMenu(GLUT_RIGHT_BUTTON); //<=====将菜单附着到鼠标
//glutAttachMenu(GLUT_MIDDLE_BUTTON);
}
///
// 处理菜单事件 <============== NEW!!!
void myMenuManager(int _item) {
//根据参数判断哪个菜单项被选中,并进行该菜单项指定的处理
switch (_item) { //分发菜单选中标识
case 99:
exit(0); break;
case 100:
std::cout<<"Processing SumMenu0/item0 ....\n"; break;
case 101:
std::cout<<"Processing SumMenu0/item1 ....\n"; break;
case 200:
std::cout<<"Processing SumMenu1/item0 ....\n"; break;
case 201:
std::cout<<"Processing SumMenu1/item1 ....\n"; break;
default:
std::cout<<"Error occurred!\n"; exit(0);
}
}
main.cpp
///
#include "GLUT_H0_Callbacks.h" //声明回调函数的文件
// 菜单生成与事件处理函数头文件
#include "GLUT_H0_Menu.h" // <========== NEW!!!
///
// 主函数
int main(int argc, char **argv) {
glutInit(&argc, argv);
//对GLUT进行初始化
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//设置绘制窗口大小
glutInitWindowSize(300, 300);
//设置绘制窗口的位置
glutInitWindowPosition(400, 0);
//产生一个名为“Hello”的绘制窗口
glutCreateWindow("Hello");
//注册绘制函数
glutDisplayFunc(myDrawing);
//注册键盘字符键事件处理函数
glutKeyboardFunc(myKeyboard);
//注册键盘功能键事件处理函数
glutSpecialFunc(mySpecialKey);
//注册鼠标事件处理函数
glutMouseFunc(myMouse);
myCreateMenu(); //生成菜单 <==================== NEW!!!
//主消息循环
glutMainLoop(); //进入消息循环
return 0;
}
新增的知识点:
绘制结果: