OpenGL学习之路

碎碎念:

最近老是出去玩,感觉要收收心,但也感觉应该出去走走。向来平衡都不太好找。

刚接触OpenGL,还算是比较顺利的配好了环境,比opencv要好配。差不多就是把几个文件之类的加进来就可以。(之前也记录了一下)

这里呢,也记录一下opengl的学习过程,我感觉是记录大于分享(水平还远达不到分享二字的份量)。下面就开始叭(以案例和代码形式)。

opengl的第一课

(#include <GL/ogl.h> 是俺老师写的头文件,里面有包含<glut.h>)

1.窗口、绘制的回调函数

// GLUT头文件
#include <GL/ogl.h>  //包含了<glut.h> glut.h//中包含了<glu.h>&<gl.h>
#include <stdio.h>

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 <glutCreateWindow> 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 <GL/ogl.h>

// 绘制函数声明             <========== 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 <GL/ogl.h>
#include <iostream>

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: "<<width<<", Height: "<<height<<"\n";

}


///
void myDraw() {
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClear(GL_COLOR_BUFFER_BIT);

	//glPushMatrix();
	glRotatef(30.0, 1.0f, 1.0f, 1.0f);
	glutWireSphere(1.0f, 20, 20);
   //glutWireIcosahedron();

	glFlush();
}

新增知识点:

1.glutReshapeFunc(myReshape): 改变窗口大小时的回调函数

2.回调函数myReshape,将每一次改变后的窗口大小打印下来

绘制结果:

4.点击键盘上普通键('a'或'1')时的回调函数

#include <GL/ogl.h> 
#include <iostream>

///
// 函数声明
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 <GL/ogl.h>
#include <iostream>

///
// 函数声明
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 <GL/ogl.h>
#include <iostream>

///
// 函数声明
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 <GL/glut.h>
#include <iostream>

///
// 声明四个绘制函数
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 <GL/glut.h>
#include <iostream>

///
// 四个绘制函数
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 <GL/glut.h>
#include <iostream>


///
// 函数声明
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 <GL/glut.h>
#include <iostream>
#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;
}

新增的知识点:

绘制结果: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值