OpenGL 键盘控制及鼠标控制实例
- 格式:docx
- 大小:147.54 KB
- 文档页数:5
C# 实例OpenGL是图形硬件的一个软件接口,是一种快速、高质量的3D图形软件。
它提供了近120个绘制点、线点多边形等3D图形的命令,可以完成绘制物体、变换、光照处理、着色、反走样、融合、雾化、位图和图像、纹理映射、动画等基本操作,通过把这一系列基本操作进行组合,可以构造更复杂的3D物体和描绘丰富多彩、千变万化的客观世界。
C#是以运行库为基础的一种编程语言,它几乎集中了所有关于软件开发和软件工程研究的最新成果,如面向对象、类型安全等,并被寄希望成为微软发布的用于企业编写基于COM+和视窗系统的程序语言中的最好的一种[2]。
与C++相比,C#的语法更加简洁,调试更加容易,且应用程序开发更加快速。
把C#和OpenGL结合起来开发3D应用程序和软件,将显著提高开发效率。
在C#中,程序间的依赖项通过符号而不是文本来控制,因而不使用头文件,而且opengl32.dll以及opengl32.lib等文件也不能像在C++中那样进行部署和引用,所以,无法直接使用OpenGL所提供的图形库。
在C#中通过调用OpenGL 动态链接库文件:csgl.dll和csgl.native.dll实现OpenGL所提供的强大的图形功能。
这2个文件可以从网页上获取。
csgl.dll中定义了4个名称空间,即CsGL,CsGL.OpenGL,CsGL.Pointers,CsGL.Util,其中,CsGL.OpenGL定义的4个类OpenGL、GL、GLU、GLUT中封装了几乎所有的OpenGL函数、用户库函数、辅助库函数和实用库函数及常量;类OpenGLControl中定义了OpenGL场景绘制函数,如场景的初始化、场景的绘制函数等;类OpenGLContext中定义了OpenGL环境控制命令,如像素格式、调色板的创建等命令。
CsGL.Util定义了键盘、鼠标事件及异常处理等。
为了能够使用这2个文件,先将这2个文件拷贝到系统文件夹%systemroot%╲system32中,然后在项目的属性页对话框中将"引用路径"设置为系统文件夹%systemroot%╲system32,这样C#就可以找到运行/调试应用程序所需要的库文件。
弹弹堂游戏在C开发环境下使用OpenGL库进行开发弹弹堂游戏是一款极其受欢迎的休闲游戏,玩家可以通过弹射弹性球来消除屏幕上的方块。
在本文中, 将介绍如何利用C开发环境下的OpenGL库来实现弹弹堂游戏的开发。
这个过程将涵盖如何创建游戏窗口、加载资源、绘制游戏元素以及处理用户输入等方面。
1. 引言OpenGL是一个强大的图形渲染库,通过利用它的功能,我们可以轻松实现弹弹堂游戏中的各种效果,例如绘制图形、添加贴图以及实现动画效果等。
C语言是一种方便、简单的编程语言,适用于对底层操作有需求的开发工作。
因此,使用C开发环境下的OpenGL库来开发弹弹堂游戏,不仅能保证程序的高效性,还能满足开发人员对于底层控制的需求。
2. 创建游戏窗口为了在C语言环境下使用OpenGL库进行游戏开发,首先需要创建一个游戏窗口来显示游戏画面。
可以使用OpenGL的工具库来创建窗口,并设置窗口的大小、标题等属性。
在创建窗口后,还需要初始化OpenGL的上下文环境,以确保之后的绘制操作能够正常进行。
3. 加载资源弹弹堂游戏中需要加载的资源包括游戏关卡的地图、玩家的角色模型、音效等。
在C开发环境下,可以利用OpenGL库提供的纹理加载函数来加载贴图资源,并将其应用到游戏元素上。
同时,还可以使用其他C语言的文件操作函数来加载地图数据、读取角色模型等。
4. 绘制游戏元素在弹弹堂游戏中,有许多不同的游戏元素需要绘制,如方块、弹性球、角色模型等。
使用OpenGL库的绘图功能,可以通过指定每个元素的顶点坐标、纹理坐标等属性来绘制它们。
同时,还可以利用OpenGL提供的变换函数来实现元素的平移、旋转、缩放等动画效果。
5. 处理用户输入弹弹堂游戏需要根据用户的输入来控制玩家角色的移动、发射弹性球等操作。
在C语言环境下,可以通过监听键盘或鼠标事件,并根据用户的操作来更新游戏状态。
通过OpenGL库提供的回调函数,可以轻松地捕获用户的输入,并进行相应的处理。
学生实验实习报告册学年学期:2016-2017学年 春□√秋学期课程名称:大学计算机基础学生学院:通信与信息工程学院专业班级:学生学号:学生姓名:联系电话:重庆邮电大学教务处印制实验实习名OpenGL基本使用指导教师秦红星考核成绩课程名称计算机图形学A 课程编号实验实习地点信息科技大厦S306 完成日期学生姓名学生学号学院专业广电与数字媒体类所在班级教师评语教师签名:年月日一、实验实习目的及要求目的:认识了解OpenGL的性质、功能要求:1.利用OpenGL绘制一个简单的场景:比如球体、正方体2.加入灯光3.实现交互操作:平移、缩放、旋转二、实验实习设备(环境)及要求(软硬件条件)采用Microsoft Visual C 2010生成环境并用C++编写程序三、实验实习内容与步骤内容:背景为黑色,在点光源下,能够实现平移、缩放、旋转的球。
步骤:建立立体-->添加光照-->添加变换1.先写“主函数”,在主函数中将窗口生成好。
2.在“自定义函数1”中对窗口进行清除、填色等操作。
3.在“自定义函数1”中设置点光源,设置光照的各种参数。
4.在“自定义函数1”中设置平移、缩放、旋转及各参数。
5.在“自定义函数2”中设置平移和缩放的循环。
6.在主函数中调用这两个自定义函数,并且在主函数里面用“自定义函数1”为参数调用glutDisplayFunc()来注册一个绘图函数。
其次用空闲回调函数glutIdleFunc()来使球体不停地循环有缩放、平移功能的函数。
实现动画。
四、实验实习过程或算法(源程序、代码)#include<GL/glut.h>GLfloat angle = 0.0f;GLfloat multiply = 0.0f;void display(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //设置窗口里面的背景颜色glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(90.0f, 1.0f, 1.0f, 20.0f);glLoadIdentity();gluLookAt(0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);{//设置一个点光源GLfloat light_position[] = { 0.5f,0.0f,0.0f,1.0f };//(xyzw)w为1时代表点光源,0时代表方向光源GLfloat light_ambient[] = { 0.5f,0.5f,0.5f,1.0f };//(0001)GLfloat light_diffuse[] = { 1.0f,1.0f,1.0f,1.0f };//(1111)GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };//(1111)glLightfv(GL_LIGHT0, GL_POSITION, light_position);glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);//光源环境光强值glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);//光源漫反射强值glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);//光源镜面反射强值glEnable(GL_LIGHT0);//打开该光源glEnable(GL_LIGHTING);//打开光照}{glRotatef(angle, 0.0f, 1.0f, 0.0f);glTranslatef(0.0f, 0.0f, 0.6f); //平移glScaled(multiply, multiply, multiply); //缩放glutSolidSphere(0.2, 50, 50);}glutSwapBuffers();}void rotateAndzoom(void) //旋转和缩放{angle += 1.0f;if (angle >= 360.0f)angle = 0.0f;display();//设置旋转multiply += 0.01f;if (multiply >= 2.0f)// multiply -= 0.01f;//if (multiply <= 1.0f)multiply = 1.0f;display();//设置缩放}int main(int argc, char* argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);glutInitWindowPosition(400, 50);glutInitWindowSize(800, 800);glutCreateWindow("立体");glutDisplayFunc(&display);glutIdleFunc(&rotateAndzoom);//旋转glutMainLoop();//调用该函数启动程序,所有以创建的窗口将会显示return 0;}五、实验实习结果分析和(或)源程序调试过程实验实习名直线扫面和区域填充实现指导教师考核成绩课程名称课程编号实验实习地点完成日期学生姓名学生学号学院专业通信与信息工程学院广电与数字媒体类所在班级教师评语教师签名:年月日一、实验实习目的及要求项目目的:熟悉光栅图形学中的相关算法项目要求:1.应用OpenGL点绘制函数直线与区域2.采用直线扫面算法绘制一条线段,直线有离散点组成3.利用区域填充算法绘制多边形区域,区域由离散点组成二、实验实习设备(环境)及要求(软硬件条件)采用Microsoft Visual C 2010生成环境并用C++编写程序三、实验实习内容与步骤内容:1.用DDA算法实现点绘制直线。
OpenGl读取导⼊3D模型并且添加⿏标移动旋转显⽰原⽂作者:aircraft最近实习要⽤到opengl库就是跟opencv 有点像的那个,然后下了⼀个3D模型的读取显⽰来研究现在分享给⼤家吧注释基本我都打好了,所以也懒得再写很多解析了,⾃⼰看注释吧!本⽂⽤到obj ⽂件的百度云下载是:控制⼀个3d模型不难,那么控制多个呢?看下⾯这篇博客:下载之后,复制代码到⾃⼰的项⽬运⾏改⼀个那个我定义的路径,然后还要配置⼀下opengl和openmesh来读取obj⽂件解析,,配置过程肯定会出现很多的问题的没事习惯就好加油⾃⼰百度去不要来问我路径就是这个:改⼀下file变成你们⾃⼰的就⾏了,,最后说⼀下配置有问题⾃⼰百度OK 百度⽆敌⼀、操作⿏标控制物体旋转移动,滚轮缩放,上下左右键可以控制模型的移动F1,F2,F3,F4,F5,F6,F7,F8可以更换显⽰⽂件Insert键更换显⽰模式 (wire,flat,flatlines)⼆、实验演⽰按F1 读⼊⼀个 cow的 obj⽂件切换为只显⽰线的模式:切换为可以显⽰线和⾯⼀起的模式:可以实现旋转:旋转之后:可以实现缩放:缩⼩:可以实现平移:按完相应键盘的按键之后,就会进⾏⼊读obj⽂件,使⽤命令⾏显⽰当前状态#include <iostream>#include<stdlib.h>#include<OpenMesh/Core/IO/MeshIO.hh>#include<OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>#include<GL/glut.h>#include <math.h>#include <Windows.h>#include <string>#define GLUT_WHEEL_UP 3 //定义滚轮操作#define GLUT_WHEEL_DOWN 4using namespace std;typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;//⿏标交互有关的int mousetate = 0; //⿏标当前的状态GLfloat Oldx = 0.0; // 点击之前的位置GLfloat Oldy = 0.0;GLuint texture;//与实现⾓度⼤⼩相关的参数,只需要两个就可以完成float xRotate = 0.0f; //旋转float yRotate = 0.0f;float ty = 0.0f;float tx = 0.0f;float scale = 0.004;//⽂件读取有关的MyMesh mesh; //mesh把⽂件读取了,封装在mesh对象中//"dinosaur.obj";const string file = "D:\\参考项⽬代码\\objdata\\objdata\\";const string file_1 = file + "cow.obj";const string file_2 = file + "bunny.obj";const string file_3 = file + "dinosaur.obj";const string file_4 = file + "mba1.obj";const string file_5 = file + "monkey.obj";const string file_6 = file + "porsche.obj";//const string file_7 = "teddy.obj";const string file_7 = file + "huangfeng.obj";const string file_8 = file + "file.obj";const string file_9 = file + "face.sur";int currentfile = 1;GLuint showFaceList, showWireList;int showstate = 1;bool showFace = true;bool showWire = false;bool showFlatlines = false;void setLightRes() {//GLfloat lightPosition[] = { 0.0f, 0.0f, 1.0f, 0.0f };GLfloat lightPosition[] = { 0.0f, 1.0f, 0.0f, 0.0f }; // 平⾏光源, GL_POSITION属性的最后⼀个参数为0glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);glEnable(GL_LIGHTING); //启⽤光源glEnable(GL_LIGHT0); //使⽤指定灯光}void SetupRC(){//当你想剔除背⾯的时候,你只需要调⽤glEnable(GL_CULL_FACE)就可以了,OPENGL状态机会⾃动按照默认值进⾏CULL_FACE,//默认是glFrontFace(GL_CCW) GL_CCW逆时针为正,GL_CW顺时针glEnable(GL_DEPTH_TEST);glFrontFace(GL_CCW);glEnable(GL_CULL_FACE);// 启⽤光照计算glEnable(GL_LIGHTING);// 指定环境光强度(RGBA)此时可以控制模型的显⽰颜⾊GLfloat ambientLight[] = { 1.0f, 0.0f, 0.0f, 0.0f };// 设置光照模型,将ambientLight所指定的RGBA强度值应⽤到环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);// 启⽤颜⾊追踪//GL_COLOR_MATERIAL使我们可以⽤颜⾊来贴物体。
1.学习在Visual C++ 6.0 中安装glut库操作截图:2. 学习、理解glut库中的基本事件:测试事件glutDisplayFunc();glutSpecialFunc(); 测试程序:#include<GL/glut.h>#include<math.h>#include<stdlib.h>int angle;double pi=3.1415;void init(void){glOrtho(-5,5,-5,5,-1,1);//视野缩放}void display(void){glClear(GL_COLOR_BUFFER_BIT);//清除所有像素glColor3f(1.0,0,0);int i;glPushMatrix();//入栈glTranslatef(0,0,0);glRotatef(angle,0,0,1);glBegin(GL_LINE_LOOP);glColor3f(1,1,0);for(i=0; i<1000; ++i)glVertex2f(0.5*cos(2*pi/1000*i),0.5*sin(2*pi/1000*i));glEnd();glBegin(GL_LINE_LOOP);glColor3f(1,1,0);for(i=0; i<1000; ++i)glVertex2f(-0.75+0.25*cos(2*pi/1000*i),0.25*sin(2*pi/1000*i));glEnd();glBegin(GL_LINE_LOOP);glColor3f(1,1,0);for(i=0; i<1000; ++i)glVertex2f(0.75+0.25*cos(2*pi/1000*i),0.25*sin(2*pi/1000*i));glEnd();glBegin(GL_LINE_LOOP);glColor3f(1,1,0);for(i=0; i<1000; ++i)glVertex2f(0.25*cos(2*pi/1000*i),-0.75+0.25*sin(2*pi/1000*i));glEnd();glBegin(GL_LINE_LOOP);glColor3f(1,1,0);for(i=0; i<1000; ++i)glVertex2f(0.25*cos(2*pi/1000*i),0.75+0.25*sin(2*pi/1000*i));glEnd();glPopMatrix();glFlush();}void Keyboard(int key, int x, int y) //键盘交互{if (key == GLUT_KEY_LEFT){angle+=30;}if (key == GLUT_KEY_RIGHT){angle-=30;}glutPostRedisplay();//重新调用绘制函数}void mymouse(int button,int state,int x,int y){if(state==GLUT_DOWN){if(button==GLUT_LEFT_BUTTON){glTranslatef(-0.5,0,0);//左移}else if(button==GLUT_RIGHT_BUTTON){glTranslatef(0.5,0,0);//右移}glutPostRedisplay();//重新调用绘制函数}return;}void main(int argc, char **argv){glutInit(&argc, argv); // 初始化工具包glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 设置显式模式glutInitWindowSize(640,480); // 设置窗口大小glutInitWindowPosition(100, 150); // 设置窗口位置glutCreateWindow("旋转平移"); // 创建屏幕窗口init();glutMouseFunc(&mymouse);//调用鼠标响应函数glutDisplayFunc(display); // 注册绘制函数glutSpecialFunc(&Keyboard);//调用键盘回调函数glutMainLoop(); // 进入主循环}运行结果:初始位置:当按下键盘←键时图形逆时针旋转如图:同理按下键盘→时,图形顺时针旋转。
OpenGL:轨迹球实现的鼠标旋转轨迹球控制By Terence J. Grant 如果只用鼠标来控制你的模型是不是很酷?轨迹球可以帮你做到这一点,我将告诉你我的实现,你可以把它应用在你的工程里。
我的实现是基于Bretton Wade’s,它是基于Ken Shoemake’s 实现的,最初的版本,你可以从游戏编程指南这本图上找到。
但我还是修正了一些错误,并优化了它。
轨迹球实现的内容就是把二维的鼠标点映射到三维的轨迹球,并基于它完成旋转变化。
为了完成这个设想,首先我们把鼠标坐标映射到[-1,1]之间,它很简单:MousePt.X = ((MousePt.X / ((Width -1) / 2)) -1);MousePt.Y = -((MousePt.Y / ((Height -1) / 2))-1);这只是为了数学上的简化,下面我们计算这个长度,如果它大于轨迹球的边界,我们将简单的把z轴设为0,否则我们把z轴设置为这个二维点映射到球面上对应的z值。
一旦我们有了两个点,就可以计算它的法向量了和旋转角了。
下面我们从构造函数开始,完整的讲解这个类:ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)当点击鼠标时,记录点击的位置void ArcBall_t::click(const Point2fT* NewPt)当拖动鼠标时,记录当前鼠标的位置,并计算出旋转的量。
void ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)如果窗口大小改变,设置鼠标移动的范围void ArcBall_t::setBounds(GLfloat NewWidth, GLfloat NewHeight)下面是完成计算所要用到的数据结果,都是一些矩阵和向量Matrix4fT Transform ={ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };Matrix3fT LastRot = { 1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f };Matrix3fT ThisRot = { 1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f };ArcBallT ArcBall(640.0f, 480.0f);Point2fT MousePt;bool isClicked = false; // 是否点击鼠标bool isRClicked = false; // 是否右击鼠标bool isDragging = false; // 是否拖动在上面定义的变量中,transform是我们获得的最终的变换矩阵,lastRot是上一次鼠标拖动得到的旋转矩阵,thisRot为这次鼠标拖动得到的旋转矩阵。
opengl简单⼊门实例实现任务⽬标:使⽤纹理贴图,增强可视效果应⽤坐标变换,实现场景中不同物体重建采⽤双缓冲技术,实现场景实时绘制具有⼀定的⿏标、键盘交互功能先放效果⿏标的交互功能有:右键暂停转动,左键继续转动,滚轮向前放⼤,向后缩⼩IDE:opengl实现需要库函数。
⽤的编译环境是visual studio。
附上⼀个很好的教程【1】:。
(vs2019也可以⽤)⼀个很好的⼊门教程【2】:。
讲得很仔细,通俗易懂。
前⼏课⽤到的库都没有超过glut的范围。
事实上,对于opengl的实现主要是对于各种库函数的调⽤,所以对于各种库函数的认知很重要。
这⾥也给出⼀个很好的教程【3】:。
ok,在看了上⾯的教程以后肯定对于opengl有了⼀定认识,尤其是第⼆个教程中讲解得⾮常仔细。
所以本⽂接下来的内容是建⽴在对那个教程的学习基础之上,对⼀些我在实践中遇到的问题作出补充。
下⾯就进⼊正⽂。
所包含的头⽂件⽬录1 #include <GL/glut.h>2 #include <stdlib.h>3 #include <stdio.h>最基本的功能是当然是创建⾃⼰的图形并显⽰出来,如上图我创建的是⽇地⽉系统。
需要的函数为display()和main()。
这其中很重要的⼀个知识点就是图像的视图变换/模型变换、投影变换和视⼝变换。
有关这块的内容个⼈觉得教程【2】中讲得不够清楚,可以参考⼀些别的教程。
⽐如:;。
这⾥要介绍⼀下opengl中的坐标轴。
x轴⽔平向右为正,y轴竖直向上为正,z轴垂直屏幕向外为正。
符合右⼿定则。
2020/5/15 13:06:37 对于图像的各种变换做⼀个⼩的补充视图变换即设置/改变观察点的位置,可以这么理解,相当于选择⼀个位置和⽅向设置⼀台照相机。
针对glLookAt()函数⽽⾔,它⼀共有九个参数,3对坐标值。
第⼀对三维坐标是观察点(照相机)在世界坐标中的位置,第⼆对三维坐标是被观察点(物体)的位置。
实验一、Ope nGL直线、圆的绘制1、实验目的1)了解OpenGL图形库的功能和结构;2)学习了解OpenGL程序的基本结构,及常用函数;3 )学习使用OpenGL绘制基本图形(线、圆);2、实验内容1 )使用OpenGL编写一个简单的C++程序,使该程序能够绘制出直线。
2 )使用OpenGL编写一个简单的C++程序,使该程序能够绘制出圆。
3、实验过程1)在系统上配置好OpenGL的环境(头文件,库文件,和链接库文件);2)使用Visual V++6.0新建一个C++文档,并创建相应的工程;3)在文档中引入OpenG啲头文件,编辑代码实现鼠标拖动画直线,画圆。
4、实验结果可单击鼠标左键,然后拖动鼠标画出两条直线,并同时画出圆; 可单击鼠标右键,然后拖动鼠标画出两个圆,并同时画出直线。
结果截图:1.鼠标左键主要控制绘制的直线:石Open诂L直找和园的锭制5、实验代码1. #in elude vgl/glut.h>2. #in elude <math.h>3.3. // GLint pNum = 0;4. GLint px1, py1, px2, py2, ex, cy, r;5. GLint winWidth=600, winHeight=600;-/25.} 26.7. 8. llllllllllllllllll 画直线 llllllllllll 9. void Draw_Brese nham(i nt pStartx,i nt pStarty,i nt 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.27. pEn dx,i nt pEndy) {ll 用Bresenham 算法画直线 int i; if(pStartx==pE ndx) ll 为竖线 if(pStartyv=pE ndy) for(i=pStarty;i<=pE ndy;i++) glVertex2f(pStartx,i); else for(i=pE ndy;i<=pStarty;i++) glVertex2f(pStartx,i); return;-/// 为横线 if(pStarty==pE ndy) { if(pStartx<=pE ndx) { for(i=pStartx;i<=pE ndx;i++) glVertex2f(i,pStarty);} else { for(i=pE ndx;i<=pStartx;i++) glVertex2f(i,pStarty); } return; } // 为斜线 float m=(pE ndy-pStarty)*1.0/(pE ndx-pStartx); 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49.-/ float p;}else-/p=2*m-1; if(m>0 && m<=1) { if(pStartx<pE ndx) { while(pStartx<=pE ndx) { glVertex2f(pStartx++,pStarty); if(p>=0) { p+=2*m-2; pStarty++; } else p+=2*m; } { while(pE ndx<=pStartx) {50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71.} else glVertex2f(pE ndx++,pE ndy); if(p>=0) { p+=2*m-2; pEndy++; } else p+=2*m; } } return; } p=-2*m-1; if(m<0 && m>=-1) { if(pStartx<pE ndx) { while(pStartx<=pE ndx) { glVertex2f(pStartx++,pStarty);72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93.} elseif(p>=0) { p+=-2*m-2; pStarty--; } else p+=-2*m; } } else { while(pE ndx<=pStartx) { glVertex2f(pE ndx++,pE ndy); if(p>=0) { p+=-2*m-2; pEn dy--; p+=-2*m;94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115.} else } return; } p=2/m-1; if(m>1) { if(pStartyvpE ndy) { while(pStartyv=pE ndy) { glVertex2f(pStartx,pStarty++); if(p>=0) { p+=2/m-2; pStartx++; p+=2/m; }116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137.-/else {while(pE ndyv=pStarty) {glVertex2f(pE ndx,pE ndy++); if(p>=0) {p+=2/m-2; pEndx++; } else p+=2/m; } }return;} p=-2/m-1; if(pStarty<pE ndy) { while(pStarty<=pE ndy)138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153.154. 155. 156. 157. 158. 159.-/181.{glVertex2f(pStartx,pStarty++);if(p>=0){p+=-2/m-2;pStartx--;}elsep+=-2/m;}}else{while(pE ndyv=pStarty){glVertex2f(pE ndx,pE ndy++);if(p>=0){p+=-2/m-2;pEn dx--;}else160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180.-/203. }182.p+=-2/m; 183. }184. }185. }186.187.////////////////// 画圆//////////// 188. /////////其他象限绘制189. void CirclePoi nts(i nt x,i nt y){190.// 第1象限191.glVertex2f(x,y); 192.glVertex2f(y,x);193.// 第2象限194.glVertex2f(-x,y); 195.glVertex2f(-y,x);196.// 第3象限197.glVertex2f(-y,-x); 198.glVertex2f(-x,-y);199.// 第4象限200.glVertex2f(x,-y); 201.glVertex2f(y,-x);202.-/void DrawCircle(i nt cx,i nt cy,i nt radis){ glPushMatrix(); gITra nslatef(cx,cy,0); glPoi ntSize(1);glColor3f(0.5f, 0.5f, 1.0f); glBegi n( GL_POINTS);int x,y; double p; x=0; y=radis; p=1.25-radis; while(x<=y+1) {CirclePoi nts(x,y); x++; if(p>=0) { y--;p+=2.0*(x-y)+5;204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225.〃////////中点算法画圆-/} else p+=2*x+3; }glE nd(); glPopMatrix(); }////////// 绘制坐标轴 void DrawOx(){ glColor3f(0.95, 0.7, 0.8); glPoi ntSize(1); glBeg in (GL_LINES); glVertex2f(-wi nWidth/2,0); glVertex2f(wi nWidth/2,0); glVertex2f(0,wi nH eight/2); glVertex2f(0,-wi nH eight/2); glE nd(); }226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243.244. 245. 246. 247.////////// 显示函数-/ 248. void Display(){249. 〃//////GL_COLOR_BUFFER_BIT(用背景颜色填充) 250. glClear(GL_COLOR_BUFFER_BIT);251.251. DrawOx();253.252. glColor3f(0.0,0.0,1.0);255.253. glBegi n( GL_POINTS);254. //Brese nhamL in e(px1, py1, px2, py2);255. Draw_Brese nham(px1, py1,px2, py2);256. glE nd();257. glBegi n( GL_POINTS);258. Draw_Brese nham(py1, px1,py2, px2);259. glE nd();260. //glBegi n(GL_LINES);261. 〃glVertex2f(px1,py1);262. 〃glVertex2f(px2,py2);263. 〃glVertex2f(py1,px1);264. 〃glVertex2f(py2,px2);265. //glE nd();269.270. DrawCircle(cx,cy,r);271. DrawCircle(cy,cx,r);272.273. III 交换缓冲区274. glutSwapBuffers();275. 〃glFlush();〃刷新绘图命令276. }277.278.279. II 设置渲染状态(听起来满下人,实际上很简单)280. void SetupRC(void)281. {282. II清除颜色(这里为黑色,为了方便找画的那个点)可以理解成背景颜色283. II和glColor4f(1.0f, O.Of, O.Of , 1.0f) 一样,所有参数都在0.0到1.0之间,后缀f是表示参数是浮点型的284. II最后的那个1.0f是透明度,0.0f表示全透明,1.0f 是完全不透明285. glClearColor(1.0f, 1.0f, 1.0f,1.0f);286. }287.287. II当绘制的窗口大小改变时重新绘制,使绘制的图形同比例变化,288. //几乎所有OpenGL程序中的这个函数都是一样的,所以,放心大胆的拷贝吧290. void Chan geSize(i nt w, i nt h)291. {292. wi nWidth = w;293. wi nH eight = h;294. //设置观察视野为窗口大小(用FLASH里面的话来说应该叫设置摄象机视野)295. glViewport(0,0,w,h);296. //重置坐标系统,指定设置投影参数297. glMatrixMode(GL_PROJECTION);298. /////// 调用单位矩阵,去掉以前的投影参数设置299. glLoadIde ntity();300. ////// 设置投影参数301. gluOrtho2D(-w/2,w/2,-h/2,h/2);302. }303.304. ///////////////// 鼠标点击305. void MousePlot(GLi nt butto n,GL int actio n,GL int xMouse,GLi nt yMouse){306. if(butto n==GLUT_LEFT_BUTTON &&-/324.307. px1 = xMouse - win Width/2; 308. py1 = winH eight/2 - yMouse;309. }310.if(butto n==GLUT_LEFT_BUTTONactio n==GLUT_UP){311. px2 = xMouse - win Width/2; 312. py2 = winH eight/2 - yMouse; 313. glutPostRedisplay();314. }315.if(butto n==GLUT_RIGHT_BUTTONactio n==GLUT_DOWN){316. cx=xMouse-wi nWidth/2; 317. cy=wi nH eight/2-yMouse; 318. }319. }320. //////////////// 鼠标移动321.void MouseMove(GLi nt xMouse,GL int yMouse){ 322. px2 = xMouse - win Width/2; 323. py2 = winH eight/2 - yMouse;actio n==GLUT_DOWN){ &&&&r=sqrt(pow((xMouse-wi nWidth/2-cx),2)+pow((wi nH eig-/ ht/2-yMouse-cy),2));325. glutPostRedisplay();326. }327.327. //主函数328. int main (i nt argc, char* argv[])329. {330. glutI ni t(&argc, argv);331. //设置显示模式332. glutI ni tDisplayMode(GLUT_DOUBLE | GLUT_RGB| GLUT_DEPTH);333. //设置窗口大小像素334. glutI nitWin dowSize(600, 600);335. ////设置窗口出现在屏幕的位置336. glutI nitWin dowPositio n(300,160);337. //建立一个叫OpenGL的窗口338. glutCreateWi ndow("Ope nGL-Li ne");340.339. //调用函数Display进行绘制340. glutDisplayF un c(Display);341. ////// 调用鼠标移动函数-/ 342. //glutPassiveMotio nFun c(PassiveMouseMove);-/ 357. } 345. glutMotio nFun c(MouseMove); 346. ... 调用鼠标点击函数 347. glutMouseFu nc(MousePlot); 348. 349.//如果窗口大小改变则调用函数 绘制 350. glutReshapeF un c(Cha ngeSize); 351. //清屏 352. SetupRC(); 353. //循环绘制 354. glutMai nLoop(); 355. 356.return 0; ChangeSize 重新进行。
实验四 OpenGL的简单动画与交互一、实验目的1、学会OpenGL的简单键盘交互操作。
2、掌握OpenGL鼠标交互功能及其简单应用。
3、掌握OpenGL的闲置函数与简单动画。
4、掌握反走样思想和算法。
二、实验内容与要求1、在实验一(画矩形)的基础上添加键盘交互,按W键绘制的矩形上移,按S键矩形下移,按A键矩形左移,按D键矩形右移,如图3-1。
参考步骤如下:(1)在主函数里添加键盘注册回调函数glutKeyboardFunc(mykeyboard);此函数可放在 glutDisplayFunc(display);后面。
(2)在display()绘制函数中修改绘制矩形代码,用变量代替数值参数。
例如: glRectf(-0.5,-0.5,0.5,0.5)改为glRectf(x1,y1,x2,y2);(3)在程序中增加mykeyboard键盘子函数,并在如下代码中进行修改,实现键盘控制矩形移动void mykeyboard(unsigned char key, int x, int y){switch(key){ case 'W':case 'w':// 矩形对角坐标变量修改使得矩形上移 break;case 'S':case 's'://矩形对角坐标变量修改使得矩形下移 break;case 'A':case 'a'://矩形对角坐标变量修改使得矩形左移 break;case 'D':case 'd'://矩形对角坐标变量修改使得矩形右移 break;}//参数修改后调用重画函数,屏幕图形将发生改变glutPostRedisplay();}2、闲置函数的使用与简单动画。
旋转的六边形,如图3-3所示阅读OpenGL旋转的六边形样本框架程序rotate-polygon.cpp,分析程序的实现步骤://样本程序:旋转的六边形#include<glut.h>#include<math.h>#define PI 3.14159 //设置圆周率int n=6, R=10; //多边形变数,外接圆半径float theta=0.0; //旋转初始角度值void Keyboard(unsigned char key, int x, int y);void Display(void);void Reshape(int w, int h);void myidle();void main(int argc, char** argv){ glutInit(&argc, argv); //初始化GLUT库;glutInitWindowSize(700,700); //设置显示窗口大小glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //设置显示模式;(注意双缓冲)glutCreateWindow("A Rotating Square"); // 创建显示窗口glutDisplayFunc(Display); //注册显示回调函数glutReshapeFunc(Reshape); //注册窗口改变回调函数glutIdleFunc(myidle); //注册闲置回调函数glutMainLoop(); //进入事件处理循环}void Display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0,0); //设置红色绘图颜色glBegin(GL_POLYGON); //开始绘制六边形for (int i=0;i<n;i++)glVertex2f( R*cos(theta+i*2*PI/n), R*sin(theta+i*2*PI/n));glEnd();glutSwapBuffers(); //双缓冲的刷新模式;}void myidle(){theta+=1.0;if (theta>=2*PI) theta-=2*PI;glutPostRedisplay(); //重画,相当于重新调用Display(),改编后的变量得以传给绘制函数}void Reshape(GLsizei w,GLsizei h){glMatrixMode(GL_PROJECTION); //投影矩阵模式glLoadIdentity(); //矩阵堆栈清空gluOrtho2D(-1.5*R*w/h,1.5*R*w/h,-1.5*R,1.5*R); //设置裁剪窗口大小glViewport(0,0,w,h); //设置视区大小glMatrixMode(GL_MODELVIEW); //模型矩阵模式}运行该程序,观察旋转动画效果。
opengl使用手册简书【实用版】目录一、OpenGL 简介二、OpenGL 函数库1.核心函数库2.矩阵操作、几何变换和投影变换函数3.扩展库 GLEW三、OpenGL 菜单的使用1.交互式输入设备的处理2.glut 命令与鼠标函数四、总结正文一、OpenGL 简介OpenGL(Open Graphics Library)是一个跨平台的图形编程接口,用于渲染 2D 和 3D 图形。
它被广泛应用于游戏开发、计算机辅助设计、虚拟现实等领域。
OpenGL 提供了丰富的函数库,可以实现各种复杂的图形效果。
二、OpenGL 函数库OpenGL 的函数库主要可以分为核心函数库和扩展库。
核心函数库包含了基本的绘图功能,如绘制几何图元、矩阵操作、几何变换和投影变换等。
扩展库 GLEW(GLEW Extension Wrangler Library)则提供了更多的高级功能,如阴影、纹理贴图等。
1.核心函数库核心函数库包含了许多常用的绘图函数,如:- glBegin():开始绘制- glEnd():结束绘制- glVertex():绘制一个顶点- glColor():设置颜色2.矩阵操作、几何变换和投影变换函数OpenGL 提供了丰富的矩阵操作、几何变换和投影变换函数,如:- glPushMatrix():矩阵入栈- glPopMatrix():矩阵出栈- glTranslate():几何变换(平移)- glRotate():几何变换(旋转)- glScale():几何变换(缩放)- gluPerspective():投影变换3.扩展库 GLEWGLEW 是一个方便的扩展库,可以方便地管理 OpenGL 扩展。
它提供了一系列的函数,如:- glewInit():初始化 GLEW- glewGetError():获取 GLEW 错误- glewCreateContext():创建 OpenGL 上下文- glewMakeCurrent():设置当前 OpenGL 上下文三、OpenGL 菜单的使用OpenGL 支持交互式输入设备,如鼠标和键盘。
实验四OpenGL下图形的交互控制实验目的:通过实验掌握下列知识:1.熟悉OpenGL Glut中常用的回调函数;2.掌握用鼠标对图形进行交互控制的方法;3.掌握用键盘对图形进行交互控制的方法;内容及步骤:一、常用回调函数的介绍1、用于显示的回调函数(1) void glutDisplayFunc(void (*func)(void));注册当前窗口的显示回调函数参数:func:形为void func()的函数,完成具体的绘制操作这个函数告诉GLUT当窗口内容必须被绘制时,那个函数将被调用.当窗口改变大小或者从被覆盖的状态中恢复,或者由于调用glutPostRedisplay()函数要求GLUT 更新时,执行func参数指定的函数.(2) void glutReshapeFunc(void (*func)(int width, int height));指定当窗口的大小改变时调用的函数参数:func:形如void func(int width, int height)处理窗口大小改变的函数.width,height:为窗口改变后长宽.这个函数确定一个回调函数,每当窗口的大小或形状改变时(包括窗口第一次创建),GLUT将会调用这个函数,这个回调函数接受这个窗口新的长宽作为输入参数.2、用于鼠标操作的回调函数(1) void glutMouseFunc(void (*func)(int button, int state, int x, int y));注册当前窗口的鼠标点击回调函数参数:func:形如void func(int button, int state, int x, int y);button:鼠标的按键,为以下定义的常量GLUT_LEFT_BUTTON:鼠标左键GLUT_MIDDLE_BUTTON:鼠标中键GLUT_RIGHT_BUTTON:鼠标右键state:鼠标按键的动作,为以下定义的常量GLUT_UP:鼠标释放GLUT_DOWN:鼠标按下x,y:鼠标按下式,光标相对于窗口左上角的位置当点击鼠标时调用.(2) void glutMotionFunc(void (*func)(int x, int y));当鼠标在窗口中按下并移动时调用glutMotionFunc注册的回调函数(3) void glutPassiveMotionFunc(void (*func)(int x, int y));当鼠标在窗口中移动时调用glutPassiveMotionFunc注册的回调函数参数:func:形如void func(int x, int y);x,y:鼠标按下式,光标相对于窗口左上角的位置,以像素为单位(4) void glutEntryFunc(void (*func)(int state));设置鼠标进出窗口的回调函数参数:func:形如void func(int state);注册的鼠标进出回调函数state:鼠标的进出状态,为以下常量之一GLUT_LEFT 鼠标离开窗口GLUT_ENTERED 鼠标进入窗口当窗口取得焦点或失去焦点时调用这个函数,当鼠标进入窗口区域并点击时,state 为GLUT_ENTERED,当鼠标离开窗口区域点击其他窗口时,state为GLUT_LEFT.3、用于键盘操作的回调函数(1) void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y));注册当前窗口的键盘回调函数参数:func:形如void func(unsigned char key, int x, int y)key:按键的ASCII码x,y:当按下键时鼠标的坐标,相对于窗口左上角,以像素为单位当敲击键盘按键时调用. ( 除了特殊按键,即glutSpecialFunc()中处理的按键,详见glutSpecialFunc() )(2)void glutSpecialFunc(void (*func)(int key, int x, int y));设置当前窗口的键盘特定键的回调函数参数:Func:形如void func(int key, int x, int y);key:按下的特定键,为以下定义的常量GLUT_KEY_F1:F1功能键GLUT_KEY_F2:F2功能键GLUT_KEY_F3:F3功能键GLUT_KEY_F4:F4功能键GLUT_KEY_F5:F5功能键GLUT_KEY_F6:F6功能键GLUT_KEY_F7:F7功能键GLUT_KEY_F8:F8功能键GLUT_KEY_F9:F9功能键GLUT_KEY_F10:F10功能键GLUT_KEY_F11:F11功能键GLUT_KEY_F12:F12功能键GLUT_KEY_LEFT:左方向键GLUT_KEY_UP:上方向键GLUT_KEY_RIGHT:右方向键GLUT_KEY_DOWN:下方向键GLUT_KEY_PAGE_UP:PageUp键GLUT_KEY_PAGE_DOWN:PageDown键GLUT_KEY_HOME:Home键GLUT_KEY_END:End键GLUT_KEY_INSERT:Insert键注意特别:上述键盘和鼠标的回调函数中,都返回光标的当前坐标x和y,注意这个坐标的原点是在窗口左上角,向右为X轴的正方向,向下为Y轴的正方向。
【转】【OpenGL】GLUT 按键处理2010-07-16 15:19转载自hh20040410最终编辑hh20040410GLUT教程键盘输入GLUT允许我们编写程序,在里面加入键盘输入控制,包括了普通键,和其他特殊键(如F1,UP)。
在这一章里我们将学习如何去检测哪个键被按下,可以从GLUT里得到些什么信息,和如何处理键盘输入。
到现在,你应该注意到了,只要你想控制一个事件的处理,你就必须提前告诉GLUT,哪个函数将完成这个任务。
到现在为止,我们已经使用GLUT告诉窗口系统,当窗口重绘时我们想调用哪个渲染函数,当系统空闲时,哪个函数被调用。
当窗口大小改变时,哪个函数又将被调用。
相似的,我们必须做同样的事来处理按键消息。
我们必须使用GLUT通知窗口系统,当某个键被按下时,哪个函数将完成所要求的操作。
我们同样是调用一个函数注册相关的回调函数。
一函数介绍:当你按下一个键后,GLUT提供了两个函数为这个键盘消息注册回调。
①glutKeyboardFunc普通按键的按键消息。
这个函数是告诉窗口系统,哪一个函数将会被调用来处理普通按键消息。
普通键是指字母,数字,和其他可以用ASCII代码表示的键。
函数原型如下: void glutKeyboardFunc(void(*func)(unsigned char key,int x,int y));参数:func: 处理普通按键消息的函数的名称。
如果传递NULL,则表示GLUT忽略普通按键消息。
这个作为glutKeyboardFunc函数参数的函数需要有三个形参。
第一个表示按下的键的ASCII码,其余两个提供了,当键按下时当前的鼠标位置。
鼠标位置是相对于当前客户窗口的左上角而言的。
一个经常的用法是当按下ESCAPE键时退出应用程序。
注意,我们提到过,glutMainLoop函数产生的是一个永无止境的循环。
唯一的跳出循环的方法就是调用系统exit函数。
这就是我们函数要做的,当按下ESCAPE键调用exit函数终止应用程序(同时要记住在源代码包含头文件 stdlib.h)。
实验5 OpenGL模型视图变换一、实验目的:理解掌握OpenGL程序的模型视图变换。
二、实验内容:(1)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换;(2)根据示范代码,尝试完成实验作业;三、实验原理:在代码中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换。
1.display()程序中绘图函数潜在的重复性强调了:在指定的视图变换之前,应该使用glLoadIdentity()函数把当前矩阵设置为单位矩阵。
2.在载入单位矩阵之后,使用gluLookAt()函数指定视图变换。
如果程序没有调用gluLookAt(),那么照相机会设定为一个默认的位置和方向。
在默认的情况下,照相机位于原点,指向Z轴负方向,朝上向量为(0,1,0)。
3.一般而言,display()函数包括:视图变换 + 模型变换 + 绘制图形的函数(如glutWireCube())。
display()会在窗口被移动或者原来先遮住这个窗口的东西被一开时,被重复调用,并经过适当变换,保证绘制的图形是按照希望的方式进行绘制。
4.在调用glFrustum()设置投影变换之前,在reshape()函数中有一些准备工作:视口变换 + 投影变换 + 模型视图变换。
由于投影变换,视口变换共同决定了场景是如何映射到计算机的屏幕上的,而且它们都与屏幕的宽度,高度密切相关,因此应该放在reshape()中。
reshape()会在窗口初次创建,移动或改变时被调用。
OpenGL中矩阵坐标之间的关系:物理坐标*模型视图矩阵*投影矩阵*透视除法*规范化设备坐标——〉窗口坐标(1)视图变换函数gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0,)设置照相机的位置。
把照相机放在(0,0,5),镜头瞄准(0,0,0),朝上向量定为(0,1,0)朝上向量为照相机指定了一个唯一的方向。
OpenGL⿏标交互响应事件OpenGL ⿏标、键盘交互响应事件先来⼀个样例:usesgl,glu,glut;procedure InitEnvironment;cdecl;beginglClearColor(0.6,0.6,0.6,0);//设置清屏颜⾊灰⾊glClear(GL_COLOR_BUFFER_BIT);glPointSize(6);/设置点的⼤⼩glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluOrtho2D(0,400,0,400);end;procedure mydisplay;cdecl;beginglClear(GL_COLOR_BUFFER_BIT);glFlush();end;procedure OnMouse(button,state,x,y:longint);cdecl;beginif (button=GLUT_LEFT_BUTTON)and(state=GLUT_DOWN)then//如果⿏标左键按下beginglColor3f(1,0,0);//红⾊glBegin(GL_POINTS);glVertex2f(x,400-y);//画点glEnd();glFlush();end;if (button=GLUT_MIDDLE_BUTTON)and(state=GLUT_DOWN)then//如果⿏标滚轮按下beginglColor3f(0,1,0);//原谅⾊glBegin(GL_POINTS);glVertex2f(x,400-y);//画点glEnd();glFlush();end;if (button=GLUT_RIGHT_BUTTON)and(state=GLUT_DOWN)then//如果⿏标右键按下beginglColor3f(0,0,1);//蓝⾊glBegin(GL_POINTS);glVertex2f(x,400-y);//画点glEnd();glFlush();end;end;beginglutInit(@argc,argv);glutInitDisplayMode(GLUT_RGB or GLUT_SINGLE);glutInitWindowPosition(500,200);glutInitWindowSize(400,400);//设置窗⼝⼤⼩glutCreateWindow('OpenGL');//建⽴窗⼝InitEnvironment();glutMouseFunc(@OnMouse);//⿏标键盘事件注册glutDisplayFunc(@myDisplay);//调⽤主过程glutMainLoop();end.从上⾯可以看到到,处理⿏标OnMouse事件的函数,⼀定有4个参数。
OpenGL学习笔记——处理键盘输⼊⽤GLFW处理⽤户键盘输⼊有两种⽅式,⼀种是使⽤回调函数,⼀种是在每⼀次游戏循环中处理。
这两种⽅法的最⼤差别在于是否能连续获得键盘输⼊,第⼆种⽅法可以。
⼀、回调函数⽅法介绍对这种⽅法的讲解很详尽,下⾯只简单记录⼀下要点。
我们只需要⾃定义回调函数key_callback,并在进⼊游戏循环前调⽤函数glfwSetKeyCallback(window, key_callback)即可。
下⾯简单介绍回调函数包含的内容。
函数头为void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods),其中,key为按键,例如GLFW_KEY_UP,如果敲下的键不能被GLFW识别,⽐如Play和E-mail,key值就是GLFW_KEY_UNKNOWN;scancode是每个平台⾃定义的表⽰按键的代码,当key值为GLFW_KEY_UNKNOWN时scancode会被⽤来识别键,否则scancode会被忽略;另外它可以和key⼀起⽤来获得键的名字const char* key_name = glfwGetKeyName(GLFW_KEY_W, 0);,第⼆个参数就是scancode。
scancode可以通过const int scancode = glfwGetKeyScancode(GLFW_KEY_X);获得;action代表动作类型,有GLFW_PRESS:按下GLFW_RELEASE:松开GLFW_REPEAT:重复按键其中需要特别注意的是GLFW_REPEAT。
引⽤Stack Overflow上的⼀个回答来解释它的意义:Ask yourself, what is the frequency at which GLFW_REPEAT triggers? The right answer is that this frequency depends on your user's settings. It is exactly the frequency at which characters will appear in any input field in any application if you hold acharacter key. So the only purpose of GLFW_REPEAT is to implement printing in your application and make it look consistent with all other applications on the machine. You definitely should not use GLFW_REPEAT to implement WASD controls andother things like that.也就是说如果我们希望在游戏中通过键盘控制⼀个⼈物的移动的话,是不能依靠GLFW_REPEAT让⼈物跑起来的,⼀个原因是移动速度不由程序员控制,容易引起游戏混乱,另⼀个原因是,如果像下⾯这样定义回调函数:void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){switch (key){// change the position of the cameracase GLFW_KEY_UP:camera_y += camera_speed;break;case GLFW_KEY_DOWN:camera_y -= camera_speed;break;...}}连续按“↑”键会发现摄像机位置先上移⼀个camera_speed的长度,卡顿⼀会⼉,才开始连续向上移动的。
1.学习在Visual C++ 6.0 中安装glut库
操作截图:
2. 学习、理解glut库中的基本事件:
测试事件glutDisplayFunc();glutSpecialFunc(); 测试程序:
#include<GL/glut.h>
#include<math.h>
#include<stdlib.h>
int angle;
double pi=3.1415;
void init(void)
{
glOrtho(-5,5,-5,5,-1,1);//视野缩放
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);//清除所有像素glColor3f(1.0,0,0);
int i;
glPushMatrix();//入栈
glTranslatef(0,0,0);
glRotatef(angle,0,0,1);
glBegin(GL_LINE_LOOP);
glColor3f(1,1,0);
for(i=0; i<1000; ++i)
glVertex2f(0.5*cos(2*pi/1000*i),0.5*sin(2*pi/1000*i));
glEnd();
glBegin(GL_LINE_LOOP);
glColor3f(1,1,0);
for(i=0; i<1000; ++i)
glVertex2f(-0.75+0.25*cos(2*pi/1000*i),0.25*sin(2*pi/1000*i));
glEnd();
glBegin(GL_LINE_LOOP);
glColor3f(1,1,0);
for(i=0; i<1000; ++i)
glVertex2f(0.75+0.25*cos(2*pi/1000*i),0.25*sin(2*pi/1000*i));
glEnd();
glBegin(GL_LINE_LOOP);
glColor3f(1,1,0);
for(i=0; i<1000; ++i)
glVertex2f(0.25*cos(2*pi/1000*i),-0.75+0.25*sin(2*pi/1000*i));
glEnd();
glBegin(GL_LINE_LOOP);
glColor3f(1,1,0);
for(i=0; i<1000; ++i)
glVertex2f(0.25*cos(2*pi/1000*i),0.75+0.25*sin(2*pi/1000*i));
glEnd();
glPopMatrix();
glFlush();
}
void Keyboard(int key, int x, int y) //键盘交互
{
if (key == GLUT_KEY_LEFT)
{
angle+=30;
}
if (key == GLUT_KEY_RIGHT)
{
angle-=30;
}
glutPostRedisplay();//重新调用绘制函数
}
void mymouse(int button,int state,int x,int y)
{
if(state==GLUT_DOWN)
{
if(button==GLUT_LEFT_BUTTON)
{
glTranslatef(-0.5,0,0);//左移
}
else if(button==GLUT_RIGHT_BUTTON)
{
glTranslatef(0.5,0,0);//右移
}
glutPostRedisplay();//重新调用绘制函数
}
return;
}
void main(int argc, char **argv)
{
glutInit(&argc, argv); // 初始化工具包
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 设置显式模式glutInitWindowSize(640,480); // 设置窗口大小
glutInitWindowPosition(100, 150); // 设置窗口位置
glutCreateWindow("旋转平移"); // 创建屏幕窗口
init();
glutMouseFunc(&mymouse);//调用鼠标响应函数
glutDisplayFunc(display); // 注册绘制函数
glutSpecialFunc(&Keyboard);//调用键盘回调函数
glutMainLoop(); // 进入主循环
}
运行结果:
初始位置:
当按下键盘←键时图形逆时针旋转如图:
同理按下键盘→时,图形顺时针旋转。
当点击鼠标左键时,图形向左移动如图:
当点击鼠标右键时,图形向右移动如图:。