您的位置:首页 > 编程语言

OpenGL学习-3-键盘事件注册以及投影矩阵变换练习代码

2015-03-15 17:10 417 查看
#include<stdio.h>
#include<windows.h>
#include<glut.h>
#include<glaux.h>

void init(void);
void CALLBACK reshape(GLsizei w,GLsizei h);
void CALLBACK On0KeyDown(void);
void CALLBACK On1KeyDown(void);
void CALLBACK OnLButtonDown(AUX_EVENTREC *);
void CALLBACK OnLButtonMove(AUX_EVENTREC *);
void CALLBACK display(void);
void drawCoordinates(void);

GLint mx,my;//鼠标的坐标
GLint m_state = 0;//设置鼠标操作所属的模式
GLfloat x_angle = 0.0f, y_angle = 0.0f;//摄像机的角度
GLfloat dist = 10.0f;//设置摄像机的远近

void init(void)
{
}

void CALLBACK reshape(GLsizei w,GLsizei h)//回调函数,用于在改变窗口大小时由系统自行调用
//!!注意!!GLsizei为正确类型!而非GLsize
{
glViewport(0,0,w,h);//视口函数,指定了视口的左下角(在第一象限内,以(0,0)为原点)位置?
glMatrixMode(GL_PROJECTION);//指定哪一个矩阵是当前矩阵
//此模式表示对投影矩阵应用随后的矩阵操作
glLoadIdentity();//将当前用户坐标系的原点移到了屏幕中心,类似于一个复位操作

if(h < 1) h=1;//防止分母为0出错
gluPerspective(30.0, 1.0*w/h, 0.1, 20.0);//设置透视投影矩阵
//参数为fovy,aspect,zNear,zFar
//参数fovy指定视景体的视野的角度,以度数为单位,y轴的上下方向
//参数的大小即是摄像头视角的大小(投影的锥形的扩张角度),数字越大可以看到的范围就越大,图形的近大远小也就越明显,图像也越容易扭曲
//参数aspect指定你的视景体的宽高比(x平面上),为了避免图形扭曲一般区窗口宽高比的一倍
//zNear指定观察者到视景体最近的裁剪面的距离  (必须为正数)
//zFar与上面的参数相反,指定观察者到视景体的最远的裁剪面的距离(必须为正)
//以上两个参数就是决定将视锥中的哪一段圆台裁剪出来投影到矩阵中

glMatrixMode(GL_MODELVIEW);//对模型视景矩阵堆栈应用随后的矩阵操作
glLoadIdentity();//将当前用户坐标系的原点移到了屏幕中心,类似于一个复位操作
}

void CALLBACK On0KeyDown(void){m_state=0;}
void CALLBACK On1KeyDown(void){m_state=1;}
//按下0或1键时,记录当前选择的操作模式

void CALLBACK OnLButtonDown(AUX_EVENTREC *event)
//鼠标按下时的回调函数,记录按下时鼠标的位置,作为计算位移的初始点
{
mx=event->data[AUX_MOUSEX];
my=event->data[AUX_MOUSEY];
}

void CALLBACK OnLButtonMove(AUX_EVENTREC *event)
//鼠标拖拽使的回调函数,根据位移后的位置和记录的开始位移位置改变摄像头的拍摄角度
{
GLint dx,dy;//声明记录位移大小的变量

dx = event->data[AUX_MOUSEX]-mx;
dy = event->data[AUX_MOUSEY]-my;
//计算位移
//在鼠标未按下时,鼠标位移调用的mx,my与dx,dy相同,所以不会造成角度变换,对于这个设置的保证在下方
mx=event->data[AUX_MOUSEX];
my=event->data[AUX_MOUSEY];
//将鼠标位置更新为当前位置,若没有这一步图像可能在点击一次后移动鼠标即会快速转动,并且离点击位置越远转动速度越快,无法表现出拖拽的效果

if(m_state==0)//在模式为0时将鼠标的位移记录到坐标轴旋转中
{
y_angle += dx*0.1f;
x_angle += dy*0.1f;
//由位移计算出绕x,y轴旋转的角度,保存至y_angle,x_angle
//所乘系数的大小关系到旋转的速度
//!!特别注意!!因为使用上的感觉,左右的位移就像是在转动竖直的坐标轴的操作,所以在X方向上的位移是保存至y_angle,在Y方向上的位移保存至x_angle
}

else if(m_state==1)//在模式为1是将鼠标的位移记录到摄像头距离中
{
dist+=(dx+dy)*0.01f;
}

display();
//调用显示函数
}

void CALLBACK display(void)//回调函数,用于在窗口内显示图像时由系统调用,在窗口大小改变后会被自动调用
{
glClearColor(0.0f,0.0f,0.0f,0.0f);//清理窗口内容,设置背景颜色。由RGBA数字代表颜色;
//绘制图形时尽量避免设置透明图形,因为透明效果显示时需要对图像显示层数进行排序
glClear(GL_COLOR_BUFFER_BIT);//清除缓冲,此参数代表清除颜色缓冲,color改为depth为清除深度缓冲

glPushMatrix();//将当前的矩阵保存入堆栈顶,当前矩阵的值不变
glTranslated(0.0,0.0,-dist);
//平移坐标系,三个参数分别代表向x轴正方向、y轴正方向和z轴正方向平移的距离
//无法理解为何前两个参数只有在第一次显示图形时才会起作用
glRotatef(x_angle,1.0f,0.0f,0.0f);
glRotatef(y_angle,0.0f,1.0f,0.0f);
//旋转坐标系,第一个参数为旋转角度,后三个参数为旋转轴的方向向量
drawCoordinates();
auxWireTeapot(0.5);//glaux自带的画壶函数,括号内参数代表壶的大小
glPopMatrix();//栈顶矩阵出栈,读取当时保存的矩阵的值
glFlush();//强制刷新缓冲函数,保证图形绘制命令被执行而不是存储在缓冲区
//auxSwapBuffers();//利用双缓冲技术避免经常刷新带来的屏幕闪烁
}

void drawCoordinates(void)//绘制坐标轴
{
//glLineWidth(3.0f);//设置绘制线段的宽度

glColor3f(1.0f,0.0f,0.0f);//设置接下来绘制图形的颜色,此为红色
glBegin(GL_LINES);//此函数代表某种图形绘制的开始,参数为所要绘制图形的类型;
glVertex3f(0.0f,0.0f,0.0f);
glVertex3f(1.0f,0.0f,0.0f);//代表绘制的线段的两个端点在坐标系中的位置

//!!注意!!坐标系中一个单位长度为视口高/宽的1/2

glEnd();//此图形绘制结束

glColor3f(0.0f,1.0f,0.0f);//设置接下来绘制图形的颜色,此为绿色
glBegin(GL_LINES);//此函数代表某种图形绘制的开始,参数为所要绘制图形的类型;
glVertex3f(0.0f,0.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);//代表绘制的线段的两个端点在坐标系中的位置
glEnd();//此图形绘制结束

glColor3f(0.0f,0.0f,1.0f);//设置接下来绘制图形的颜色,此为蓝色
glBegin(GL_LINES);//此函数代表某种图形绘制的开始,参数为所要绘制图形的类型;
glVertex3f(0.0f,0.0f,0.0f);
glVertex3f(0.0f,0.0f,1.0f);//代表绘制的线段的两个端点在坐标系中的位置
glEnd();//此图形绘制结束
}

void main(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);//glaux函数:设置显示模式,single代表单缓冲,一般用于静态绘制,RGBA表示红绿蓝透明度色彩模式
auxInitPosition(0,0,500,500);//glaux函数:设置窗口位置和大小,前两位代表新建窗口时左上角的位置,后两位代表窗口的宽和高
auxInitWindow("MyWindow");//glaux函数:创建窗口,函数参数为窗口的名字
init();

printf("0 key down means control the angle of the eye\n");
printf("1 key down means control the distance of the eye\n");
//由控制台给出使用说明

auxReshapeFunc(reshape);//注册回调函数,使之能被系统调用
auxKeyFunc(AUX_0,On0KeyDown);//注册回调函数,使之能被系统调用
//两个参数分别是代表所绑定按键的整数和指向按键绑定的函数的指针
auxKeyFunc(AUX_1,On1KeyDown);//注册回调函数,使之能被系统调用
auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSEDOWN,OnLButtonDown);//注册回调函数,使之能被系统调用
//参数的含义分别是代表所绑定的鼠标按键、按键的状态和指向所绑定函数的指针
auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSELOC,OnLButtonMove);//注册回调函数,使之能被系统调用
auxMainLoop(display);//注册回调函数,使之能被系统调用
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: