OpenGL入门(三):图形随鼠标转动
2017-03-02 21:36
411 查看
void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
函数功能:定义一个视图矩阵,并与当前矩阵相乘。
eyex,eyey,eyez表示相机在世界坐标系中的位置;
centerx,centery,centerz表示镜头对准的物体在世界坐标系中的位置;
upx,upy,upz相机顶部向上的方向在世界坐标系中的方向。
glColor3f(A,B,C);
函数功能:颜色设定,0.0不使用颜色成分,1.0使用颜色成分的最大值。
if(state == GLUT_DOWN) //相当于“如果某个鼠标键被按下”
if(state == GLUT_UP) //相当于“如果某个鼠标键被放开”
if(button == GLUT_LEFT_BUTTON) //相当于“如果鼠标左键被按下或者被放开”
if(button == GLUT_RIGHT_BUTTON) //相当于“如果鼠标右键被按下或被放开”
if(button == GLUT_MIDDLE_BUTTON) //相当于“如果鼠标中键被按下或者被放开”
void glEnable(GLenum cap);
函数功能:启用由参数决定的功能,与glDisable相对应,glDisable是用来关闭的,两个函数的参数取值是一致的。
参数说明:GLenum 是unsigned int类型;cap 是一个取值,由值决定启用功能。
说明:glEnable不能写在glBegin和glEnd两个函数中间。
参数cap的取值如下表所示:
glViewport(GLint x,GLint y,GLsizei width,GLsizei height)
在屏幕上打开窗口的任务是由窗口系统,而不是OpenGL负责的,在默认情况下,视口被设置为占据打开窗口的整个像素矩形,窗口大小和设置视口大小相同。
x,y——以像素为单位,指定了视口的左下角。
width,height——表示这个视口矩形的宽度和高度。
glMatrixMode(Mode);
设置当前矩阵模式:
GL_MODELVIEW 对模型视景矩阵堆栈应用随后的矩阵操作.
GL_PROJECTION 对投影矩阵应用随后的矩阵操作.
GL_TEXTURE 对纹理矩阵堆栈应用随后的矩阵操作.
与glLoadIdentity()一同使用
glLoadIdentity();
函数功能:将图形的当前点移到了屏幕中心,类似于一个复位操作。
注意:用一个单位矩阵来替换当前矩阵的做法并非在任何场合下都可以使用
例如,已经进行了3次矩阵变换,而现在打算将当前矩阵恢复到第二次变换后的状态时,该方法将失效。此时可用glPushMatrix()命令将每次变换前的矩阵压入矩阵堆栈,在进行完新矩阵中的各种操作后,再利glPopMatrix()命令将栈顶的矩阵弹出矩阵堆栈,成为当前矩阵。
glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
函数功能:将当前的可视空间设置为正投影空间。
六个参数, 前两个是x轴最小坐标和最大坐标,中间两个是y轴,最后两个是z轴值
它创建一个平行视景体(就是一个长方体空间区域)。
实际上这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。
其中近裁剪平面是一个矩形,矩形左下角点三维空间坐标是(left,bottom,-near),
右上角点是(right,top,-near);远裁剪平面也是一个矩形,左下角点空间坐标是(left,bottom,-far),右上角点是(right,top,-far)。
注意,所有的near和far值同时为正或同时为负, 值不能相同。如果没有其他变换,正射投影的方向平行于Z轴,且视点朝向Z负轴。这意味着物体在视点前面时far和near都为负值,物体在视点后面时far和near都为正值。
只有在视景体里的物体才能显示出来。
如果最后两个值是(0,0),也就是near和far值相同了,视景体深度没有了,整个视景体都被压成个平面了,就会显示不正确。
void glFrustum(GLdouble left, GLdouble Right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
函数功能:创建一个透视投影的矩阵,并且用这个矩阵乘以当前矩阵,这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的离视点的距离值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值(near/far 必须>0)。
void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);
函数功能:创建一个对称的透视型视景体,但它的参数定义于前面的不同,如图。其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在Y-Z平面的角度,范围是[0.0, 180.0];参数aspect是投影平面宽度与高度的比率;参数Near和Far分别是近远裁剪面到视点(沿Z负轴)的距离,它们总为正值。
代码如下:
运行结果:
函数功能:定义一个视图矩阵,并与当前矩阵相乘。
eyex,eyey,eyez表示相机在世界坐标系中的位置;
centerx,centery,centerz表示镜头对准的物体在世界坐标系中的位置;
upx,upy,upz相机顶部向上的方向在世界坐标系中的方向。
glColor3f(A,B,C);
函数功能:颜色设定,0.0不使用颜色成分,1.0使用颜色成分的最大值。
值 | 颜色 |
---|---|
glColor3f(0.0,0.0,0.0) | 黑色 |
glColor3f(1.0,0.0,0.0) | 红色 |
glColor3f(0.0,1.0,0.0) | 绿色 |
glColor3f(0.0,0.0,1.0) | 蓝色 |
glColor3f(1.0,1.0,0.0) | 黄色 |
glColor3f(1.0,0.0,1.0) | 品红色 |
glColor3f(0.0,1.0,1.0) | 青色 |
glColor3f(1.0,1.0,1.0) | 白色 |
Static //Example2 //File1第一个代码文件的代码 #include<iostream.h> void fn(); //声明fn函数 static int n; //定义静态全局变量 void main() { n=20; cout<<n<<endl; fn(); } //File2第二个代码文件的代码 #include<iostream.h> extern int n;//用extern声明不能使用静态全局变量 void fn() { n++; printf("%d",n); } 全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过extern全局变量名的声明,就可以使用全局变量。 全局静态变量是显式用static修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用extern声明也不能使用。 静态函数不能被其它文件所用;其它文件中可以定义相同名字的函数,不会发生冲突。
if(state == GLUT_DOWN) //相当于“如果某个鼠标键被按下”
if(state == GLUT_UP) //相当于“如果某个鼠标键被放开”
if(button == GLUT_LEFT_BUTTON) //相当于“如果鼠标左键被按下或者被放开”
if(button == GLUT_RIGHT_BUTTON) //相当于“如果鼠标右键被按下或被放开”
if(button == GLUT_MIDDLE_BUTTON) //相当于“如果鼠标中键被按下或者被放开”
void glEnable(GLenum cap);
函数功能:启用由参数决定的功能,与glDisable相对应,glDisable是用来关闭的,两个函数的参数取值是一致的。
参数说明:GLenum 是unsigned int类型;cap 是一个取值,由值决定启用功能。
说明:glEnable不能写在glBegin和glEnd两个函数中间。
参数cap的取值如下表所示:
类型 | 值 | 说明 |
---|---|---|
GL_ALPHA_TEST | 4864 | 跟据函数glAlphaFunc的条件要求来决定图形透明的层度是否显示 |
GL_AUTO_NORMAL | 3456 | 执行后,图形能把光反射到各个方向 |
GL_BLEND | 3042 | 启用颜色混合。例如实现半透明效果 |
GL_CLIP_PLANE0 ~ GL_CLIP_PLANE5 | 12288 ~ 12283 | 根据函数glClipPlane的条件要求,启用图形切割管道。这里指六种缓存管道 |
GL_COLOR_LOGIC_OP | 3058 | 启用每一像素的色彩为位逻辑运算 |
GL_COLOR_MATERIAL | 2930 | 执行后,图形(材料)将根据光线的照耀进行反射,反射要求由函数glColorMaterial进行设定 |
GL_CULL_FACE | 2884 | 根据函数glCullFace要求启用隐藏图形材料的面 |
GL_DEPTH_TEST | 2929 | 启用深度测试,根据坐标的远近自动隐藏被遮住的图形(材料) |
GL_DITHER | 3024 | 启用抖动 |
GL_FOG | 2912 | 雾化效果,例如距离越远越模糊 |
GL_INDEX_LOGIC_OP | 3057 | 逻辑操作 |
GL_LIGHT0 ~ GL_LIGHT7 | 16384 ~ 16391 | 启用0号灯到7号灯(光源),光源要求由函数glLight函数来完成 |
GL_LIGHTING | 2896 | 启用灯源 |
GL_LINE_SMOOTH | 2848 | 执行后,过虑线段的锯齿 |
GL_LINE_STIPPLE | 2852 | 执行后,画虚线 |
GL_LOGIC_OP | 3057 | 逻辑操作 |
GL_MAP1_COLOR_4 | 3472 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1生成RGBA曲线 |
GL_MAP1_INDEX | 3473 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1生成颜色索引曲线 |
GL_MAP1_NORMAL | 3474 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1生成法线 |
GL_MAP1_TEXTURE_COORD_1 | 3475 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1生成文理坐标 |
GL_MAP1_TEXTURE_COORD_2 | 3476 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1生成文理坐标 |
GL_MAP1_TEXTURE_COORD_3 | 3477 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1生成文理坐标 |
GL_MAP1_TEXTURE_COORD_4 | 3478 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1生成文理坐标 |
GL_MAP1_VERTEX_3 | 3479 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1在三维空间里生成曲线 |
GL_MAP1_VERTEX_4 | 3480 | 根据函数Map1对贝赛尔曲线的设置,启用glEvalCoord1,glEvalMesh1,glEvalPoint1在四维空间里生成法线 |
GL_MAP2_COLOR_4 | 3504 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2生成RGBA曲线 |
GL_MAP2_INDEX | 3505 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2生成颜色索引 |
GL_MAP2_NORMAL | 3506 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2生成法线 |
GL_MAP2_TEXTURE_COORD_1 | 3507 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2生成纹理坐标 |
GL_MAP2_TEXTURE_COORD_2 | 3508 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2生成纹理坐标 |
GL_MAP2_TEXTURE_COORD_3 | 3509 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2生成纹理坐标 |
GL_MAP2_TEXTURE_COORD_4 | 3510 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2生成纹理坐标 |
GL_MAP2_VERTEX_3 | 3511 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2在三维空间里生成曲线 |
GL_MAP2_VERTEX_4 | 3512 | 根据函数Map2对贝赛尔曲线的设置,启用glEvalCoord2,glEvalMesh2,glEvalPoint2在三维空间里生成曲线 |
GL_NORMALIZE | 2977 | 根据函数glNormal的设置条件,启用法向量 |
GL_POINT_SMOOTH | 2832 | 执行后,过虑线点的锯齿 |
GL_POLYGON_OFFSET_FILL | 32823 | 根据函数glPolygonOffset的设置,启用面的深度偏移 |
GL_POLYGON_OFFSET_LINE | 10754 | 根据函数glPolygonOffset的设置,启用线的深度偏移 |
GL_POLYGON_OFFSET_POINT | 10753 | 根据函数glPolygonOffset的设置,启用点的深度偏移 |
GL_POLYGON_SMOOTH | 2881 | 过虑图形(多边形)的锯齿 |
GL_POLYGON_STIPPLE | 2882 | 执行后,多边形为矢量画图 |
GL_SCISSOR_TEST | 3089 | 根据函数glScissor设置,启用图形剪切 |
GL_STENCIL_TEST | 2960 | 启用模板测试 |
GL_TEXTURE_1D | 3552 | 启用一维文理 |
GL_TEXTURE_2D | 3553 | 启用二维文理 |
L_TEXTURE_GEN_Q | 3171 | 根据函数glTexGen,启用纹理处理 |
GL_TEXTURE_GEN_R | 3170 | 根据函数glTexGen,启用纹理处理 |
GL_TEXTURE_GEN_S | 3168 | 根据函数glTexGen,启用纹理处理 |
GL_TEXTURE_GEN_T | 3169 | 根据函数glTexGen,启用纹理处理 |
在屏幕上打开窗口的任务是由窗口系统,而不是OpenGL负责的,在默认情况下,视口被设置为占据打开窗口的整个像素矩形,窗口大小和设置视口大小相同。
x,y——以像素为单位,指定了视口的左下角。
width,height——表示这个视口矩形的宽度和高度。
glMatrixMode(Mode);
设置当前矩阵模式:
GL_MODELVIEW 对模型视景矩阵堆栈应用随后的矩阵操作.
GL_PROJECTION 对投影矩阵应用随后的矩阵操作.
GL_TEXTURE 对纹理矩阵堆栈应用随后的矩阵操作.
与glLoadIdentity()一同使用
glLoadIdentity();
函数功能:将图形的当前点移到了屏幕中心,类似于一个复位操作。
注意:用一个单位矩阵来替换当前矩阵的做法并非在任何场合下都可以使用
例如,已经进行了3次矩阵变换,而现在打算将当前矩阵恢复到第二次变换后的状态时,该方法将失效。此时可用glPushMatrix()命令将每次变换前的矩阵压入矩阵堆栈,在进行完新矩阵中的各种操作后,再利glPopMatrix()命令将栈顶的矩阵弹出矩阵堆栈,成为当前矩阵。
glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
函数功能:将当前的可视空间设置为正投影空间。
六个参数, 前两个是x轴最小坐标和最大坐标,中间两个是y轴,最后两个是z轴值
它创建一个平行视景体(就是一个长方体空间区域)。
实际上这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。
其中近裁剪平面是一个矩形,矩形左下角点三维空间坐标是(left,bottom,-near),
右上角点是(right,top,-near);远裁剪平面也是一个矩形,左下角点空间坐标是(left,bottom,-far),右上角点是(right,top,-far)。
注意,所有的near和far值同时为正或同时为负, 值不能相同。如果没有其他变换,正射投影的方向平行于Z轴,且视点朝向Z负轴。这意味着物体在视点前面时far和near都为负值,物体在视点后面时far和near都为正值。
只有在视景体里的物体才能显示出来。
如果最后两个值是(0,0),也就是near和far值相同了,视景体深度没有了,整个视景体都被压成个平面了,就会显示不正确。
void glFrustum(GLdouble left, GLdouble Right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
函数功能:创建一个透视投影的矩阵,并且用这个矩阵乘以当前矩阵,这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的离视点的距离值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值(near/far 必须>0)。
void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);
函数功能:创建一个对称的透视型视景体,但它的参数定义于前面的不同,如图。其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在Y-Z平面的角度,范围是[0.0, 180.0];参数aspect是投影平面宽度与高度的比率;参数Near和Far分别是近远裁剪面到视点(沿Z负轴)的距离,它们总为正值。
代码如下:
#include <gl/glut.h> #include <math.h> #define PI 3.1415926535 static int du=90,OriX=-1,OriY=-1; //du是视点和x轴的夹角 static float r=1.5,h=0.0; //r是视点绕y轴的半径,h是视点高度即在y轴上的坐标 static float c=PI/180.0; //弧度和角度转换参数 void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除缓冲,GL_COLOR_BUFFER_BIT :颜色缓冲标志位 glLoadIdentity(); //重置当前矩阵为4*4的单位矩阵 //glRotatef(-135,0.5,0.0,0.0); //旋转 //glTranslatef(0.5,0.5,0.0); //移动原点 //glScalef(0.5,0.5,1); //缩小 /*glBegin(GL_TRIANGLES); glVertex3f(-0.5,-0.5,0.0); glVertex3f(0.5,0.0,0.0); glVertex3f(0.0,0.0,0.0); glEnd();*/ gluLookAt(r*cos(c*du), h, r*sin(c*du), 0.0,0.0,0.0, 0.0,1.0,0.0); //从视点看远点 glColor3f(1.0,0.0,0.0); glutWireTeapot(0.5f); glutSwapBuffers(); //交换两个缓冲区指针 } void Mouse(int button, int state, int x, int y) { if(state == GLUT_DOWN) //记录鼠标按下位置 OriX = x,OriY = y; } void onMouseMove(int x,int y) //处理鼠标拖动 { du += x - OriX; //鼠标在窗口x轴方向上的增量加到视点与x轴的夹角上,就可以左右转 h +=0.03*(y-OriY); //鼠标在窗口y轴方向上的改变加到视点y的坐标上,就可以上下转 if(h>1.0) h=1.0; //对视点y坐标作一些限制,不会使视点太奇怪 else if(h<-1.0) h=-1.0; OriX = x,OriY = y; //将此时的坐标作为旧值,为下一次计算增量做准备 } void init() { glEnable(GL_DEPTH_TEST); //启用深度,根据坐标的远近自动隐藏被遮住的图形(材料) } void reshape(int w,int h) { glViewport(0,0,w,h); //截图;1、2为视口的左下角;3、4为视口的宽度和高度 glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵 glLoadIdentity(); gluPerspective(75.0,(float)w/h,1.0,1000.0); //1、视野在Y-Z平面的角度[0,180];2、投影平面宽度与高度的比率;3、近截剪面到视点的距离;4、远截剪面到视点的距离 glMatrixMode(GL_MODELVIEW); //对模型视景矩阵堆栈应用随后的矩阵操作. } int main(int argc, char* argv[]) { glutInit(&argc, argv); //初始化glut库 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); //设置初始显示模式 glutInitWindowPosition(100,100); glutInitWindowSize(600,600); glutCreateWindow("***************"); init(); glutReshapeFunc(reshape); // glutDisplayFunc(renderScene); // glutIdleFunc(renderScene); //设置不断调用显示函数 glutMouseFunc(Mouse); glutMotionFunc(onMouseMove); //glutDisplayFunc(renderScene); //调用函数 glutMainLoop();//enters the GLUT event processing loop. return 0; }
运行结果:
相关文章推荐
- OpenGL入门学习——第三课 绘制几何图形的一些细节问题
- OpenGL入门示例8——图形平移、旋转、缩放
- 通过屏幕鼠标绘制opengl三维场景图形
- OpenGL入门学习之二——绘制几何图形
- OpenGL 入门基础教程 —— 键盘和鼠标响应
- [OpenGL]用鼠标拖拽图形移动
- opengl入门实例(4)-鼠标事件
- OpenGL入门学习 课程 (三) 绘制几何图形的一些细节问题
- OpenGL入门——画一些简单的图形
- OpenGL入门学习——第二课 绘制几何图形
- OpenGL入门学习之三——绘制几何图形的一些细节问题
- bgfx入门练习1——切换图形API驱动模式DX与OpenGL
- OpenGL程序设计轻松入门
- OpenGL极速入门宝典
- 利用VC+OpenGL实现几种特殊图形效果
- OpenGL编程轻松入门(三)
- OpenGL入门教程
- OpenGL基础图形编程 - OpenGL基本程序结构
- Java语言入门 -- 第六章 Java图形用户接口
- OpenGL编程轻松入门(四)