鼠标响应opengl
使用OpenGL实现三维坐标的鼠标拣选
OpenGL红宝书中提出了一种方法,使用后缓存来处理选择,个人觉得其完全可以替代标准选择机制。
使用方法与标准选择机制比较类似,不同的是其使用颜色来标记物体,每一组对象使用不同的颜色值,当发生选择时将场景以标记颜色在后缓存渲染一遍,然后读取帧缓存中所点选的点的颜色值(获取到颜色后不应交换前后缓存,而应直接清空后缓存以免该单色场景被显示出来),由该颜色值即可以得出被选中的是哪个对象。
和标准选择机制相比,这种方法同样需要重复渲染一次,但是由于其使用的是颜色标记,可以利用顶点缓存来显著地提高渲染速度,这是标准选择机制所无法做到的。
另外,因为读取的是像素数据而不是图元数据,拾取到的像素已经经过了Alpha测试和深度测试,所以也不会出现选取到没有光栅化的完全透明的物体或被遮挡物体的现象。
而在现在的标准24位颜色深度设备情况下,该方法能够标识256*256*256=16777216个不同的对象,这作为一般应用已经足够了。
使用OpenGL实现三维坐标的鼠标拣选Implementation of RIP(Ray-Intersection-Penetration)3D Coordinates Mouse Selection Using OpenGL顾露(武汉理工大学计算机系中科院智能设计与智能制造研究所湖北武汉 430070)摘要(Abstract):本文提出并实现一种用于三维坐标拣选的RIP(Ray-Intersection-Penetration)方法。
介绍了如何在已经渲染至窗口的三维场景中,使用鼠标或者相关设备拣选特定三维对象的方法。
此方法对于正交投影或透视投影均有效,相对于OpenGL自带的选择与反馈机制,本方法无论是拣选精度还是算法实现效率均高出许多,是一种比较通用的解决方案。
关键词(Keywords)正交投影(Ortho-Projection)、透视投影(Perspective-Projection)世界坐标系、屏幕坐标系、三维拣选、OpenGL一、简介(Introduction)OpenGL是一种比较“纯粹”的3D图形API,一般仅用于三维图形的渲染,对于特定领域的开发者(如游戏开发者)而言,如果选择使用OpenGL进行开发,类似碰撞检测的机制就都需要自行编写了。
计算机科技与应用专业毕业论文--基于Opengl的3D游戏设计
摘要随着时代进步,从简单的色块堆砌而成的画面到数百万多边形组成的精细人物,游戏正展示给我们越来越真实且广阔的世界。
对于近几年游戏的发展来说,老式2D游戏的画面、游戏性、互动性已经无法满足各类玩家的需要,而3D游戏无论是在游戏画面的真实程度、操作的流畅程度、以及故事背景方面的优越性都非常突出。
在这种发展趋势下,2D游戏所占领的市场将会变得微乎其微,3D游戏的开发将会成为整个游戏制作领域的一种趋势。
针对于3D游戏开发,OpenGL作为一个3D的应用程序编程接口(API)来说,是非常合适的。
OpengGL作为与硬件无关的软件接口,只要操作系统使用了OpengGL适配器就可以打到相同的效果。
它又是一个开放图形库,在跨平台领域上非常便利。
并且它具有优良的移植性,是广大3D游戏开发者的首选。
本论文为利用OpengGL进行3D射击游戏的设计与开发,采用碰撞检测、粒子系统、MD2模型绘制、3D声效等技术,最终实现一个射击游戏。
关键词:游戏, 基于OpengGL,三维, 射击游戏Abstract: Along with the progress of the times,fine characters from simple color swatch built the picture to the millions of polygons, the game is to show us more and more real and the wide world.For the development of the game in recent years, the old 2D games' screen ,games andinteractive have been unable to meet all kinds of game player needs, while 3D regardless of the game on the game screen reality, smooth operation, and the background of the story of the superiority is very prominent.In this trend, 2D game occupied market will become very little, the development of 3D games will become the game made a trend in the field.For 3D game development, OpenGL as the application programming interface of a 3D (API), is a very suitable. OpengGL as the interface of the software and hardware independence, as long as the operating system uses the OpengGL adapter can reach the same effect. It is also an open graphics library, cross-platform in areas very convenient. And it has good transplantation, is the 3D game developer's choice.In this paper, the design and development of 3D shooting game is to use OpengGL, the collision detection, particle system, MD2 model, 3D sound rendering technology, the ultimate realization of a shooting game.Keywords game, OpengGL, 3D, shooting game目录1 引言 (1)1.1 课题的背景及意义 (1)1.2 毕业设计的任务 (1)1.3 国内外现状的研究 (2)1.4 开发技术与开发平台 (3)1.4.1 开发技术 (3)1.4.2 开发平台 (3)2 OpenGL简介与3D图形学相关 (5)2.1 OpenGL简介 (5)2.1.1 OpenGl特点 (5)2.1.2 OpenGL功能 (6)2.1.3 OpenGL渲染 (7)2.2 3D图形学相关 (8)2.2.1 向量与矩阵 (8)2.2.2 变换 (8)2.2.3 投影 (8)2.2.4 3D裁剪 (9)3 游戏设计 (11)3.1 游戏的组成 (11)3.2 游戏的结构 (11)3.3 本游戏设计 (12)4 关键技术 (15)4.1 摄像机漫游 (15)4.2 碰撞检测 (16)4.3 粒子爆炸 (19)4.4 云雾效果 (20)4.5 简易AI (21)4.6 3D模型 (23)4.7 3D音效 (26)4.8 游戏场景随机地形 (28)5 运行游戏 (30)结论 (36)参考文献 (37)致谢 .................................................................................................................................. 错误!未定义书签。
OPENGL选择模式
OPENGL 选择模式OpenGL 中采⽤⼀种⽐较复杂⽅式实现了拾取拾取操作,即选择模式。
选择模式⼀种绘制模式,它基本思想在⼀次拾拾取操作时,系统根据拾取拾取操作参数(如⿏标位置)⽣成⼀个特定视景体,然后由系统重新绘制场景中所有图元,但这些图元并不会绘制到颜⾊缓存中缓存中,系统跟踪有哪些图元绘制到了这个特定视景体中,并将这些对象 标识符保存到拾取拾取缓冲区数组中。
在OpenGL 中实现 拾取拾取操作主要包括以下步骤操作主要包括以下步骤:1.设置.设置拾取拾取缓冲区缓冲区拾取拾取时,在特定视景体中绘制每个对象都会产⽣⼀个命中消息,命中消息将存放存放在⼀个名字堆栈中,这个名字堆栈就拾取缓冲区。
函数:void glSelectBuffer(GLsizei n, GLunint *buff);指定了⼀个具有n 个元素整形数组buffer 作为拾取拾取缓冲区。
对于每个命中消息,都会在拾取拾取缓冲区数组中添加⼀条记录,每条记录包含了以下信息:(1)命中发⽣时堆栈中名称序号;(2)拾取拾取图元所有顶点最⼤和最⼩窗⼝z 坐标。
这两个值范围都位于[0,1]内,他们都乘以232-1,然后四舍五⼊为最接近⽆符号整数。
(3)命中发⽣时堆栈中内容(物体的名字),最下⾯名称排在最前⾯。
2.进⼊选择模式在定义了拾取拾取缓冲区后,需要激活选择模式。
选择模式指定采⽤函数:GLint glRenderMode(GLenum mode);其中,参数mode 值可以为GL_RENDER (默认值)、GL_SELECT 或GL_FEEDBACK ,分别指定应⽤程序处于渲染模式、选择模式和反馈模式。
应⽤程序⼀直处于当前模式下,直到调⽤本函数改变为其他模式为⽌。
3.名字堆栈操作在选择模式下,需要对名字堆栈进⾏⼀系列操作,包括初始化、压栈、弹栈以及栈顶元素操作等。
void glInitNames();//初始化名字堆栈,其初始状态为空void glPushName(GLuint name);//将⼀个名字压⼊堆栈,其中name 标识图元⼀个⽆符号整数值void glLoad Name(GLuint name);//将名字堆栈栈顶元素替换为name void glPopName();//将栈顶元素弹出4.设置合适变换过程拾取拾取操作可以通过矩形拾取拾取窗⼝来实现,我们可以⽤下⾯函数调⽤:gluPickMatrix(xPick, yPick, widthPick, heightPick, *vp);其中参数xPick 和yPick 指定相对于显⽰区域左下⾓拾取拾取窗⼝中⼼双精度浮点屏幕坐标值。
关于OpenGL模式和D3D模式的解释
OpenGL的英文全称是“Open Graphics Library”,顾名思义,OpenGL便是“开放的图形程序接口”。
opengl就是软件加速,没有的都为硬件加速,软件加速使得画面更为流畅,细腻,看上去比较舒服,硬件加速比较快,闪动的利害,画面也粗糙,但运动比较快,一般游戏中会用到,安装完显卡带的驱动程序而非windows自带的那个都会把opengl给安装上的。
DirectX是一种图形应用程序接口,简单的说它是一个辅助软件,一个提高系统性能的加速软件,由微软创建开发的,微软将定义它为“硬件设备无关性”。
Direct是直接的意思,X是很多东西,加在一起就是一组具有共性的东西前,随着DirectX的不断发展和完善,OpenGL的优势逐渐丧失,至今虽然已有3Dlabs提倡开发的2.0版本面世,在其中加入了很多类似于DirectX中可编程单元的设计,但厂商的用户的认知程度并不高,未来的OpenGL发展前景迷茫关于OpenGL模式和D3D模式的解释- 独乐乐不如齐乐乐点击返回766首页查看海量游戏库| 最全游戏下载| 玩家抢号专区|游戏美女云集| 随心畅谈网游| 全球网游动态| 网游百态大观| 热门话题探讨| 业内走向QQ三国>> 经验心得>> 综合>> 正文关于OpenGL模式和D3D模式的解释2007年10月10日作者:佚名进入论坛打开三国游戏图标后,在登陆前有几项设置,其中1项是选择显卡驱动模式的,应该有不少朋友不明白意思,我在新手训练区也没发现相关资料,就在网上搜了一下发到这里,希望对个别朋友有帮助,自己本来就懂的就当我说废话了,以下是正文:D3D (Direct3D):这是微软为提高3D 游戏在Win95/98中的显示性能而开发的显示程序。
这个基于显示光栅加速引擎非常强大和复杂,它在显示满屏状态,提供多边形计算、贴图场景等优化能力。
由于其只能在满屏提供优化能力,所以在3DSMAX中你只能在最大化显示视角时(如最大化显示TOP、RIGHT、LEFT和PERSPECTIVE视角),才能获得加速能力。
allegro 大鼠标模式下的拖影问题
allegro 大鼠标模式下的拖影问题email:zhangjinren-0218@
2013-11-30 一般情况下, 我们在安装了Cadence 软件之后, 都会碰到在大鼠标情况下的拖影问题, 这往往是由于显卡的兼容性不够造成的, 通常的解决办法是关闭Opengl, 如果我们关闭OPENGL 功能, 可以使大鼠标不出现拖影, 但是在关闭了opengl的情况下面, 我们的3D 和PCB Flip 功能也无法正常使用, 所以会给我们造成很多不必要的麻烦!
鼠标拖影问题见下图.
为了解决既能消除拖影,又能使3D 和Flip 功能,我们需要在环境变量中加入下面一行,这样,即便我们使用大鼠标模式,也不会出现那种拖影问题!
setinfinite_cursor_bug_nt
具体操作方法如下:
在D:\Cadence\SPB_16.6\share\pcb\text(D盘是cadence的安装目录)下打开env文件,用写字板打开,不要使用记事本打开。
然后在这个环境变量里加入(set infinite_cursor_bug_nt),保存并关闭,此时已经解决了拖影问题。
OpenGL教程
在谈出的对话框左边点 Application Settings,找到 Empty project 并勾上,选择 Finish。 然后向该工程添加一个代码文件,取名为“OpenGL.c”,注意用.c 来作为文件结尾。 搞定了,就跟平时的工程没什么两样的。
=====================未完,请勿跟帖=====================
该程序的作用是在一个黑色的窗口中央画一个白色的矩形。下面对各行语句进行说明。
=====================未完,请勿跟帖=====================
怎么样?代码还不算长吧?
首先,需要包含头文件#include <GL/glut.h>,这是 GLUT 的头文件。 本来 OpenGL 程序一般还要包含<GL/gl.h>和<GL/glu.h>,但 GLUT 的头文件中已经自动将 这两个文件包含了,不必再次包含。
可以想象,通过点、直线和多边形,就可以组合成各种几何图形。甚至于,你可以把一段弧 看成是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度。这样 一来弧和圆也可以表示出来了。通过位于不同平面的相连的小多边形,我们还可以组成一个 “曲面”。
=====================未完,请勿跟帖=====================
OpenGL 程序如下:(注意,如果需要编译并运行,需要正确安装 GLUT,安装 方法如上所述)
#include <GL/glut.h>
void myDisplay(void) {
glClear(GL_COLOR_BUFFER_BIT); glRectf(-0.5f, -0.5f, 0.5f, 0.5f); glFlush(); }
计算机图形学基础实验指导书
计算机图形学基础实验指导书目录实验一直线的生成 ............................................................... -..2.-实验二圆弧及椭圆弧的生成........................................................ -..3 -实验三多边形的区域填充 ......................................................... - (4)-实验四二维几何变换 ............................................................. -..5.-实验五裁剪算法 ................................................................. -..6.-实验六三维图形变换 ............................................................. -..7.-实验七BEZIER 曲线生成......................................................... -..8.-实验八交互式绘图技术实现........................................................ -..10-实验一直线的生成一、实验目的掌握几种直线生成算法的比较,特别是Bresenham 直线生成算法二、实验环境实验设备:计算机实验使用的语言: C 或Visual C++ 、OpenGL三、实验内容用不同的生成算法在屏幕上绘制出直线的图形,对不同的算法可设置不同的线形或颜色表示区别。
四、实验步骤直线Bresenham 生成算法思想如下1)画点(x i, y i), dx=x2-x i, dy=y2-y i,计算误差初值P i=2dy-dx , i=1;2)求直线下一点位置x i+i=x i+i 如果P i>0,贝U y i+i=y i+i,否则y i+i=y i;3)画点(x i+i ,y i+i );4)求下一个误差P i+i 点,如果P i>0,贝U P i+i=P i+2dy-2dx,否则P i+i=P i+2dy;i=i+i ,如果i<dx+i 则转步骤2,否则结束操作。
关于OPENGL中与鼠标交互的矩阵算法
移动的方向
放大距离
最后是放大缩小: 算法思想:直接glScalef即可
得到矩阵
边缘的地方 上下左右移动,就 是绕轴转动
�
得到鼠标移动的垂直矢量 放大旋转系数 模化矢量
矩阵相乘得到新的矢量பைடு நூலகம்
其次是移动: 算法思想:当鼠标按下并且移动的时候,会产生2D的矢量,移动的方向就是这个 2D的矢量, 将他投影到当前的矩阵中, 得到一个3D的矢量,最后用glTranslatef来乘以当前的矩阵,达到移动的目的
得到鼠标的移动方向
移动距离 模化矢量
用鼠标控制视图的旋转,缩放,平移是CAD软件不可缺少的一个重要部分, 常见的方法有轨迹球法,在网上可以找到,就是NeHe OpenGL 的第48课, 我这里运用的是矩阵相乘得到的矢量来达到目的的.
轨迹球法在边缘的地方 上下左右移动,会感觉 是转动
首先是旋转: 算法思想:当鼠标按下并且移动的时候,会产生2D的矢量,旋转的方向是这个 2D的矢量的垂直矢量,计算出这个2D的矢量,然后将他投影到当前的矩阵中, 得到一个3D的矢量,最后用glRotatef来乘以当前的矩阵,达到旋转的目的
opengl实验报告
总评成绩:_________________________实验类型: 交互实验名称: 实验2.3草拟姓名: __肖祥炜____________学号: ____201158501103______ 班级: ___计111-1_______电子文档提交: 按时提交____延时提交____未提交____格式正确____基本正确____ 不正确____实验报告: 完整____合格____不合格____实验成绩:____________________验收记录:时间________________ 顺序________________−−−−−−−−−−−−−−−−−−−−一、原创性声明程序参考了drawFreeCurve.c程序自由画线部分,其余的都是自己原创的二、实验要求1.单击左键移动鼠标开始自由绘图。
2.单击鼠标右键绘制随机曲线:(1)单击键盘a放大图形(2)单击键盘b缩小图形三、完成情况●功能1 : 基本内容✧功能描述:✧完成情况: 基本完成实验要求,但是在绘制随机线条时,图案总是显示在左下角,如果图案调到中间左键自由绘制的时候点不在鼠标点上,不知道怎么改!!✧Bug:暂时没有找到✧备注:图形放大会放大到窗口外面。
四、实现方案1.用鼠标响应函数控制左右键,在左键条件下用一个参数记录鼠标单击几次,只有当参数为1 时才响应鼠标移动函数绘制点,所以只要鼠标移动速度比较慢就能自由绘制图形。
2.自由绘制随机曲线:绘制bezier曲线,把他的四个点用随机数代替就行,设置八个随机数分别控制4个点,单击右键,响应一次随机函数给4个点赋值。
3.放大缩小:放大与减少随机函数。
五、创新和亮点六、运行结果给出尽可能完备的测试用例及测试结果(截图)-合法的测试用例至少两个-1:左键单击移动鼠标形成的图案2.右键单击形成的随机曲线3.放大随机曲线- 非法的测试用例至少两个七、源码#include <GL/glut.h>#include <stdlib.h>#include<iostream.h>/* globals */int iPointNum = 0; //定义一个鼠标记录单击几次的参数int w[7];int c,d,f,h,g,j,k; //七个随机数GLsizei wh = 800, ww = 600;int num[7]={0};/* initial window size */GLfloat size = 3.0; /* half side length of square *///红色部分引用drawFreeCurve.c程序的画点部分void drawSquare(int x, int y)//画点函数颜色随机{y=wh-y;glColor3ub( (char) rand()%256, (char) rand()%256, (char) rand()%256); glBegin(GL_POLYGON);glVertex2f(x+size, y+size);glVertex2f(x-size, y+size);glVertex2f(x-size, y-size);glVertex2f(x+size, y-size);glEnd();glFlush();}void myReshape(GLsizei w, GLsizei h)//初始化窗体点部分的{/* adjust clipping box */glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(10.0, (GLdouble)w, 0.0, (GLdouble)h, -10.0, 10.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glViewport(0,0,w,h);glClearColor (1.0, 1.0, 1.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glLineWidth(4.0);glFlush();ww = w;wh = h;}/* display callback required by GLUT 3.0 */void display(void){ glViewport(0,0,ww,wh);}void random()//随机数产生函数{ int i;for( i=0;i<7;i++)w[i]=(int) rand()%100;for(i=0;i<7;i++)num[i]=w[i];}void mouse()/画随机曲线函数{c=w[0]+num[0];d=w[1]+num[1];f=w[2]+num[2];h=w[3]+num[3];g=w[4]+num[4];j=w[5]+num[5];k=w[6]+num[6];GLfloat ControlP[4][3]={{c,c,0.0}, {d,f,0.0},{h,g,0.0}, {j,k,0.0}};glMap1f(GL_MAP1_VERTEX_3,0.0,1.0,3,4,*ControlP);glEnable(GL_MAP1_VERTEX_3);glFlush();glutPostRedisplay();glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glMapGrid1f(100,0.0,1.0);glEvalMesh1(GL_LINE, 0, 100);glFlush();}void MousePlot(GLint button, GLint action, GLint xMouse, GLint yMouse)// 右键鼠标响应函数{if(button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) { if(iPointNum == 0 || iPointNum == 2){iPointNum = 1;GLint x = xMouse; GLint y = wh- yMouse;}else {iPointNum = 2;GLint x = xMouse; GLint y = wh - yMouse;}}if(button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN){ iPointNum = 0;random();mouse();}}void PassiveMouseMove (GLint xMouse, GLint yMouse)//鼠标移动函数{if(iPointNum == 1) {GLint x = xMouse;GLint y = yMouse;drawSquare(x, y);}}void keyboard(unsigned char key, int x, int y)//键盘响应{int i;switch (key) {case 'a':for(i=0;i<7;i++)num[i] *=2;mouse();breakcase 'b':for(i=0;i<7;i++)num[i] /=-2;mouse();break;default:break;}}void main(int argc, char** argv){glutInit(&argc,argv);glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);glutCreateWindow("草拟一");glutInitWindowSize(400, 400);glutInitWindowPosition (100, 100);glutDisplayFunc(display); //回调函数glutReshapeFunc (myReshape);glutMouseFunc(MousePlot); //指定鼠标响应函数glutPassiveMotionFunc(PassiveMouseMove); //指定鼠标移动响应函数glutKeyboardFunc (keyboard); //键盘响应函数glutMainLoop();}。
一个简单的OpenGL拾取例子
一个简单的OpenGL拾取例子【注】OpenGL鼠标拾取的大致样子。
唉,一个堂堂的“医生”,竟然要做这些coding的体力活。
真丢人啊!!#include <GL/glut.h>#include <stdlib.h>#include <stdio.h>void init(){glClearColor(0, 0, 0, 0);}void drawObjects(GLenum mode){if (mode == GL_SELECT) glLoadName(1);glColor3f(1, 0, 0);glRectf(-0.5, -0.5, 1.0, 1.0);if (mode == GL_SELECT) glLoadName(2);glColor3f(0, 0, 1);glRectf(-1.0, -1.0, 0.5, 0.5);}void display(){glClear(GL_COLOR_BUFFER_BIT);drawObjects(GL_RENDER);glFlush();}void processHits(GLint hits, GLuint buffer[]){unsigned int i, j;GLuint names, *ptr;ptr = (GLuint*)buffer;for (i=0; i<hits; i++) {names = *ptr;ptr += 3; // 跳过名字数和深度for (j=0; j<names; j++) {if (*ptr == 1)printf("red\n");elseprintf("blue\n");ptr++;}}#define SIZE 512#define N 5void mouse(int button, int state, int x, int y){GLuint selectBuf[SIZE];GLint hits;GLint viewport[4];if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {glGetIntegerv(GL_VIEWPORT, viewport);// 初始化名称堆栈glSelectBuffer(SIZE, selectBuf);glRenderMode(GL_SELECT);glInitNames();glPushName(0);glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();// 定义一个以光标为中心的NxN拾取区域// 必须对鼠标y坐标求反,从屏幕坐标系转换成世界坐标系gluPickMatrix(x, viewport[3]-y, N, N, viewport);gluOrtho2D(-2, 2, -2, 2);drawObjects(GL_SELECT);glMatrixMode(GL_PROJECTION);glPopMatrix();glFlush();hits = glRenderMode(GL_RENDER);processHits(hits, selectBuf);glutPostRedisplay();}}void reshape(int w, int h)glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION); glLoadIdentity();gluOrtho2D(-2, 2, -2, 2);glMatrixMode(GL_MODELVIEW); glLoadIdentity();}void keyboard(unsigned char key, int x, int y){switch(key){case 'q':exit(0);break;}}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("123");init();glutReshapeFunc(reshape);glutDisplayFunc(display);glutMouseFunc(mouse);glutKeyboardFunc(keyboard);glutMainLoop();return 0;}。
OpenGL轨迹球实现的鼠标旋转
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为这次鼠标拖动得到的旋转矩阵。
Adobe Photoshop CS4 中的 OpenGL
Adobe Photoshop CS4 中的OpenGL/GPU 功能包括:∙任意缩放级别的平滑显示∙带动画效果的缩放工具∙执行一步缩放时的动画过渡∙手掷图像∙鸟瞰视图∙旋转画布∙非方形像素图像的平滑显示∙像素网格∙移动色彩匹配GPU∙通过GPU 绘制画笔笔尖编辑反馈∙3D GPU 功能包括:∙3D 加速∙3D 轴∙3D 光源Widget∙通过直接显示加速3D 交互Bridge CS4 中的GPU 功能包括:∙预览面板∙全屏预览∙幻灯片放映∙“审阅”模式∙疑难排解∙请执行本节的疑难排解步骤, 以尝试解决您的问题。
∙ 1. 关闭“启用OpenGL 绘图”。
∙如果您遇到以下已知问题一节中所述的任何问题, 或任何其它可能与显卡驱动程序有关的问题, 请关闭“Photoshop”>“首选项”>“性能” (Mac OS) 或“编辑”>“首选项”>“性能” (Windows)中的“启用OpenGL 绘图”, 然后执行同样的功能。
如果问题没有再次出现, 请更新您的显示器驱动程序, 然后参见特定问题以了解详细的信息。
如果问题再次出现, 则可能不是显示器驱动程序的问题。
∙ 2. 重置Photoshop 首选项。
∙疑难排解的下一步是在重启Photoshop 后, 立即按住Shift + Option + Command 组合键(Mac OS) 或Shift + Ctrl + Alt 组合键(Windows) 重置首选项。
当询问您“是否要删除Adobe Photoshop 设置文件”时, 请单击“是”, 并重试引起问题的功能。
有关删除Photoshop首选项文件的详细信息, 请参阅“functions, names, and locations of preferences files inPhotoshop CS4”(TechNote kb405012*)。
∙ 3. 更新您的GPU 驱动程序, 然后打开“启用OpenGL 绘图”。
华硕笔记本WIN7系统运行魔兽争霸3鼠标慢、飘,问题解决
华硕笔记本WIN7系统运行魔兽争霸3鼠标慢、飘,问题解决2010-08-31 17:23首先,这个问题网上已经有回答。
我在这里重复一次,是因为还是有很多人问。
我建议大家问之前还是先搜索一下。
当然,会出这个问题也不能怪大家,应该怪英伟达,怪华硕。
所以,我建议大家遇到显卡的任何问题,不要光在群里问,最好去找英伟达和华硕投诉。
我们只有不断地闹,它才会重视,才会解决。
言归正传,使用独立显卡玩《War3》发生鼠标漂移,是于WAR3的程序没有运行到OpenGL造成的。
解决的方法是,运行时加载OpenGL参数。
1、单机单机玩War3,要在运行时加载OpenGL参数,需要位War3启动程序建立一个快捷方式。
方法是,在快捷方式的目标后面,加入一个空格,及“-opengl”。
运行快捷方式即可。
如图:2、战网战网都提供了参数设置功能。
以浩方为例,在选择游戏执行文件时,在“游戏运行参数”一栏里输入“-opengl”即可。
如图:希望英伟达和华硕能妥善解决显卡的问题,不要让用户这么麻烦。
1。
对战平台:HF和VS上有个游戏参数,在那里写上-opengl2。
魔兽争霸:将游戏模式改成OpenGL,这样鼠标会好用很多,切换桌面也会好很多,方法如下:在魔兽争霸的快捷方式-属性-快捷方式-目标最后加上‘ -opengl’不要引号,记得前边有一个空格3。
将显示驱动更新至最合适你显卡的版本,非宽屏显示器尽量将游戏分辨率保持和显示器一样,另外宽屏显示器将分辨率改成与你的桌面分辨率相近的分辨率【注册表会改吧。
】也会好很多,比如:分辨率为1280×800的改成1280×1024。
不建议将魔兽改成宽屏,很不爽4。
系统:如果是普通鼠标,那么下载一个罗技的setpoint安装,如果是高档鼠标,那么安装自带的驱动5。
AMD双核处理器安装双核补丁笔记本是吗?笔记本经常出现这种问题~是16:9的屏幕吗?用的windows7?在开始搜索框输入regedit打开注册表,定位到HKEY_LOCAL_MACHINE------SYSTEM------ControlSet001-------Control-------GraphicsDrivers-------Configuration------然后右键点击Configuration,选择查找,输入Scaling,在右框内即可看到scaling,右键scaling选择修改,将数值改为3即可,原值为4这样可以解决大部分游戏无法全屏有黑边的问题。
Qt_OpenGL_教程
#include "nehewidget.h" int main( int argc, char **argv ) { bool fs = false; 我们把这个布尔型变量的初始值设置为 false。 QApplication a(argc,argv); 每一个 Qt 应用程序都使用 QApplication 类。 switch( QMessageBox::information( 0, "Start FullScreen?", "Would You Like To Run In Fullscreen Mode?", QMessageBox::Yes, QMessageBox::No | QMessageBox:efault ) ) { case QMessageBox::Yes: fs = true; break; case QMessageBox::No: fs = false; break; } 这里弹出一个消息对话框,让用户选择是否使用全屏模式。 NeHeWidget w( 0, 0, fs ); 创建一个 NeHeWidget 对象。 a.setMainWidget( &w ); 设置应用程序的主窗口部件为 w。 w.show(); 显示 w。 return a.exec(); 程序返回。 }
(由 nehewidget.cpp 展开。 ) #include "nehewidget.h" NeHeWidget::NeHeWidget( QWidget* parent, const char* name, bool fs ) : QGLWidget( parent, name ) { fullscreen = fs; 保存窗口是否为全屏的状态。 setGeometry( 0, 0, 640, 480 ); 设置窗口的位置,即左上角为(0,0)点,大小为 640*480。 setCaption( "NeHe's OpenGL Framework" ); 设置窗口的标题为“NeHe's OpenGL Framework” 。 if ( fullscreen ) showFullScreen(); 如果 fullscreen 为真,那么就全屏显示这个窗口。 } 这个是构造函数,parent 就是父窗口部件的指针,name 就是这个窗口部件的名称,fs 就是 窗口是否最大化。 NeHeWidget::~NeHeWidget() { } 这个是析构函数。 void NeHeWidget::initializeGL() { glShadeModel( GL_SMOOTH ); 这一行启用 smooth shading(阴影平滑)。阴影平滑通过多边形精细的混合色彩,并对外部光 进行平滑。我将在另一个教程中更详细的解释阴影平滑。 glClearColor( 0.0, 0.0, 0.0, 0.0 ); 这一行设置清除屏幕时所用的颜色。 如果您对色彩的工作原理不清楚的话, 我快速解释一下。 色彩值的范围从 0.0 到 1.0。0.0 代表最黑的情况,1.0 就是最亮的情况。glClearColor 后的第 一个参数是红色,第二个是绿色,第三个是蓝色。最大值也是 1.0,代表特定颜色分量的最亮 情况。最后一个参数是 Alpha 值。当它用来清除屏幕的时候,我们不用关心第四个数字。现 在让它为 0.0。我会用另一个教程来解释这个参数。 通过混合三种原色(红、绿、蓝) ,您可以得到不同的色彩。希望您在学校里学过这些。因 此 , 当 您 使 用 glClearColor(0.0, 0.0,1.0, 0.0 ) , 您 将 用 亮 蓝 色 来 清 除 屏 幕 。 如 果 您 用 glClearColor(0.5, 0.0, 0.0, 0.0)的话,您将使用中红色来清除屏幕。不是最亮(1.0),也不是最 暗(0.0)。要得到白色背景,您应该将所有的颜色设成最亮(1.0)。要黑色背景的话,您该将所 有的颜色设为最暗(0.0)。 glClearDepth( 1.0 ); 设置深度缓存。 glEnable( GL_DEPTH_TEST ); 启用深度测试。 glDepthFunc( GL_LEQUAL ); 所作深度测试的类型。
计算机图形学OpenGL(第三版)第二章
const int screenWidth = 640; // width of screen window in pixels const int screenHeight = 480; // height of screen window in pixels GLdouble A, B, C, D; // values used for scaling and shifting void myInit(void) {glClearColor(1.0,1.0,1.0,0.0); // background color is white glColor3f(0.0f, 0.0f, 0.0f); // drawing color is black glPointSize(2.0); // a 'dot' is 2 by 2 pixels glMatrixMode(GL_PROJECTION); // set "camera shape" glLoadIdentity(); gluOrtho2D(0.0, (GLdouble)screenWidth, 0.0, (GLdouble)screenHeight); A = screenWidth / 4.0; // x方向的缩放量A B = 0.0; //x方向的平移量B C = D = screenHeight / 2.0;// y方向的缩放量C和平移量D } void myDisplay(void) {glClear(GL_COLOR_BUFFER_BIT); // clear the screen glBegin(GL_POINTS); for(GLdouble x = 0; x < 4.0 ; x += 0.005) { Gldouble func = exp(-x) * cos(2 * 3.14159265 * x); //sx= A * x + B, sy =C * y + D glVertex2d(A * x + B, C * func + D); } glEnd(); glFlush(); // send all output to display }
OpenGL功能简介
状态变量通过函数 glEnable() 和 glDisable() 进行激活或取消的设置
OpenGL状态机制(2/2)
每一个状态变量都有系统默认的缺省值 状态变量的当前值可以通过一系列函数查询
顶点数据 Vertex data
OpenGL渲染流水线(7/20)
求值器
参数化的曲面曲线(如贝塞尔,NURBS曲面曲线) 并不直接给出顶点,而是给出一系列控制点及其生成 曲面曲线的函数 求值器的功能就是,通过控制点和生成函数,得到实 际使用的顶点数据 对于非参数化曲面曲线,这一步是被忽略的
顶点数据 Vertex data 求值器 Evaluators
对每个顶点的操作和图元装配
对象坐标 Object 人眼坐标 Eye 裁剪 Clip 归一化 Normalize 窗口坐标 Window
顶点 Vertex
模型视图矩阵 Modelview matrix
投影矩阵 Project matrix
透视除法 Perspective division
视区变换 Viewport transform
OpenGL基本功能(5/11)
矩阵变换
无论多复杂的图形都是由基本图元组成并经 过一系列变换来实现的 OpenGL提供四种基本变换:平移、旋转、按 比例缩放、镜像 OpenGL提供两种投影变换:平行投影(正射 投影)、透视投影
OpenGL基本功能(6/11)
颜色管理
OpenGL提供了两种颜色模式:RGBA模式,颜色索 引模式(Color index) RGBA模式为每个像素点指定颜色,可提供丰富多彩 的色彩效果,其中A是混合因子,用于各种特效处理 对于显示能力不足的硬件,可采用颜色索引模式,系 统提供一个颜色表,通常有256或4096种颜色,各像 素点通过索引颜色表项得到颜色值
delphiopengl三维坐标鼠标拾取[资料]
delphi opengl 三维坐标鼠标拾取unit MainUnit;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs,gl,glu, ExtCtrls, StdCtrls,Math, ComCtrls;typeTMainForm = class(TForm)StatusBar1: TStatusBar;procedure FormCreate(Sender: TObject);procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);procedure Panel1Resize(Sender: TObject);procedure FormResize(Sender: TObject);procedure FormMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,procedure FormMouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);//procedure glDrawString(x,y,z:Extended;const ss: string);private{ Private declarations }public{ Public declarations }end;constBUFSIZE = 32; // Size of selection buffer.typegl1f = glfloat;gl3f = array [0..2] of glfloat;gl4f = array [0..3] of glfloat;varMainForm: TMainForm;WinW:integer;WinH:integer;keys : Array[0..255] of Boolean; // Holds keystrokesviewP :TviewPortArray;modeM,projM :T16DArray;//viewP:Array [0..3] of GLint;//modeM,projM:Array [0..15] of GLdouble;// User vaiablesLdown,Rdown :boolean;zPos :Tpoint;x0, y0 :Integer; // mouse movementrx, ry :single;// Object positionobj :array[1..236410] of gl3f; //对象的空间坐标Pos :array[1..236410] of gl3f; //对象的屏幕坐标{***********************}p,pi:single;m_Pattern:Integer;mat:array[0..3] of GLDouble;m_bhide,m_bColor:boolean;dnum:integer;bs,zl:double;implementation{$R *.dfm}procedure glDrawCamber;varx1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,x0,y0,z0,QL,m,n:Extende d;i,j,z,k,tt:integer;Arr1:Array [1..720,1..3] of Extended;Arr2:Array [1..720,1..3] of Extended;beginglColor3f(1.0,1.0,0.0);// glbegin(GL_LINE_LOOP);//初始化for i:=1 to 720 dobeginfor j:=1 to 3 dobeginArr1[i,j]:=100;Arr2[i,j]:=100;end;end;for i:=0 to 80 dobeginfor j:=1 to 720 dobegin//tt:=tt+1;z:=((j) mod 16)+1;ql:=p;case z of1:beginql:=p*0.95;//glColor3f(1.0,0.0,0.0); end;2:beginql:=p*0.96;// glColor3f(0.0,1.0,0.0); end;3:beginql:=p*0.97;//glColor3f(0.0,0.0,1.0);end;4:beginql:=p*0.99;//glColor3f(1.0,1.0,0.0);end;5:beginql:=p*1.00;//glColor3f(1.0,0.0,1.0);end;6:ql:=p*1.02;7:ql:=p*1.03;8:ql:=p*1.04;9:ql:=p*1.05;10:ql:=p*1.04;11:ql:=p*1.03;12:ql:=p*1.02;13:ql:=p*1.00;14:ql:=p*0.99;15:ql:=p*0.98;16:ql:=p*0.97;end;k:=i-40;m:=k/2;n:=j/2;x0:=ql*cos(m*pi/180)*cos(n*pi/180); z0:=ql*sin(m*pi/180);y0:=ql*cos(m*pi/180)*sin(n*pi/180);Arr1[j,1]:=x0;Arr1[j,2]:=y0;Arr1[j,3]:=z0;if (i>0) and (j>1) thenbeginx1:=Arr2[j-1,1];y1:=Arr2[j-1,2];z1:=Arr2[j-1,3];x2:=Arr1[j-1,1];y2:=Arr1[j-1,2];z2:=Arr1[j-1,3];x3:=Arr2[j,1];y3:=Arr2[j,2];z3:=Arr2[j,3];x4:=Arr1[j,1];y4:=Arr1[j,2];z4:=Arr1[j,3];//GlBegin(GL_POINTS);//GlBegin(GL_lines);//glColor3f(1.0,1.0,0.0); //GlBegin(GL_POLYGON);GlBegin(GL_LINE_LOOP);glVertex3f(x1,y1,z1);glVertex3f(x3,Y3,z3);glVertex3f(x4,y4,z4);glVertex3f(x2,y2,z2);glend();end;if j=720 thenbeginfor tt:=1 to 720 dobeginArr2[tt,1]:=Arr1[tt,1];Arr2[tt,2]:=Arr1[tt,2];Arr2[tt,3]:=Arr1[tt,3];end;end;end;end;//glend();end;procedure glDrawColor( Mode :integer);varx1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4:GL1f;i,j,k,pnum:integer;beginpnum:=3;for i:=0 to 40 dobeginfor j:=1 to 360 dobeginpnum:=pnum+1;if mode = GL_SELECT then glLoadName(pnum);k:=i-20;x1:=P*cos(k*pi/180)*cos(j*pi/180);z1:=p*sin(k*pi/180);y1:=p*cos(k*pi/180)*sin(j*pi/180);x2:=P*cos((k+1)*pi/180)*cos(j*pi/180);z2:=p*sin((k+1)*pi/180);y2:=p*cos((k+1)*pi/180)*sin(j*pi/180);x3:=P*cos(k*pi/180)*cos((j+1)*pi/180);z3:=p*sin(k*pi/180);y3:=p*cos(k*pi/180)*sin((j+1)*pi/180);x4:=P*cos((k+1)*pi/180)*cos((j+1)*pi/180);z4:=p*sin((k+1)*pi/180);y4:=p*cos((k+1)*pi/180)*sin((j+1)*pi/180);if (k<=5) and (k>=-5) thenbeginif (j>=1) and (j<=90) thenglColor3f(1.0,0.0,0.0)else if (j>90) and (j<=180) thenglColor3f(0.0,1.0,1.0)else if (j>180) and (j<=270) thenglColor3f(1.0,1.0,1.0)elseglColor3f(1.0,1.0,0.0);endelse if ((k<=10) and (K>=5)) or ((k>=-10) and (k<=-5)) thenglColor3f(0.0,1.0,0.0)else if ((k<=15) and (K>=10)) or ((k>=-15) and (k<=-10)) thenglColor3f(0.0,0.0,1.0)elseglColor3f(0.0,1.0,1.0);glbegin(GL_POLYGON );if hit=pnum thenglColor3f(1, 0, 0);// obj[pnum]:=Vert(x1,y1,z1);//obj[pnum+1]:=Vert(x2,y2,z2);//obj[pnum+2]:=Vert(x3,y3,z3);//obj[pnum+3]:=Vert(x4,y4,z4);//glVertex3fv(@obj[pnum]);//glVertex3fv(@obj[pnum+2]);//glVertex3fv(@obj[pnum+3]);//glVertex3fv(@obj[pnum+1]);glVertex3f(x1,y1,z1);glVertex3f(x3,Y3,z3);glVertex3f(x4,y4,z4);glVertex3f(x2,y2,z2);glend();//end;end;end;end;procedure glDrawString(x,y,z:Extended;const ss: string);const MAX_char:integer=128;{$J+}const isFirstCall:integer = 1;const lists:GLuint=0;{$J-}vari,j:integer;beginglRasterPos3f(x,y,z);if isFirstCall=1 thenbegin// 如果是第一次调用,执行初始化// 为每一个ASCII字符产生一个显示列表isFirstCall:=0;// 申请MAX_CHAR个连续的显示列表编号lists:=glGenLists(MAX_CHAR);// 把每个字符的绘制命令都装到对应的显示列表中wglUseFontBitmaps(wglGetCurrentDC(),0,MAX_CHAR,lists);end;// 调用每个字符对应的显示列表,绘制每个字符for i:=1 to length(ss) dobeginj:=Ord(ss[i]);glCallList(Lists+j);end;end;{------------------------------------------------------------------}{ Function to convert int tostring. }{------------------------------------------------------------------}function IntToStr(Num : Integer) : String;beginStr(Num, result);end;function Vert( x,y,z :gl1f) :gl3f;beginresult[0]:=x; result[1]:=y; result[2]:=z;end;function Point(X, Y: Integer): TPoint;beginResult.X:= X; Result.Y:= Y;end;procedure setAxisList;beginglNewList(1,GL_COMPILE); //坐标线glColor3f(1,0.5,0.5); glLineWidth (1);//绘图直线时笔的宽度glBegin(GL_LINE_STRIP);glColor3f(1,0,1); glVertex3f( 0,0,0);glVertex3f( 2.5,0,0);glColor3f(0,1,0); glVertex3f( 0,0,0);glVertex3f( 0,2.5,0);glColor3f(0,0,1); glVertex3f( 0,0,0);glVertex3f( 0,0,2.5);glEnd;glEndList;end;procedure setupPixelFormat(DC:HDC);constpfd:TPIXELFORMATDESCRIPTOR =(nSize:sizeof(TPIXELFORMATDESCRIPTOR); // sizenVersion:1; // versiondwFlags:PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER; // support double-bufferingiPixelType:PFD_TYPE_RGBA; // color typecColorBits:24; // preferred color depthcRedBits:0; cRedShift:0; // color bits (ignored)cGreenBits:0; cGreenShift:0;cBlueBits:0; cBlueShift:0;cAlphaBits:0; cAlphaShift:0; // no alpha buffercAccumBits: 0;cAccumRedBits: 0; // no accumulation buffer,cAccumGreenBits: 0; // accum bits (ignored)cAccumBlueBits: 0;cAccumAlphaBits: 0;cDepthBits:16; // depth buffercStencilBits:0; // no stencil buffercAuxBuffers:0; // no auxiliary buffersiLayerType:PFD_MAIN_PLANE; // main layerbReserved: 0;dwLayerMask: 0;dwVisibleMask: 0;dwDamageMask: 0; // no layer, visible, damage masks);var pixelFormat:integer;beginpixelFormat := ChoosePixelFormat(DC, @pfd);if (pixelFormat = 0) thenexit;if (SetPixelFormat(DC, pixelFormat, @pfd) <> TRUE) thenexit;end;{------------------------------------------------------------------}{ InitialiseOpenGL }{------------------------------------------------------------------}procedure GLInit;begin// set viewing projectionglMatrixMode(GL_PROJECTION);glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);// position viewer */glMatrixMode(GL_MODELVIEW);glEnable(GL_DEPTH_TEST);glClearColor(0.0, 0.0, 0.0, 0.0); // Black Background// glShadeModel(GL_SMOOTH); // Enables Smooth Color ShadingglClearDepth(1.0); // Depth Buffer SetupglDepthFunc(GL_LESS); // The Type Of Depth Test To DoglEnable(GL_DEPTH_TEST); // Enable Depth BufferglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);//Realy Nice perspective calculationsglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //控制混合方式glEnable(GL_BLEND); //混合(透明)使能glEnable(GL_line_smooth);glEnable(GL_POINT_SMOOTH);end;procedure gldrawball;beginend;//############ 获得对象的屏幕坐标 ################function GetWinPos( h:integer) :gl3f;var wx,wy,wz :glDouble; // 屏幕坐标begingluProject( obj[h,0],obj[h,1],obj[h,2], modeM,projM,viewP, @wx,@wy,@wz);result:= Vert( wx,wy,wz);end;//############ 将屏幕坐标转换为空间坐标 ################function GetObjPos( x,y,z:gl1f) :gl3f;var px,py,pz :glDouble; // 对象坐标a,b:Double;begingluUnProject( x,y,z, modeM,projM,viewP, @px,@py,@pz);result:= Vert( px,py,pz);MainForm.StatusBar1.Panels[0].Text:='X='+FloattoStr(px); MainForm.StatusBar1.Panels[1].Text:='Y='+FloattoStr(py); MainForm.StatusBar1.Panels[2].Text:='Z='+FloattoStr(pz);if Hit>3 thenbegina:=ArcSin(pz/p)*180/pi; //纬度与xy平面的反正弦b:=ArcCos(Sqrt(px*px+pz*pz)/p)*180/pi; //经度与xz平面的反余弦if (px<0) and (py>=0) thenb:=180-b;if (px<0) and (py<0) thenb:=b-180;MainForm.StatusBar1.Panels[3].Text:='LON='+FloattoStr(a); MainForm.StatusBar1.Panels[4].Text:='LAT='+FloattoStr(b);end;end;--------}{ Handle windowresize }{------------------------------------------------------------------}procedure glResizeWnd(Width, Height : Integer);beginwinW:= width; winH:= Height;if (Height = 0) then Height := 1; // prevent divide by zero exceptionglViewport(0, 0, Width, Height); // Set the viewport for the OpenGL windowglMatrixMode(GL_PROJECTION); // Change Matrix Mode to ProjectionglLoadIdentity(); // Reset ViewgluPerspective(45, Width/Height, 1, 100); // Do the perspective calculations. Last value = max clipping depthglMatrixMode(GL_MODELVIEW); // Return to the modelview matrixglLoadIdentity(); // Reset Viewend;{------------------------------------------------------------------}{ Function to draw the actualscene }--------}procedure glDraw( Mode :integer);var h :integer;i,j,latw,lonw:integer;x,y,z,x0,y0,z0,m,n:Extended;x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,lx,ly,lz:GL1f;k,pnum:integer;pp:Array of Array of GL3f;beginglClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth BufferglLoadIdentity(); // Reset The ViewglTranslatef(0,0,-eye);glRotatef( ry, 1,0,0);glRotatef( rx, 0,0,1);glColor3f(0, 0.1, 0.6);glCallList(1);{*******************************}glmatrixmode(gl_modelview);glclipplane(gl_clip_plane1,@mat[0]);if m_bhide thenglenable(gl_clip_plane1)elsegldisable(gl_clip_plane1);//glLineWidth(1);{===================================}glPointSize(6);glLineWidth(2);{ if mode = GL_SELECT then glLoadName(1);glBegin(GL_POINTS);glColor3f(1, 1, 0);if hit=1 then glColor3f(1, 0, 0) else glColor3f(1, 1, 0); glVertex3fv(@obj[1]); //画第一点glEnd;if mode = GL_SELECT then glLoadName(2);glBegin(GL_POINTS);glColor3f(1, 1, 0);if hit=2 then glColor3f(1, 0, 0) else glColor3f(1, 1, 0); glVertex3fv( @obj[2]); //画第二点glEnd;if mode = GL_SELECT then glLoadName(3);glBegin( GL_LINES);if hit=3 then glColor3f(1, 0, 0) else glColor3f(1, 0.5, 0.5);glVertex3fv( @obj[1]); glVertex3fv( @obj[2]); //连接线glEnd;}//if mode = GL_SELECT then glLoadName(4);{**********************************}{红色: (1.0,0.0,0.0)(1.0,0.125,0.0)红橙色: (1.0,0.25,0.0);(1.0,0.45,0.0)橙色: (1.0,0.65,0.0)(1.0,0.7,0.0)黄橙色: (1.0,0.8,0.0)(1.0,0.9,0.0)黄色: (1.0,1.0,0.0)(0.75,1.0,0.0)黄绿色: (0.5,1.0,0.0)(0.25,1.0,0.0)绿色: (0.0,1.0,0.0)(0.0,0.75,0.25)蓝绿色: (0.0,0.5,0.5)(0.0,0.25,0.75)蓝色 (0.0,0.0,1.0)(0.25,0.0,1.0)蓝紫色: (0.5,0.0,1.0)(0.5,0.0,0.75)紫色: (0.5,0.0,0.5)(0.75,0.0,0.75)红紫色: (1.0,0.0,1.0)(1.0,0.0,0.5)}pnum:=0;glPointSize(1);setlength(pp,1440,161);for i:=0 to 1439 dobeginfor j:=0 to 159 dobegin//pnum:=pnum+1;//if mode=GL_Select then GLLoadName(pnum);n:=i*0.25;m:=j*0.25-20;pp[i,j,0]:=P*cos(m*pi/180)*cos(n*pi/180);pp[i,j,2]:=p*sin(m*pi/180);pp[i,j,1]:=p*cos(m*pi/180)*sin(n*pi/180);endend;for i:=0 to 1438 dobeginfor j:=0 to 159 dobegin//颜色选取pnum:=pnum+1;if mode=GL_Select then GLLoadName(pnum);//k:=(pnum div 23000)+1;case pnum of1..9600: glColor3f(1.0,0.0,0.0); //红色9601..19200:glColor3f(1.0,0.125,0.0);19201..28800: glColor3f(1.0,0.25,0.0);28801..38400: glColor3f(1.0,0.45,0.0);38401..48000:glColor3f(1.0,0.65,0.0);48001..57600: glColor3f(1.0,0.7,0.0);57601..67200: glColor3f(1.0,0.8,0.0);67201..76800: glColor3f(1.0,0.9,0.0);76801..86400: glColor3f(1.0,1.0,0.0);86401..96000: glColor3f(0.75,1.0,0.0);96001..105600: glColor3f(0.5,1.0,0.0);105601..115200: glColor3f(0.25,1.0,0.0);115201..124800:glColor3f(0.0,1.0,0.0);124801..134400:glColor3f(0.0,0.75,0.25);134401..144000: glColor3f(0.0,0.5,0.5); 144001..153600:glColor3f(0.0,0.25,0.75);153601..163200: glColor3f(0.0,0.0,1.0); 163201..172800: glColor3f(0.25,0.0,1.0);172801..182400: glColor3f(0.5,0.0,1.0); 182401..192000: glColor3f(0.5,0.0,0.75);192001..201600: glColor3f(0.5,0.0,0.5); 201601..211200: glColor3f(0.75,0.0,0.75);211201..220800: glColor3f(1.0,0.0,1.0); 220801..239000: glColor3f(1.0,0.0,0.5); end;if j<>159 thenbeginGLbegin(GL_POLYGON);if hit=pnum thenbeginGLColor3f(1.0,1.0,1.0);MainForm.StatusBar1.Panels[5].Text:='光强='+InttoStr(hit);end;obj[pnum]:=Vert(pp[i,j,0],pp[i,j,1],pp[i,j,2]); obj[pnum+1]:=Vert(pp[i+1,j,0],pp[i+1,j,1],pp[i+1,j,2]);obj[pnum+2]:=Vert(pp[i+1,j+1,0],pp[i+1,j+1,1],pp[i+1,j+1,2] );obj[pnum+3]:=Vert(pp[i,j+1,0],pp[i,j+1,1],pp[i,j+1,2]);glVertex3fv(@obj[pnum]);glVertex3fv(@obj[pnum+1]);glVertex3fv(@obj[pnum+2]);glVertex3fv(@obj[pnum+3]);GLend();end;end;end;{pnum:=0;for i:=0 to 40 dobeginfor j:=1 to 360 dopnum:=pnum+1;if mode = GL_SELECT then glLoadName(pnum);k:=i-20;x1:=P*cos(k*pi/180)*cos(j*pi/180);z1:=p*sin(k*pi/180);y1:=p*cos(k*pi/180)*sin(j*pi/180);x2:=P*cos((k+1)*pi/180)*cos(j*pi/180);z2:=p*sin((k+1)*pi/180);y2:=p*cos((k+1)*pi/180)*sin(j*pi/180);x3:=P*cos(k*pi/180)*cos((j+1)*pi/180);z3:=p*sin(k*pi/180);y3:=p*cos(k*pi/180)*sin((j+1)*pi/180);x4:=P*cos((k+1)*pi/180)*cos((j+1)*pi/180);z4:=p*sin((k+1)*pi/180);y4:=p*cos((k+1)*pi/180)*sin((j+1)*pi/180);if (k<=5) and (k>=-5) thenbeginif (j>=1) and (j<=90) thenglColor3f(1.0,0.0,0.0)else if (j>90) and (j<=180) thenglColor3f(0.0,1.0,1.0)else if (j>180) and (j<=270) thenglColor3f(1.0,1.0,1.0)elseglColor3f(1.0,1.0,0.0);else if ((k<=10) and (K>=5)) or ((k>=-10) and (k<=-5)) thenglColor3f(0.0,1.0,0.0)else if ((k<=15) and (K>=10)) or ((k>=-15) and (k<=-10)) thenglColor3f(0.0,0.0,1.0)elseglColor3f(0.0,1.0,1.0);glbegin(GL_POLYGON );if hit=pnum thenbeginglColor3f(1, 0, 0);MainForm.Edit6.Text:=InttoStr(hit);end;obj[pnum]:=Vert(x1,y1,z1);obj[pnum+1]:=Vert(x2,y2,z2);obj[pnum+2]:=Vert(x3,y3,z3);obj[pnum+3]:=Vert(x4,y4,z4);glVertex3fv(@obj[pnum]);glVertex3fv(@obj[pnum+2]);glVertex3fv(@obj[pnum+3]);glVertex3fv(@obj[pnum+1]);glend();//end;end;end;}//显示0、x,y,zglDrawString(0,0,0,'0');glDrawString(2.5,0,0,'X');glDrawString(0,2.5,0,'Y');glDrawString(0,0,2.5,'Z');//颜色绘图// if MainForm.CheckBox3.Checked then// glDrawCamber; //画曲面{=================================}if mode = GL_SELECT then glLoadName(0);glCallList(1); //画坐标轴线{ if Ldown and(hit>0) then //画坐标指示线beginglColor3f( 0.5,0.5,0.5);glEnable( GL_LINE_STIPPLE);glLineStipple(1,$4444);if hit<3 then h:=hit else h:=1;glBegin( GL_LINE_STRIP);glVertex3fv( @obj[h]);glVertex3f( obj[h,0],obj[h,1],0);glVertex3f( obj[h,0],0,0); glVertex3f( 0,0,0);glVertex3f( 0,obj[h,1],0);glVertex3f( obj[h,0],obj[h,1],0);glEnd;glDisable( GL_LINE_STIPPLE);end;}SwapBuffers(wglGetCurrentDC);end;{------------------------------------------------------------------}{ Processes all mouseClicks }{------------------------------------------------------------------}{function doSelect(X, Y : Integer) :integer;var selectBuff : Array[1..8] of glUint;begin// result:= -1;glGetIntegerv(GL_VIEWPORT, @viewP); // Viewport = [0, 0, width, height]glSelectBuffer(8, @selectBuff);// glSelectBuffer(BUFSIZE, @selectBuff);glRenderMode(GL_SELECT);glInitNames;glPushName(0);glMatrixMode(GL_PROJECTION);glPushMatrix(); //--glLoadIdentity();gluPickMatrix(x, winH-y, 0.1, 0.1, viewP); // Set-up pick matrixgluPerspective(45, winW/winH, 1, 100); // Do the perspective calculations. Last value = max clipping depthglMatrixMode(GL_MODELVIEW);glDraw( GL_SELECT);glMatrixMode(GL_PROJECTION);glPopMatrix();glMatrixMode(GL_MODELVIEW);if (glRenderMode(GL_RENDER)>0 )then result:= selectBuff[4] else result :=-1;end; }function doSelect(X, Y : Integer) :integer;var selectBuff : Array[0..31] of glUint;beginglGetIntegerv(GL_VIEWPORT, @viewP); // Viewport = [0, 0, width, height]glSelectBuffer(BUFSIZE, @selectBuff);glRenderMode(GL_SELECT);glInitNames;glPushName(32);glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();gluPickMatrix(x, winH-y-20, 4, 4, viewP); // Set-up pick matrixgluPerspective(45, winW/winH, 1, 100); // Do the perspective calculations. Last value = max clipping depthglMatrixMode(GL_MODELVIEW);glDraw(GL_SELECT);glMatrixMode(GL_PROJECTION);glPopMatrix();glMatrixMode(GL_MODELVIEW);if glRenderMode(GL_RENDER)>0then result:= selectBuff[3]else result:= -1;end;//============ 按下鼠标 =============procedure MouseDw( hit, x,y : Integer);var i :integer;beginLdown:= TRUE;if hit<=0 then exit;zPos:= point(x,y); //很奇怪,这个变量无任何用处,但在这里却不能删除,否则就会黑屏!glGetDoublev( GL_Modelview_Matrix, @modeM);glGetDoublev(GL_Projection_Matrix, @projM);for i:= 1 to 236160 do Pos[i]:= GetWinPos(i);//构件的屏幕坐标glDraw(GL_RENDER);end;//============= 移动鼠标 ==============procedure MouseMv( hit, x,y, x0,y0 : Integer);var dx,dy, i :integer;begindx:= x-x0; dy:= y-y0;if hit<0 then begin rx:= rx+ (x-x0)/5; ry:= ry+ (y-y0)/5; end; //改变视角if hit<3 thenobj[hit]:= GetObjPos( x, winH-y, GetWinPos( hit)[2]); //直接将构件移动到新的位置if hit=3 thenfor i:= 1 to 2 dobeginobj[i]:=GetObjPos( Pos[i][0]+dx,(Pos[i][1]-dy),Pos[i][2]);//将构件移动到新的位置Pos[i]:= GetWinPos(i);//构件的屏幕坐标end;if hit>3 thenbeginobj[hit]:=GetObjPos( Pos[hit][0],(Pos[hit][1]),Pos[hit][2]);//将构件移动到新的位置Pos[hit]:= GetWinPos(hit);//构件的屏幕坐标end;glDraw(GL_RENDER);end;procedure TMainForm.FormCreate(Sender: TObject);var DC:HDC;RC:HGLRC;beginDC:=GetDC(Handle); //Actually, you can use any windowed control hereSetupPixelFormat(DC);RC:=wglCreateContext(DC); //makes OpenGL window out of DC wglMakeCurrent(DC, RC); //makes OpenGL window activeGLInit; //initialize OpenGLglResizeWnd(800,600);glDraw(GL_RENDER);p:=2.0;mat[0]:=0;mat[1]:=0;mat[2]:=1;mat[3]:=0;m_bHide:=False;m_bColor:=False;m_Pattern:=2;dnum:=24;pi:=3.1415926;setAxisList;rx:= -125; ry:= -65; //视角eye:= 10; //景深obj[1]:=Vert(-1, 2, 0.8);obj[2]:=Vert( 2,-1,-0.5);bs:=8*pi*p*p*sin(pi/9);bs:=bs/(1440*160);zl:=Sqrt(bs);end;procedure TMainForm.Panel1MouseDown(Sender: TObject; Button:TMouseButton;Shift: TShiftState; X, Y: Integer);beginif Button=mbLeft thenbeginx0:=x;y0:=y;MouseDw( hit, x0,y0 );MouseMv( hit, x,y, x0,y0);end;if Button=mbRight thenbeginx0:= x;y0:= y;Rdown:= true;end;// glDraw(GL_RENDER);glDraw(GL_RENDER); // Draw the sceneend;procedure TMainForm.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);beginif not(Ldown or Rdown) thenbeginhit:= doSelect(x, y); //自由移动// MouseMv( hit, x,y, x0,y0);end;if Ldown then MouseMv( hit, x,y, x0,y0); //拖动左键if Rdown then begin //拖动右键eye:= eye- (x-x0); //改变景深if eye>80 theneye:=80;if eye<5 theneye:=5;end;x0:= x; y0:= y;glDraw(GL_RENDER); // Draw the sceneend;procedure TMainForm.Panel1MouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);beginif Button=mbLeft thenbeginLdown :=FALSE;end;if Button=mbRight thenbeginRdown :=FALSE;end;// glDraw(GL_RENDER);glDraw(GL_RENDER); // Draw the sceneend;procedure TMainForm.Panel1Resize(Sender: TObject);beginglResizeWnd(MainForm.Width,MainForm.Height);end;procedure TMainForm.FormResize(Sender: TObject);beginglResizeWnd(MainForm.Width,MainForm.Height);end;procedure TMainForm.FormMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);beginif Button=mbLeft thenbeginx0:=x;y0:=y;MouseDw( hit, x0,y0 );MouseMv( hit, x,y, x0,y0);end;if Button=mbRight thenbeginx0:= x;y0:= y;Rdown:= true;end;// glDraw(GL_RENDER);glDraw(GL_RENDER); // Draw the sceneend;procedure TMainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);beginif not(Ldown or Rdown) thenbeginhit:= doSelect(x, y); //自由移动// MouseMv( hit, x,y, x0,y0);end;if Ldown then MouseMv( hit, x,y, x0,y0); //拖动左键if Rdown then begin //拖动右键eye:= eye- (x-x0); //改变景深if eye>80 theneye:=80;if eye<5 theneye:=5;end;x0:= x; y0:= y;glDraw(GL_RENDER); // Draw the sceneend;procedure TMainForm.FormMouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);beginif Button=mbLeft thenbeginLdown :=FALSE;end;if Button=mbRight thenbeginRdown :=FALSE;end;// glDraw(GL_RENDER);glDraw(GL_RENDER); // Draw the sceneend;end.。
计算机图形学实验代码及截图
目录实验一:OpenGL基础知识 0实验二 OpenGL中的建模与变换 (1)实验三 OpenGL中的光照 (4)实验四 OpenGL中的拾取 (7)实验五 OpenGL中的纹理映射 (10)实验一:OpenGL基础知识一、实验目的1、建立Windows系统下的OpenGL实验框架。
2、学习理解OpenGL工作流程。
二、实验环境⒈硬件:每个学生需配备计算机一台。
⒉软件:Visual C++;三、实验内容1、建立非控制台的Windows程序框架。
2、建立OpenGL框架。
3、建立OpenGL框架的类文件。
4、完善Windows框架。
5、理解程序间的相互关系。
四、实验要求1、学习教材第2章的内容。
2、理解教材中相关实例的代码,按要求添加到适当的地方,调试并通过运行。
3、运行结果应该与教材中的相关实例相符。
4、编译第2章的框架代码,修改背景色、窗口标题。
五、程序设计提示(略)六、报告要求1.认真书写实验报告,字迹清晰,格式规范。
报告中应写清姓名、学号、实验日期、实验题目、实验目的、实验原理。
2.报告中应书写主要源程序,且源程序中要有注释。
3.报告中应包含运行结果及结果分析。
如调试通过并得到预期的效果,请注明‘通过’并粘贴运行效果图;如未调试通过或结果不正确,试分析原因。
4.报告最后包含实验总结和体会。
实验二 OpenGL中的建模与变换一、实验目的1.学习配置OpenGL环境。
2.掌握在OpenGL中指定几何模型的方法。
3. 掌握OpenGL中的透视投影和正投影的设置方法,学会诊断投影问题导致的显示异常。
二、实验环境⒈ 硬件:每个学生需配备计算机一台。
⒉ 软件:Visual C++;三、实验内容1.建立OpenGL编程环境(注:Windows自带gl和glu,还需要安装glut库文件。
)(a)查看Windows自带的OpenGL文件。
在文件夹c:\windows\system32下查看是否存在文件opengl32.dll和glu32.dll;在Visual Studio的安装目录Vc7\PlatformSDK\Include\gl下查看是否存在gl.h和glu.h;在Vc7\PlatformSDK\Lib 下是否存在opengl32.lib和glu32.lib。
OpenGL图形编程9交互(陈永强)
键盘注册函数
glutKeyboardFunc(Key);
键盘相应函数
void Key(unsigned char key,int x,int y);
7
9.1OpenGL实现橡皮筋技术
2.键盘实现 教材【程序3-2】
9.2 OpenGL实现拾取操作
设置拾取缓冲区
void glSelectBuffer(GLsizei n, GLunint *buff);
பைடு நூலகம்
进入选择模式
GLint glRenderMode(GLenum mode);
9
9.2OpenGL实现拾取操作
名字堆栈操作
初始化名字堆栈(glInitNames)
将一个名字压入堆栈(glPushName)
替换名字堆栈的栈顶元素(glLoadName)
将栈顶元素弹出(glPopName)
参数action:GLUT_DOWN或GLUT_UP。
坐标(xMouse,yMouse)制定当前鼠标相对于窗口左上角点的位置坐标。
4
9.1OpenGL实现橡皮筋技术
1.鼠标实现
鼠标移动注册函数
glutMotionFunc(MouseMove);
glutPassiveMotionFunc(PassiveMouseMove);
10
9.2OpenGL实现拾取操作
设置合适的变换过程
gluPickMatrix(xPick, yPick, widthPick, heightPick,
*vp);
为每个图元分配名字并绘制 切换回渲染模式 分析选择缓冲区中的数据
11
9.2OpenGL实现拾取操作
第三章常见的鼠标键盘交互方法
TrackBall模式Trackball模式是跟踪球模式,具体来说,就是物体的中心位置不变,而改变视点的位置,从而使模型随着鼠标的移动绕着中心位置旋转。
对于鼠标移动需要计算相应的视点(照相机)的运动情况,在osg中,通过TrackballManipulator::calcMovement()来实现,并且对于不同的鼠标事件,分别进行如下的操作:1.按下鼠标的左键,则旋转照相机。
2.按下鼠标中间键或者同时按下鼠标的左键和与右键,则改变物体的中心位置,也即对物体进行平移操作。
3.按下鼠标的右键,则对模型进行缩放。
在按下鼠标的左键从而旋转照相机时,这里主要模拟了一个跟踪球技术,球的半径理想情况下应该基于旋转中心到鼠标所指的物体上某点的距离,但是为了简化处理,一般情况下,球的半径TRACKBALLSIZE可以预先给定,也能达到比较好的模拟效果。
具体实现过程如下:首先分别记录两次鼠标事件的坐标的(x1,y1)和(x2,y2),根据x坐标的最小值X min和最大值X max,以及y坐标的最小值Y min和最大值Y max,对(x1,y1)和(x2,y2)坐标进行规范化,转化到(-1,1)之间,不妨假设新的坐标点为p1和p2,然后通过将p1和p2投影到跟踪球上,从而获取相应的z 坐标。
这样,以球的中心为起始点,计算出的球上的两个点为终点,可以确定两个向量,不妨记作P1和P2,那么旋转轴axis = P2^ P1,旋转的弧度为:t = ||(P2- P1)|| / (2.0*TRACKBALLSIZE),为了避免产生某些不可操纵的结果,必须先将t规范到(-1,1)之间,再将其转化为角度angles,然后将照相机绕着axis旋转angles的角度,从而实现了对照相机的旋转操作。
在osg的实现中,该跟踪球并不是一个正规的球体,而是进行了一定的变形,在中心附近是一个半径为TRACKBALLSIZE的球体,而在离中心达到一定距离时(小于球的半径TRACKBALLSIZE),该球体被扭曲成了四个双曲面。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
func:处理鼠标click事件的函数的函数名。
从上面可以看到,处理鼠标单击事件的函数,一定有4个参数。第一个参数表明哪个鼠标键被按下或松开,这个变量可以是下面的三个值中的一个:
GLUT_LEFT_BUTTON
GLUT_MIDDLE_BUTTON
GLUT_RIGHT_BUTTON
第二个参数表明,函数被调用发生时,鼠标的状态,也就是是被按下,或松开,可能取值如下:
GLUT_DOWN
GLUT_UP
当函数被调用时,state的值是GLUT_DOWN,那么程序可能会假定将会有个GLUT_UP事件,甚至鼠标移动到窗口外面,也如此。然而,如果程序调用glutMouseFunc传递NULL作为参数,那么GLUT将不会改变鼠标的状态。
剩下的两个参数(x,y)提供了鼠标当前的窗口坐标(以左上角为原点)。
和以前一样,你必须注册将处理鼠标事件的函数(定义函数)。GLUT让我们可以指定两个不同的函数,一个追踪passive motion,另一个追踪active motion。
它们的函数原型如下:
void glutMotionFunc(void(*func)(int x,int y));
void glutPassiveMotionFunc(void (*func)(int x,int y));
首先,定义几个全局变量:
bool mouseLeftDown;
bool mouseRightDown;
float mouseX, mouseY;
float cameraDistance;
float cameraAngleX;
float cameraAngleY;
其中,mouseLeftDown和mouseRightDown变量标志鼠标左右键按下与否,mouseX和mouseY变量标志鼠标滑动时,前一刻的鼠标所在位置,cameraDistance这个变量根据鼠标右键按下并上下滑动来控制场景中物体移入屏幕的远近。cameraAngleX和cameraAngleY变量根据鼠标左键按下并滑动来控制场景中物体的旋转。
mouseLeftDown = false;
}
else if(button == GLUT_RIGHT_BUTTON)
{
if(state == GLUT_DOWN)
{
mouseRightDown = true;
}
else if(state == GLUT_UP)
mouseRightDown = false;
检测鼠标单击
要想在OpenGL中处理鼠标事件非常的方便,GLUT已经为我们的注册好了函数,只要我们提供一个方法。使用函数glutMouseFunc,就可以帮我们注册我们的函数,这样当发生鼠标事件时就会自动调用我们的方法。
函数的原型是:
void glutMouseFunc(void(*func)(int button,int state,int x,int y));
}
}
void mouseMotionCB(int x, int y)
{
if(mouseLeftDown)
{
cameraAngleY += (x - mouseX);
cameraAngleX += (y - mouseY);
mouseX = x;
mouseY = y;
}
if(mouseRightDown)
{
cameraDistance += (y - mouseY) * 0.2f;
mouseY = y;
}
glutPostRedisplay();
}
在主函数中,调用相应的函数注B);
glutMotionFunc(mouseMotionCB);
在场景中物体绘制之前,这样就可以:
检测动作
GLUT提供鼠标动作检测能力。有两种GLUT处理的motion:active motion和passive motion。Active motion是指鼠标移动并且有一个鼠标键被按下。Passive motion是指当鼠标移动时,并有没鼠标键按下。如果一个程序正在追踪鼠标,那么鼠标移动期间,每一帧将产生一个结果。
void glutEntryFunc(void(*func)(int state));
参数:
Func:处理这些事件的函数名。
上面函数的参数中,state有两个值表明是离开还是进入窗口:
GLUT_LEFT
GLUT_ENTERED
应用
现在想实现的功能就是使用鼠标拖动,来转动场景中的物体,当鼠标左键按下,并且上下左右滑动时,场景中的物体相应的会随之上下左右旋转,当鼠标右键按下,并且上下滑动时,场景中的物体相应的会随之移入或是移出屏幕。
glTranslatef(0, 0, cameraDistance);
glRotatef(cameraAngleX, 1, 0, 0);
glRotatef(cameraAngleY, 0, 1, 0);
参考:
鼠标事件处理
void mouseCB(int button, int state, int x, int y)
{
mouseX = x;
mouseY = y;
if(button == GLUT_LEFT_BUTTON)
{
if(state == GLUT_DOWN)
{
mouseLeftDown = true;
}
else if(state == GLUT_UP)
参数:
Func:处理各自类型motion的函数名。
处理motion的参数函数的参数(x,y)是鼠标在窗口的坐标。以左上角为原点。
检测鼠标进入或离开窗口
GLUT还能检测鼠标鼠标离开,进入窗口区域。一个回调函数可以被定义去处理这两个事件。GLUT里,调用这个函数的是glutEntryFunc,函数原型如下: