基于OpenGL的3D旋转魔方实现汇总

合集下载

OpenGL实现3DS文件中的模型自由旋转

OpenGL实现3DS文件中的模型自由旋转

OpenGL实现3DS文件中的模型自由旋转文章出处:/course/3_program/c++/cppsl/20071119/86921_2.html摘要简述如何在OpenGL中,读入和显示3DS文件中的模型,并着重阐述通过鼠标拖动对其进行自由旋转的数学基础和编程实现的方法。

关键词OpenGL 3DS文件格式VC++ 自由旋转现在已经有很多论文和书籍提到在OpenGL中实现读入和显示3DS文件中的模型。

但是在很多场合,仅读入和显示是不够的。

我们需要从各个角度观察模型,以便更好地理解模型的形态,形成更为直观的感性认识。

例如,在医学髁上骨折诊断中,如果把骨折后,断骨错位旋转的情况用三维模型模拟出来,并仅用鼠标的拖动就能实现从任何角度观看骨折的情况,这将对医生做出正确的诊断大有裨益。

这也是我们为何考虑实现此项功能的初衷。

本文将简要介绍3DS文件格式,怎样读入和显示模型,而重点放在通过鼠标拖动实现模型自由旋转的数学基础和编程实现的方法和经验。

3DS文件的格式以及读入和显示文件中模型的一些经验.3DS文件是由许多块(chunk)组成的(大块中镶嵌子块)。

由于至今为止,没有一个官方的文献说明其格式,所以还有很多未知的块。

不过这并不影响我们读入3DS文件中的模型。

因为我们在读入时,可以根据自己的需要选择性地读入自己需要的块,而忽略掉那些不感兴趣或未知的块。

这正是块结构给我们带来的好处。

一个块由块信息和块数据组成。

块信息又由块的ID(两个字节长的标识,如4D4D)和块的长度(四个字节,其实也就是下一个块的偏移字节数)组成。

用VC++以十六进制方式打开一3DS文件可以很清楚的看到其结构。

在读入这种块结构(大块中嵌套小块,而块的结构固定)的文件时,完全可以用递归的方法实现,而返回上一级(子块读完,返回父块)的条件则是当前已经读入的块的字节数是否等于块的长度。

从父块转向读入其子块,则可用switch语句实现,通过子块的ID判断进入哪个分支。

OpenGL下三维模型的显示和自由旋转

OpenGL下三维模型的显示和自由旋转

20 世纪 70 年代后期 ,计算机图形工作站的出现推动了基于矢量的 3D 计算机图形学 ( 3D Computer Grap hics) 的迅速发展 . 目前 3D 计算机图形学已经广泛地应用于各个行业和领域 , 如 :3D Max ,Poser 等三维设计软件可以生成复杂的三维模型 . 考虑到软件的通用性 , 本文选 取了图形数据工业标准 — — — DXF 格式的三维模型数据文件作为源文件 , 不仅可以对任意软件 生成的 DXF 格式的三维模型文件进行处理 ,同时还可以处理三维模型和二维模型 . 在三维软件的开发方面 ,目前主要存在 2 种 API : 一个是微软的 Direct 3D ,一个是开放标 准 Open GL . Direct 3D 大量应用于民用产品 ,如游戏领域 ,而 Open GL 作为应用最为广泛的高 性能工业图形标准 ,是开发高质量的二维或三维交互式图形应用程序的首选环境 [ 1 ] . Open GL 提供的应用程序 API 包含了许多现代图形学中的基本功能 , 如 : 图元的绘制 、 颜色指定 、 纹理 映射 、 光照处理 、 双缓存动画和特效等 ; 另外 , 其跨平台的特性也备受用户推崇 ; Open GL 简化 了图形软件的开发过程 ,缩短了产品进入市场的周期 : 因此 ,我们选用 Open GL 作为开发工具 . 在对三维模型的研究中 ,需要对其进行自由旋转 ,以方便从任意角度细致地进行观察 . 本 文提供了一种通过操纵虚拟球实现对模型自由旋转的方法 ,使用户仅通过鼠标的拖动就能从 任何角度观看模型 .
v= b +c , cosβ= c/ v , sinβ= b/ v ;
2 2
1
Rx =
0 0 0
0 β cos sinβ - sinβ cosβ 0 0

openGL+VS2010的例程--旋转立方体(三维)

openGL+VS2010的例程--旋转立方体(三维)

openGL+VS2010的例程--旋转⽴⽅体(三维)效果图如上:步骤:⾸先,设置模型视⾓往后退,再旋转视⾓;然后,⽤默认绘制⽴⽅体函数绘制;最后,利⽤空闲对模型做⾓度微调。

实现代码如下:1 #include <GL\glut.h>23 GLfloat xRotated, yRotated, zRotated;45void Display(void)6 {7 glClear(GL_COLOR_BUFFER_BIT);8 glLoadIdentity();9 glTranslatef(0.0,0.0,-4.0);10 glRotatef(xRotated,1.0,0.0,0.0);11 glRotatef(yRotated,0.0,1.0,0.0);12 glRotatef(zRotated,0.0,0.0,1.0);13//glScalef(2.0,1.0,1.0);14 glutWireCube(1.5);15 glFlush(); //Finish rendering16 glutSwapBuffers();17 }1819void Reshape(int x, int y)20 {21if (y == 0 || x == 0) return; //Nothing is visible then, so return22//Set a new projection matrix23 glMatrixMode(GL_PROJECTION);24 glLoadIdentity();25//Angle of view:40 degrees26//Near clipping plane distance: 0.527//Far clipping plane distance: 20.028 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0);29 glMatrixMode(GL_MODELVIEW);30 glViewport(0,0,x,y); //Use the whole window for rendering31 }32static int times = 0;33void Idle(void)34 {35 times++;36if(times >30000)37 times = 0;3839if(times %30000 == 0)40 {41 xRotated += 0.3;42 yRotated += 0.1;43 zRotated += -0.4;44 Display();45 }46 }474849int main (int argc, char **argv)50 {51//Initialize GLUT52 glutInit(&argc, argv);53 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //For animations you should use double buffering54 glutInitWindowSize(300,300);55//Create a window with rendering context and everything else we need56 glutCreateWindow("Cube example");57 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);58 xRotated = yRotated = zRotated = 0.0;59 glClearColor(0.0,0.0,0.0,0.0);60//Assign the two used Msg-routines61 glutDisplayFunc(Display);62 glutReshapeFunc(Reshape);63 glutIdleFunc(Idle);64//Let GLUT get the msgs65 glutMainLoop();66return0;67 }。

OpenGL 球面相机旋转算法

OpenGL 球面相机旋转算法

旋转作为三维开发的基本功能,在任何3D程序中都需要。

用户通过旋转来实现对模型各个面的浏览,形成直观印象。

球面相机旋转这种旋转方式用户体验方式要优于x轴y轴混合旋转方式,模型旋转的方向和鼠标移动方向保持一致。

下面给出一种“球面相机”实现旋转的方法。

原理:移动鼠标时,通过gluLookAt来改变视点的位置(采用增量的方式),而模型保持不动。

即:只进行视点变换,不进行模型变换。

下图是用户按下左键,在屏幕上移动的一段距离(从A移动到B)。

由于屏幕坐标y轴向下,为了与投影平面坐标系(传统笛卡尔坐标)保持一致。

AM = y1-y2; /*将消息代码描述*/BM = x2-x1;建立屏幕和投影变换近裁截面之间的对应关系(如下图)。

代码实现:1 void setSphereCameraPos()2 {3 // 左键未按下,直接返回4 if (!is_left_button_down)5 return;67 // 从聚焦点指向视点的向量 OA向量8 vector3dd a(eye-target);910 // 计算球面相机半径11 radius = a.getLength();1213 // 将其单位化14 a.normailize();1516 // 当前相机向上方向与a做叉乘,计算投影面水平向右方向向量u17 vector3dd u = upvector.crossProduct(a);18 // 将其单位化19 u.normailize();2021 // 计算相机向上方向在投影面上的投影向量即垂直向上的方向向量v22 vector3dd v = a.crossProduct(u);23 // 将其单位化24 v.normailize();2526 // 计算屏幕AB在投影面上对应的向量 AB向量27 vector3dd m = u*delta_point.x + v*delta_point.y;2829 // 计算m向量的长度30 double len = m.getLength();31 // 降低灵敏度32 len /= 20.0;3334 if (len>0.0)35 {36 // 角度AOB 弧度表示弧长/半径37 double x = len/radius;38 // 将AB向量单位化39 m.normailize();4041 // 按相反方向转动视点到C 从而使得按与鼠标移动一致的方向转动模型42 x = -1*x;43 // 计算新的相机位置 C44 eye = target+(a*cos(x) + m*sin(x))*radius;4546 // 计算新的相机向上方向47 upvector = v;48 }49 }消息代码1 LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window2 UINT uMsg,// Message For This Window3 WPARAM wParam,// Additional Message Information4 LPARAM lParam)// Additional Message Information5 {6 switch(uMsg) // Check For Windows Messages7 {8 case WM_LBUTTONDOWN:9 {10 is_left_button_down = true;11 pre_point.x = LOWORD(lParam);12 pre_point.y = HIWORD(lParam);1314 return 0;15 }1617 case WM_MOUSEMOVE:18 {19 if (is_left_button_down)20 {21 cur_pt.x = LOWORD(lParam);22 cur_pt.y = HIWORD(lParam);// delta_point为增量点23 delta_point.x= cur_pt.x-pre_point.x);// 保持屏幕坐标系和投影平面坐标系一致24 delta_point.y =-1*(cur_pt.y-pre_point.y);// 将当前点赋值给前一个点25 pre_point = cur_pt;26// 计算相机新的位置27 setSphereCameraPos();28 }30 return 0;31 }3233 case WM_LBUTTONUP:34 {35 is_left_button_down = false;36 return 0;37 }38 }3940 // Pass All Unhandled Messages To DefWindowProc41 return DefWindowProc(hWnd,uMsg,wParam,lParam);42 }43vector3dd类vector3dd1 class vector3dd2 {3 private:4 double x,y,z;56 public:7 vector3dd(){};8 vector3dd(double a, double b, double c){x=a;y=b;z=c;}9 vector3dd(const vector3dd& v){*this=v;}11 public:12 void operator=(const vector3dd& v){x=v.x;y=v.y;z=v.z;}13 vector3dd operator*(double a)14 {15 return vector3dd(a*x,a*y,a*z);16 }17 vector3dd operator+(const vector3dd& v)18 {19 return vector3dd(x+v.x,y+v.y,z+v.z);20 }21 vector3dd operator-(const vector3dd& v)22 {23 return vector3dd(x-v.x,y-v.y,z-v.z);24 }2526 public:27 double getX(){return x;}28 double getY(){return y;}29 double getZ(){return z;}3031 void setValue(double a, double b, double c)32 {33 x = a;34 y = b;35 z = c;36 }3738 double getLength()39 {40 return sqrt(x*x+y*y+z*z);41 }4243 void normailize()44 {45 double length = getLength();46 x/=length;47 y/=length;48 z/=length;49 }5051 void invert()52 {53 x*=-1;54 y*=-1;55 z*=-1;56 }5758 vector3dd crossProduct(const vector3dd& v)59 {60 return vector3dd(y*v.z-z*v.y,z*v.x-x*v.z,x*v.y-y*v.x);61 }6263 double dotProduct(const vector3dd& v)64 {65 return (x*v.x+y*v.y+z*v.z);66 }6768 void traceMsg()69 {70 fprintf(stdout, "%.7f, %.7f, %.7f\n", x, y, z);71 }72 };效果图:。

opengl中旋转公式推导

opengl中旋转公式推导

opengl中旋转公式推导OpenGL是一个用于渲染2D和3D图形的开放式图形库。

在OpenGL中,旋转是一种常见的变换操作,用于将对象绕某个轴旋转一定角度。

本文将推导出OpenGL中旋转的公式,并解释其原理和应用。

在OpenGL中,旋转变换是通过一个旋转矩阵来实现的。

旋转矩阵可以描述物体绕某个轴旋转一定角度后的新位置。

假设我们要将一个物体绕原点的Z轴旋转,旋转角度为θ。

那么旋转矩阵可以表示为:R = | cosθ -sinθ 0 || sinθ cosθ 0 || 0 0 1 |其中,cosθ表示θ的余弦值,sinθ表示θ的正弦值。

通过将物体的顶点坐标与旋转矩阵相乘,可以得到旋转后的新顶点坐标。

下面我们来推导一下这个旋转矩阵的公式。

假设物体的原始坐标为P(x, y, z),旋转后的新坐标为P'(x', y', z')。

我们可以表示P为一个列向量:P = | x || y || z |旋转矩阵R作用于P,得到P'的计算公式为:P' = R * P展开矩阵乘法,可以得到:P' = | cosθ -sinθ 0 | * | x || y || z |经过计算,可以得到:x' = x * cosθ - y * sinθy' = x * sinθ + y * cosθz' = z这就是物体绕Z轴旋转θ角度后的新坐标公式。

同样的,我们可以推导出绕X轴和Y轴旋转的公式,分别为:绕X轴旋转:x' = xy' = y * cosθ - z * sinθz' = y * sinθ + z * cosθ绕Y轴旋转:x' = x * cosθ + z * sinθy' = yz' = -x * sinθ + z * cosθ这三个公式分别描述了物体绕X轴、Y轴和Z轴旋转后的新坐标计算方式。

在OpenGL中,我们可以通过调用旋转函数来实现物体的旋转变换。

OPENGL实现3ds文件中的模型自由旋转

OPENGL实现3ds文件中的模型自由旋转
球上# 计算旋转轴的向量和夹角的信息# 将它们保存到一个四元数
/$/
更新旋转矩阵
有 了 以 上 变 量 的 更 新 #接 下 来 就 是 根 据 这 些 更 新 #实 现 旋
转矩阵的更新 $
=)4< 1S;C<;504;H $$ZC@4?;5 !‘aG@ Ca^T=;C6 " 94E !?>1)?:3;6;< " 9?>1)?:3;6;<]E+3*; & 4E !4*S134(Q;< " I I 如果点击右键 # 重置旋转 9 I I 把 K+*6S)6 重置为单位矩阵 [+654\&EA;6a<;C646b!cK+*6S)6 "& I I 把 @B4*S)6 重置为单位矩阵 [+654\&EA;6a<;C646b!c@B4*S)6 "&
%% 和 %! 的叉乘得到 ! 即 ’
作者简介 ! 张正波 &%ERE= $! 男 ! 硕士研究生 ! 研究方向为信号与信息处理 ( 计算机图形图像 %
!"
!""#$%&
万方数据
计算机工程与应用
!"#$%&%’&!
而旋转角度就是 &% 和 &! 之间的夹角 ’ # 因此 $
!! " !& "
0;(6)5&E@ TC0;( & I I 保存拖动时的向量 ! 终点 " JKE3)+6 U<V7*6L4<6B & I I *;68)7C<* 函数用其来调整窗口 JKE3)+6 U<V7*6M;4NB6 &P

OpenGL 3D魔方游戏的设计与实现 3D魔方设计与实现 毕业论文[实用论文]

OpenGL 3D魔方游戏的设计与实现 3D魔方设计与实现 毕业论文[实用论文]

摘要三维动画又称3D动画,是近年来随着计算机软硬件技术的发展而产生的一新兴技术,其技术是模拟真实物体的方式使其成为一个有用的工具。

由于其精确性、真实性和无限的可操作性,目前被广泛应用于医学、教育、军事、娱乐等诸多领域。

本设计是在Visual C++6.0开发环境下,使用OpenGL(Open Graphics Library)函数库,绘制魔方并实现魔方的旋转、随机生成、回拧、透明处理和放大缩小等功能。

采用基本图形的绘图函数及定位函数,添加相应的颜色、纹理来实现魔方模型的绘制。

通过读取载入BMP文件,应用纹理贴图技术来完成对魔方旋转面的处理。

利用随机数来随机产生一个打乱顺序的魔方,并使用C++标准模板库(STL)中的容器来记录魔方的旋转动作,为魔方的回拧提供依据。

关键词:魔方,动画,三维模型,纹理贴图Abstract3-D animation is also called 3D animation, in recent years as computer hardware and software technology and the development of a new and emerging technologies, its technical simulate the real object is the way to become a useful tool. Because of its accuracy, authenticity and unlimited operable, is now widely used in medicine, education, military, entertainment and many other areas.This is designed to Visual C + +6.0 development environment, the use of OpenGL (Open Graphics Library) functions, drawing Rubik's Cube and Rubik's Cube to achieve the rotation, randomly generated, to twist, transparent processing and zoom functions. Drawing a basic function of the graphics and positioning function, add the corresponding color, texture Rubik's Cube model to achieve the draw. By reading load BMP files, applications texture mapping technology to complete the Rubik's Cube rotation of the handle. Using randomly generated random numbers to disrupt the order of a Rubik's Cube, and the use of C + + Standard Template Library (STL) of containers to record the rotating Rubik's Cube action for the Rubik's Cube to provide the basis for fastening.Key words: Rubik's Cube, animation, model, rendering, texture mapping目录1引言 (1)1.1课题研究的目的与意义 (1)1.2 国内外发展现状 (2)1.3 论文的主要内容 (3)2 开发环境及开发工具 (5)2.1 课题需要的知识 (5)2.2 OpenGL概述 (6)3 3D魔方生成的技术实现 (12)3.1 设计思路和需要解决的问题 (12)3.2 初始化 (13)3.3 魔方模型的设计 (17)3.4 纹理及灯光的设计 (20)3.5 程序功能效果 (32)4 总结 (34)参考文献 (35)致谢辞 (36)附录1 外文原文 (37)附录2 中文译文 (46)1引言1.1课题研究的目的与意义一、目的随着计算机技术的发展和三维图形理论与算法的日益成熟,结合三维建模技术进行创建三维电子游戏已经成为可能,对于游戏的三维模拟,除了具有真实感,符合人们平时所看的物体,更可以增添游戏的乐趣。

openGL+VS2010的例程--旋转变色立方体(三维)

openGL+VS2010的例程--旋转变色立方体(三维)

openGL+VS2010的例程--旋转变⾊⽴⽅体(三维)效果图如上。

步骤:⾸先,变换模型视⾓;然后,改变颜⾊;最后,利⽤顶点数组绘制⽴⽅体。

源代码如下:#include <GL/glut.h>// 绘制⽴⽅体// 将⽴⽅体的⼋个顶点保存到⼀个数组⾥⾯static const float vertex_list[][3] ={-0.5f, -0.5f, -0.5f,0.5f, -0.5f, -0.5f,-0.5f, 0.5f, -0.5f,0.5f, 0.5f, -0.5f,-0.5f, -0.5f, 0.5f,0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,};// 将要使⽤的顶点的序号保存到⼀个数组⾥⾯static const GLint index_list[][2] ={{0, 1},{2, 3},{4, 5},{6, 7},{0, 2},{1, 3},{4, 6},{5, 7},{0, 4},{1, 5},{7, 3},{2, 6}};// 绘制⽴⽅体void DrawCube(void){int i,j;glBegin(GL_LINES);for(i=0; i<12; ++i) // 12 条线段{for(j=0; j<2; ++j) // 每条线段 2个顶点{glVertex3fv(vertex_list[index_list[i][j]]);}}glEnd();}static float rotate = 0;static int times = 0;void renderScene(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清理颜⾊缓冲和深度缓冲glMatrixMode(GL_MODELVIEW); // 对模型视景的操作glLoadIdentity(); // 重置当前指定的矩阵为单位矩阵glPushMatrix(); // 压栈//glTranslatef(-0.2, 0, 0); // 平移//glScalef(1, 1, 1); // 缩放times++;if(times > 100){times = 0;}if(times % 100 == 0) // [0, 100){rotate += 0.5; // [0, 20)}glRotatef(rotate, 0, 1, 0); // 旋转glRotatef(rotate, 1, 0, 0);// 动态颜⾊变换--红->绿->蓝->红if(rotate == 0)glColor3f(1, 0, 0);if(rotate ==90)glColor3f(0, 1, 0);if(rotate ==180)glColor3f(0, 0, 1);if(rotate ==270)glColor3f(1, 1, 0);if(rotate ==360)rotate = 0;DrawCube(); // 绘制⽴⽅体glPopMatrix();// 出栈glutSwapBuffers();}int main(int argc, char* argv[]){glutInit(&argc, argv); // 初始化GLUTglutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); // 显⽰窗⼝在屏幕的相对位置glutInitWindowSize(500, 500); // 设置显⽰窗⼝⼤⼩glutCreateWindow(argv[0]); // 创建窗⼝,附带标题glutDisplayFunc(renderScene); // 注册显⽰⽤的函数glutIdleFunc(renderScene); // 注册空闲⽤的函数glutMainLoop(); // GLUT 状态机return0;}。

OpenGL中交互式任意旋转三维场景的实现

OpenGL中交互式任意旋转三维场景的实现

由三维物体生成二维 图形 时需要在世界坐标系 中指定观
察点 、 观察参考点 以及一个表示视线 向上 方向的矢 量 , 这些要 素构成 一个观察坐标 系 , 以表示对象 与观察 者的位 置关系 , 用
也叫做视 点坐标系 。
函数 的前三个 参数 指定 观察 点 ( 视点 )y ee的位 置 , 中间 三个 参 数 指 定 观 察 参 考 点 cn r的位 置 , 后 三个 参 数 et e 最 指定视线向上的方向 u 。 p
个视变换 , 函数声明如下 : 其
vi lL oA ( du l ee , du l ee,G dul yz odg ok tGL obe yx GL obe yy L o beee, u
’ GL o b e c n e x GL o b e c n e ' GL o b e c n ez d u l e tr, d u l e tr, / d u l e t r
最佳选择 , WX Z表 示世 界 坐标 系 ,X Z表 示观 察 坐标 以 Y EY 系 ,X Z O Y 表示局部坐标 系 , 么在观 察 坐标 系下 , 三种 坐 那 这
22 g LoA 函 数 . l ok t u
个坐标 系 , 对象 自身定位于其 中 , 坐标系就是局部坐标 该 这个
系, 用来描述对象的形状 。
2 )世界 坐标系

旦 指定 了单个 物体 的形状 , 我们 就可 以把它放 到场景
g LoA 函数是 一个 O eG l ok t u p n L实用库 函数 , 它定义 了一
图 1 三种坐标系的关系
采用 的交互式输入设备 ( 鼠标 ) 如 不具备 三维 输入能力 , 因此
不能直接 得到三维空 间中的任意轴并利用 gR te () lo t a 来旋 转场景。本文将讨 论在 O eG pn L中利用 鼠标如何简 单有效地 实现三维场景的任 意旋转。

AndroidOpenGL-绘制3D立方体全解

AndroidOpenGL-绘制3D立方体全解

Android OpenGL ES 案例总结3D旋转立方体彩色立方体package com.spl.canvasdemo31.renderer;import android.opengl.GLSurfaceView.Renderer;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.IntBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/*** Cube渲染器类* @author spl**/public class CubeRenderer implements Renderer {public class MyCube {private IntBuffer vertexBuffer;private IntBuffer colorBuffer;private ByteBuffer indexBuffer;public MyCube(){int one = 65535;//每个顶点的坐标值(x,y,z)int vertex[] = {-one, -one, -one,one, -one, -one,one, one, -one,-one, one, -one,-one, -one, one,one, -one, one,one, one, one,-one, one, one};//立方体每个顶点的颜色值,格式为RRGGBBAA0, 0, 0, one,one, 0, 0, one,one, one, 0, one,0, one, 0, one,0, 0, one, one,one, 0, one, one,one, one, one, one,0, one, one, one};//三角形顶点绘制顺序byte index[] = {0, 4, 5, 0, 5, 1,1, 5, 6, 1, 6, 2,2, 6, 7, 2, 7, 3,3, 7, 4, 3, 4, 0,4, 7, 6, 4, 6, 5,3, 0, 1, 3, 1, 2};ByteBuffer vbb = ByteBuffer.allocateDirect(vertex.length*4);vbb.order(ByteOrder.nativeOrder());vertexBuffer = vbb.asIntBuffer();vertexBuffer.put(vertex);vertexBuffer.position(0);ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);cbb.order(ByteOrder.nativeOrder());colorBuffer = cbb.asIntBuffer();colorBuffer.put(colors);colorBuffer.position(0);indexBuffer = ByteBuffer.allocateDirect(index.length);indexBuffer.put(index);indexBuffer.position(0);}public void draw(GL10 gl){gl.glFrontFace(GL10.GL_CW);gl.glV ertexPointer(3, GL10.GL_FIXED, 0, vertexBuffer);gl.glColorPointer(4, GL10.GL_FIXED, 0, colorBuffer);gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, indexBuffer);}}private MyCube myCube;private float roate;public CubeRenderer() {myCube = new MyCube();}public void onDrawFrame(GL10 gl) {// 填充屏幕gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 设置模型视景矩阵为当前操作矩阵gl.glMatrixMode(GL10.GL_MODELVIEW);// 将坐标原点移动到屏幕中心gl.glLoadIdentity();// 移动坐标系gl.glTranslatef(0, 0, -6.0f);// 在Y轴方向旋转坐标系gl.glRotatef(roate, 0, 1, 0);// 在X轴方向旋转坐标系gl.glRotatef(roate * 0.25f, 1, 0, 0);gl.glRotatef(roate, 0, 0, 1);/////////////////////////////////////gl.glScalef(1.2f, 1.2f, 1.2f);//**********大小///////////////////////////////////// 开启顶点坐标gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 开启颜色gl.glEnableClientState(GL10.GL_COLOR_ARRAY);myCube.draw(gl);roate += 0.3f;//********设置旋转角度的增量}public void onSurfaceChanged(GL10 gl, int width, int height) {gl.glViewport(0, 0, width, height);float ratio = (float) width / height;gl.glMatrixMode(GL10.GL_PROJECTION);gl.glLoadIdentity();gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);}public void onSurfaceCreated(GL10 gl, EGLConfig config) {gl.glEnable(GL10.GL_CULL_FACE);gl.glClearColor(0.5F, 0.5F, 0.5F, 1.0F);}}纯色立方体package com.spl.canvasdemo31.renderer;import android.opengl.GLSurfaceView.Renderer;import android.opengl.GLU;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10;/*** 立方体(纯色)*/public class OpenGL3DRenderer implements Renderer { FloatBuffer _mCubeVertexBuffer;//立方体顶点坐标private float box[] = {// FRONT-0.5f, -0.5f, 0.5f,0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,// BACK-0.5f, -0.5f, -0.5f,-0.5f, 0.5f, -0.5f,0.5f, -0.5f, -0.5f,0.5f, 0.5f, -0.5f,// LEFT-0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f,-0.5f, -0.5f, -0.5f,-0.5f, 0.5f, -0.5f,// RIGHT0.5f, -0.5f, -0.5f,0.5f, 0.5f, -0.5f,0.5f, -0.5f, 0.5f,0.5f, 0.5f, 0.5f,// TOP-0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,-0.5f, 0.5f, -0.5f,0.5f, 0.5f, -0.5f,// BOTTOM-0.5f, -0.5f, 0.5f,-0.5f, -0.5f, -0.5f,0.5f, -0.5f, 0.5f,0.5f, -0.5f, -0.5f};private float rotx;private float roty;private float rotz;public void onDrawFrame(GL10 gl) {//清除屏幕gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);//重置模型矩阵gl.glLoadIdentity();/***************这里设置颜色*********************/gl.glColor4f(1f, 0f, 0f, 1f);//纯色的**************** //开启顶点坐标功能gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _mCubeVertexBuffer);//保存matrix当前状态gl.glPushMatrix();//向屏幕移入5个单位gl.glTranslatef(0.0f, 0.0f, -5.0f);//设置旋转轴,以x轴旋转gl.glRotatef(rotx, 1, 0, 0);//设置旋转轴,以y轴旋转gl.glRotatef(roty, 0, 1, 0);//设置旋转轴,以z轴旋转gl.glRotatef(rotz, 0, 0, 1);//绘制第一个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);//绘制第二个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);//绘制第三个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);//绘制第四个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);//绘制第五个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);//绘制第六个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);//将matrix回复成上面push时的 matrixgl.glPopMatrix();//关闭设置顶点功能gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);//使旋转角度不断变化rotx+=0.2f;roty+=0.3f;rotz+=0.4f;}public void onSurfaceChanged(GL10 gl, int width, int height) { //设置场景大小gl.glViewport(0, 0, width, height);//设置投影矩阵gl.glMatrixMode(GL10.GL_PROJECTION);//重置模型矩阵gl.glLoadIdentity();//设置窗口比例和透视图GLU.gluPerspective(gl, 45.0f, (float)width/(float)height, 0.1f, 100.0f);//设置模型矩阵gl.glMatrixMode(GL10.GL_MODELVIEW);//重置模型矩阵}public void onSurfaceCreated(GL10 gl, EGLConfig config) { //将顶点坐标转换为native类型的数据_mCubeVertexBuffer=createFloatBuffer(box);//平滑着色gl.glShadeModel(GL10.GL_SMOOTH);//设置黑色背景gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);//设置深度缓存gl.glClearDepthf(1.0f);//启动深度测试gl.glEnable(GL10.GL_DEPTH_TEST);//深度测试的类型gl.glDepthFunc(GL10.GL_LEQUAL);//告诉系统对透视进行修正gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);}//转换为Native类型的浮点缓存public static FloatBuffer createFloatBuffer(float data[]){ByteBuffer vbb=ByteBuffer.allocateDirect(data.length*4);vbb.order(ByteOrder.nativeOrder());FloatBuffer outBuffer=vbb.asFloatBuffer();outBuffer.put(data).position(0);return outBuffer;}}贴图立方体package com.spl.canvasdemo31.renderer;import android.content.Context;import android.graphics.Bitmap;import android.opengl.GLSurfaceView.Renderer;import android.opengl.GLU;import android.opengl.GLUtils;import com.spl.canvasdemo31.R;import com.spl.canvasdemo31.util.Utility;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/*** 立方体(贴图)*/public class OpenGL3DRendererTex implements Renderer {FloatBuffer _mCubeTexBuffer;Context _context;public OpenGL3DRendererTex(Context context) {_context=context;}//立方体顶点坐标private float box[] = {// FRONT-0.5f, -0.5f, 0.5f,0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,// BACK-0.5f, -0.5f, -0.5f,-0.5f, 0.5f, -0.5f,0.5f, -0.5f, -0.5f,0.5f, 0.5f, -0.5f,// LEFT-0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f,-0.5f, -0.5f, -0.5f,-0.5f, 0.5f, -0.5f,// RIGHT0.5f, -0.5f, -0.5f,0.5f, 0.5f, -0.5f,0.5f, -0.5f, 0.5f,0.5f, 0.5f, 0.5f,// TOP-0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,-0.5f, 0.5f, -0.5f,0.5f, 0.5f, -0.5f,// BOTTOM-0.5f, -0.5f, 0.5f,-0.5f, -0.5f, -0.5f,0.5f, -0.5f, 0.5f,0.5f, -0.5f, -0.5f};//立方体纹理坐标private float texCoords[] = {// FRONT0.0f, 0.0f,1.0f, 0.0f,0.0f, 1.0f,// BACK1.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,0.0f, 1.0f,// LEFT1.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,0.0f, 1.0f,// RIGHT1.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,0.0f, 1.0f,// TOP0.0f, 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 1.0f,// BOTTOM1.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,0.0f, 1.0f};private float rotx;private float roty;private float rotz;public void onDrawFrame(GL10 gl) {// TODO Auto-generated method stub//清除屏幕gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); //重置模型矩阵gl.glLoadIdentity();//开启顶点坐标功能gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//设置顶点坐标gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _mCubeVertexBuffer);gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, _mCubeTexBuffer);//保存matrix当前状态gl.glPushMatrix();//向屏幕移入5个单位gl.glTranslatef(0.0f, 0.0f, -5.0f);//设置旋转轴,以x轴旋转gl.glRotatef(rotx, 1, 0, 0);//设置旋转轴,以y轴旋转gl.glRotatef(roty, 0, 1, 0);//设置旋转轴,以z轴旋转gl.glRotatef(rotz, 0, 0, 1);/***************************************/float fscale = 1.0f;gl.glScalef(fscale, fscale, fscale);//大小//----------------------------------------////绘制第一个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);//绘制第二个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);//绘制第三个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);//绘制第四个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);//绘制第五个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);//绘制第六个立方体面gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);//将matrix回复成上面push时的 matrixgl.glPopMatrix();//关闭设置顶点功能gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//使旋转角度不断变化rotx+=0.2f;roty+=0.3f;rotz+=0.4f;}public void onSurfaceChanged(GL10 gl, int width, int height) {// TODO Auto-generated method stub//设置场景大小gl.glViewport(0, 0, width, height);//设置投影矩阵gl.glMatrixMode(GL10.GL_PROJECTION);//重置模型矩阵gl.glLoadIdentity();//设置窗口比例和透视图GLU.gluPerspective(gl, 45.0f, (float)width/(float)height, 0.1f, 100.0f); //设置模型矩阵gl.glMatrixMode(GL10.GL_MODELVIEW);//重置模型矩阵gl.glLoadIdentity();}public void onSurfaceCreated(GL10 gl, EGLConfig config) {// TODO Auto-generated method stub//将顶点坐标转换为native类型的数据_mCubeVertexBuffer= Utility.createFloatBuffer(box);_mCubeTexBuffer=Utility.createFloatBuffer(texCoords);//开启纹理功能gl.glEnable(GL10.GL_TEXTURE_2D);//加载纹理 ********************************************loadBitmapTex(gl, R.raw.ic_bird);//平滑着色gl.glShadeModel(GL10.GL_SMOOTH);//设置黑色背景gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);//设置深度缓存gl.glClearDepthf(1.0f);//启动深度测试gl.glEnable(GL10.GL_DEPTH_TEST);//深度测试的类型gl.glDepthFunc(GL10.GL_LEQUAL);//告诉系统对透视进行修正gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);}private void loadBitmapTex(GL10 gl,int res){//将图片资源转换为位图资源Bitmap bmp=Utility.getTextureFromBitmapResource(_context, res);//定义1个长度的数组int mTextureID []=new int[1];//将纹理号保存到mTextureIDgl.glGenTextures(1, mTextureID,0);//绑定纹理号到纹理目标gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID[0]);//创建纹理GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);//设定纹理过滤器gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST); bmp.recycle();return;}}MainActivitypublic class MainActivity extends Activity {GLSurfaceView glview;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 全屏显示requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(youtParams.FLAG_FULLSCREEN,youtParams.FLAG_FULLSCREEN);getWindow().setFlags(youtParams.FLAG_KEEP_SCREEN_ON,youtParams.FLAG_KEEP_SCREEN_ON);//setContentView(new MySurfaceView(this));glview = new GLSurfaceView(this);int index = getIntent().getIntExtra("index",0);// 这里可以加载不同的renderer对象if(index == 0) {glview.setRenderer(new OpenGlRender2(null));}if(index == 1) {glview.setRenderer(new SimpleRenderer());}if(index == 2) {glview.setRenderer(new TriangleRenderer());}if(index == 3) {glview.setRenderer(new ColoredTriangleRenderer());}if(index == 4) {glview.setRenderer(new TextedTriangleRenderer(this,glview)); }if(index == 9) {glview.setRenderer(new CubeRenderer());}if(index == 10) {glview.setRenderer(new OpenGL3DRenderer());}if(index == 11) {glview.setRenderer(new OpenGL3DRendererTex(this)); }setContentView(glview);}@Overrideprotected void onPause() {glview.onPause();super.onPause();}@Overrideprotected void onResume() {super.onResume();glview.onResume();}}渲染单一背景色package spl.example.opengldemo;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLSurfaceView.Renderer;import android.util.Log;/*** 渲染单一背景色* @author**/public class SimpleRenderer implements Renderer{@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) { // TODO 表面层创建(只有一次)Log.i("spl", "surface create");}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) { // 表面层改变(多次)Log.i("spl", "width="+width +",height="+height);}@Overridepublic void onDrawFrame(GL10 gl) {// 表面层的绘制(每秒调用多次)gl.glClearColor(0, 1, 0, 1);// 设置清屏颜色gl.glClear(GL10.GL_COLOR_BUFFER_BIT);// 清空颜色缓冲区}}颜色渐变@Overridepublic void onDrawFrame(GL10 gl) {// 表面层的绘制(每秒调用多次)changeColor();gl.glClearColor(0, r, g, b);// 设置清屏颜色gl.glClear(GL10.GL_COLOR_BUFFER_BIT);// 清空颜色缓冲区}float r=1,g=0,b=1;private void changeColor(){if (r>1){r=0;}r += 0.01f;if (g>1){g=0;}g += 0.01f;if (b>1){b=0;}b += 0.01f;}纯色三角形package spl.gl.test;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.app.Activity;import android.content.Context;import android.opengl.GLSurfaceView;import android.opengl.GLSurfaceView.Renderer;import android.os.Bundle;import android.os.PowerManager;import android.os.PowerManager.WakeLock;import android.util.Log;import android.view.Window;import android.view.WindowManager;public class GLTestActivity extends Activity {/** Called when the activity is first created. */GLSurfaceView glView;long count = 0;WakeLock wakeLock;FloatBuffer vertices;// 储存3个顶点private Renderer renderer = new Renderer() {@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 当创建GLSurfaceView时被调用,只调用一次.//在这个方法中执行只发生一次的动作,比如设置OpenGL环境参数或初始化OpenGL图形对象Log.i("spl", "surface created");// 在主机的堆内存中(而不是虚拟机的堆内存中)分配一段字节缓存区ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * 2 * 4);byteBuffer.order(ByteOrder.nativeOrder());// 确保字节顺序等于CPU的字节顺序vertices = byteBuffer.asFloatBuffer();//// 将字节转化为浮点vertices.put(new float[]{140, 300,// 左下角 // 注意:这里只有x,y OpenGL会自动设置z=0340, 300,//右下角240, 500});vertices.flip();//初始化位置和长度Log.i("spl", "surfacecreated:glWiew="+glView.getWidth()+"x"+glView.getHeight());gl.glViewport(0, 0, glView.getWidth(), glView.getHeight());gl.glMatrixMode(GL10.GL_PROJECTION);// 设置投影矩阵(平行,透视)gl.glLoadIdentity();gl.glOrthof(0, glView.getWidth(), 0, glView.getHeight(), 1, -1);//设置gl.glColor4f(0, 1, 0, 1);gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 通知GL所有绘制的顶点都有位置(废话)//告诉GL从何处取得顶点的位置以及其他信息://2代表x,y(3代表x,y,z);每个点由两个坐标组成//GL10.GL_FLOAT告知所使用的数据类型//0 代表步长,是位置与位置之间的字节距离//vertices 是浮点缓冲区gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);// 把顶点位置传输到GPU并储存}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 几何体改变时系统调用此方法,比如GLSurfaceView的大小改变或设备屏幕的方向改变.//使用此方法来响应GLSurfaceView容器的变化.Log.i("spl", "surface changed: " + width + "x" + height);}@Overridepublic void onDrawFrame(GL10 gl) {// 系统在每次重绘GLSurfaceView时调用此方法.此方法是绘制图形对象的主要的执行点.//count++;//Log.i("spl", "surface draw:"+count);gl.glClearColor(1, 1, 1, 1);// 清空像素的帧缓冲区gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//GL10.GL_TRIANGLES 绘制类型//0 代表顶点偏移量, 也就是从第一个顶点开始画起//3 顶点数量gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);// 它将绘制三角形 // 必须}};// 渲染者@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(youtParams.FLAG_FULLSCREEN,youtParams.FLAG_FULLSCREEN);glView = new GLSurfaceView(this);glView.setRenderer(renderer);setContentView(glView);// 打开屏幕锁PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLTestActivity"); }@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();glView.onResume();wakeLock.acquire();Log.i("spl", "onResume");}@Overrideprotected void onPause() {// TODO Auto-generated method stubwakeLock.release();glView.onPause();super.onPause();Log.i("spl", "onPause");}}彩色三角形package spl.gl.test;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.app.Activity;import android.content.Context;import android.opengl.GLSurfaceView;import android.opengl.GLSurfaceView.Renderer;import android.os.Bundle;import android.os.PowerManager;import android.os.PowerManager.WakeLock;import android.util.Log;import android.view.Window;import android.view.WindowManager;public class GLTestActivity extends Activity {/** Called when the activity is first created. */GLSurfaceView glView;long count = 0;WakeLock wakeLock;FloatBuffer vertices;// 储存3个顶点private Renderer renderer = new Renderer() {final int VERTEX_SIZE = (2 + 4) * 4;@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 当创建GLSurfaceView时被调用,只调用一次.//在这个方法中执行只发生一次的动作,比如设置OpenGL环境参数或初始化OpenGL图形对象Log.i("spl", "surface created");// 在主机的堆内存中(而不是虚拟机的堆内存中)分配一段字节缓存区ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE);byteBuffer.order(ByteOrder.nativeOrder());// 确保字节顺序等于CPU的字节顺序vertices = byteBuffer.asFloatBuffer();//// 将字节转化为浮点vertices.put(new float[]{140, 300,1, 0, 0, 1,//添加颜色信息// 左下角 // 注意:这里只有x,y OpenGL会自动设置z=0340, 300,0, 1, 0, 1,//右下角240, 500,0, 0, 1, 1});vertices.flip();//初始化位置和长度Log.i("spl", "surfacecreated:glWiew="+glView.getWidth()+"x"+glView.getHeight());gl.glViewport(0, 0, glView.getWidth(), glView.getHeight());gl.glMatrixMode(GL10.GL_PROJECTION);// 设置投影矩阵(平行,透视)gl.glLoadIdentity();gl.glOrthof(0, glView.getWidth(), 0, glView.getHeight(), 1, -1);//设置gl.glColor4f(0, 1, 0, 1);// 默认颜色gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 通知GL所有绘制的顶点都有位置(废话)gl.glEnableClientState(GL10.GL_COLOR_ARRAY);// 告知GL 顶点包含颜色信息, 取代默认色//gl.glDisableClientState(GL10.GL_COLOR_ARRAY);// 关闭颜色vertices.position(0);gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);// 把顶点位置传输到GPU 并储存vertices.position(2);gl.glColorPointer(4, GL10.GL_FLOAT, VERTEX_SIZE, vertices);// 告知GL颜色在缓冲区的位置//告诉GL从何处取得顶点的位置以及其他信息://2代表x,y(3代表x,y,z);每个点由两个坐标组成//GL10.GL_FLOAT告知所使用的数据类型//0 代表步长,是位置与位置之间的字节距离//vertices 是浮点缓冲区//gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);// 把顶点位置传输到GPU并储存}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 几何体改变时系统调用此方法,比如GLSurfaceView的大小改变或设备屏幕的方向改变.//使用此方法来响应GLSurfaceView容器的变化.Log.i("spl", "surface changed: " + width + "x" + height);}@Overridepublic void onDrawFrame(GL10 gl) {// 系统在每次重绘GLSurfaceView时调用此方法.此方法是绘制图形对象的主要的执行点.//count++;//Log.i("spl", "surface draw:"+count);gl.glClearColor(1, 1, 1, 1);// 清空像素的帧缓冲区gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//GL10.GL_TRIANGLES 绘制类型//0 代表顶点偏移量, 也就是从第一个顶点开始画起//3 顶点数量gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);// 它将绘制三角形 // 必须}};// 渲染者@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(youtParams.FLAG_FULLSCREEN,youtParams.FLAG_FULLSCREEN);glView = new GLSurfaceView(this);glView.setRenderer(renderer);setContentView(glView);// 打开屏幕锁PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLTestActivity"); }@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();glView.onResume();wakeLock.acquire();Log.i("spl", "onResume");}@Overrideprotected void onPause() {// TODO Auto-generated method stubwakeLock.release();glView.onPause();super.onPause();Log.i("spl", "onPause");}}对三角形加载纹理(贴图)package spl.gl.test;import java.io.IOException;import java.io.InputStream;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.opengl.GLSurfaceView;import android.opengl.GLUtils;import android.opengl.GLSurfaceView.Renderer;import android.os.Bundle;import android.os.PowerManager;import android.os.PowerManager.WakeLock;import android.util.Log;import android.view.Window;import android.view.WindowManager;public class GLTestActivity extends Activity { /** Called when the activity is first created. */ GLSurfaceView glView;long count = 0;WakeLock wakeLock;FloatBuffer vertices;// 储存3个顶点public Bitmap getBitmap(String path){Bitmap bitmap = null;InputStream is = null;try {is = getAssets().open(path);bitmap = BitmapFactory.decodeStream(is);} catch (Exception e) {// TODO: handle exception}finally{if (is != null) {try {is.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}return bitmap;}private Renderer renderer = new Renderer() {final int VERTEX_SIZE = (2 + 2) * 4;int textureId ;@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 当创建GLSurfaceView时被调用,只调用一次.//在这个方法中执行只发生一次的动作,比如设置OpenGL环境参数或初始化OpenGL图形对象Log.i("spl", "surface created");// 在主机的堆内存中(而不是虚拟机的堆内存中)分配一段字节缓存区ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE);byteBuffer.order(ByteOrder.nativeOrder());// 确保字节顺序等于CPU的字节顺序vertices = byteBuffer.asFloatBuffer();//// 将字节转化为浮点vertices.put(new float[]{140, 300, 0.0f, 1.0f,//添加颜色信息// 左下角 // 注意:这里只有x,y OpenGL会自动设置z=0340, 300, 1.0f, 1.0f,//右下角240, 500, 0.5f, 0.0f});vertices.flip();//初始化位置和长度Log.i("spl", "surfacecreated:glWiew="+glView.getWidth()+"x"+glView.getHeight());gl.glViewport(0, 0, glView.getWidth(), glView.getHeight());gl.glMatrixMode(GL10.GL_PROJECTION);// 设置投影矩阵(平行,透视)gl.glLoadIdentity();gl.glOrthof(0, glView.getWidth(), 0, glView.getHeight(), 1, -1);//设置剪裁空间(正交矩形)textureId = loadTexture(gl, "desktop.png");gl.glEnable(GL10.GL_TEXTURE_2D);// 启用纹理gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);// 绑定纹理//gl.glColor4f(0, 1, 0, 1);// 默认颜色gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 通知GL所有绘制的顶点都有位置(废话)gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);// 告知GL 顶点包含纹理坐标信息, 取代默认色//gl.glDisableClientState(GL10.GL_COLOR_ARRAY);// 关闭颜色vertices.position(0);gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);// 把顶点位置传输到GPU 并储存vertices.position(2);gl.glTexCoordPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);// 告知GL纹理坐标在缓冲区的位置//告诉GL从何处取得顶点的位置以及其他信息://2代表x,y(3代表x,y,z);每个点由两个坐标组成//GL10.GL_FLOAT告知所使用的数据类型//0 代表步长,是位置与位置之间的字节距离//vertices 是浮点缓冲区//gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);// 把顶点位置传输到GPU并储存}public int loadTexture(GL10 gl,String path){Bitmap bitmap = getBitmap(path);// 创建纹理对象int textureIds[] = new int[1];gl.glGenTextures(1, textureIds, 0);// 参数1:要创建多少纹理对象;参数2:纹理id在其中;保存id的起始点int textureId = textureIds[0];// 无法返回java对象,所以返回id// 纹理上传gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); // 绑定纹理对象// 参数1:文理类型//参数2:多纹理映射层次// 参数3:位图// 参数4:永远是0GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);// 上传纹理图片(android框架)// 设置过滤类型,(需要放大和缩小)//GL_NEAREST是一种过滤器类型,他和GL_LINEAR的区别是不做平滑过渡gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);// 取消绑定,释放资源,节省内存gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);bitmap.recycle();return textureId;}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 几何体改变时系统调用此方法,比如GLSurfaceView的大小改变或设备屏幕的方向改变.//使用此方法来响应GLSurfaceView容器的变化.Log.i("spl", "surface changed: " + width + "x" + height);}@Overridepublic void onDrawFrame(GL10 gl) {// 系统在每次重绘GLSurfaceView时调用此方法.此方法是绘制图形对象的主要的执行点.//count++;//Log.i("spl", "surface draw:"+count);gl.glClearColor(1, 1, 1, 1);// 清空像素的帧缓冲区gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//GL10.GL_TRIANGLES 绘制类型//0 代表顶点偏移量, 也就是从第一个顶点开始画起//3 顶点数量gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);// 它将绘制三角形 // 必须}};// 渲染者@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(youtParams.FLAG_FULLSCREEN,youtParams.FLAG_FULLSCREEN);glView = new GLSurfaceView(this);glView.setRenderer(renderer);setContentView(glView);// 打开屏幕锁PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLTestActivity"); }@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();glView.onResume();wakeLock.acquire();Log.i("spl", "onResume");}@Overrideprotected void onPause() {// TODO Auto-generated method stubwakeLock.release();glView.onPause();super.onPause();Log.i("spl", "onPause");}}绘制两个纹理三角形package spl.gl.test;import java.io.IOException;import java.io.InputStream;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import java.nio.ShortBuffer;import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.opengl.GLSurfaceView;import android.opengl.GLUtils;import android.opengl.GLSurfaceView.Renderer;import android.os.Bundle;import android.os.PowerManager;import android.os.PowerManager.WakeLock;import android.util.Log;import android.view.Window;import android.view.WindowManager;public class GLTestActivity extends Activity { /** Called when the activity is first created. */ GLSurfaceView glView;long count = 0;WakeLock wakeLock;public Bitmap getBitmap(String path){Bitmap bitmap = null;InputStream is = null;try {is = getAssets().open(path);bitmap = BitmapFactory.decodeStream(is);} catch (Exception e) {// TODO: handle exception}finally{if (is != null) {try {is.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();。

OpenGL的glRotatef旋转变换函数详解

OpenGL的glRotatef旋转变换函数详解

OpenGL的glRotatef旋转变换函数详解OpenGL的glRotatef旋转变换函数详解先看⼀下函数定义:void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)angle:为旋转的⾓度,单位为度。

x,y,z:为对应xyz轴的布尔值变量。

重点是x,y,z表达的是什么意思呢?应该如何取值?如果说x,y,z表达的是⼀个坐标(x,y,z),那么这个函数就说明了当前⼏何图形围着这个坐标点旋转。

但往哪个⽅向旋转呢?所以很明显,x,y,z表达的意思并不是坐标点,⽽是要围绕哪个坐标轴旋转。

即其实这⾥的x,y,z值相当于⼀个布尔值,0.0表⽰假,⽽⾮零参数则表⽰真。

所以如果你想让当前的⼏何图形围绕着z轴旋转,那么x和y都设为0,⽽z设为⾮零值即可。

如果这⾥的x,y,z的值都设置为0.0,那么将围绕着x轴旋转。

还有⼀点需要注意,如果设置的旋转值(x,y,z的值)为正数,那么旋转的⽅向是逆时针的,如果旋转值是负数,那么旋转的⽅向是顺时针的。

假设:glRotatef(45,1,0,0)物体如何旋转?想象:从坐标(0,0,0)即原点,引出⼀条线到(1,0,0),⽤右⼿握住这条线.这时,你会问,如何握?右⼿⼤拇指指向(0,0,0)⾄(1,0,0)的⽅向才握。

另外四个⼿指的弯曲指向即是物体旋转⽅向。

为什么是右⼿握住,⽽不是左⼿呢?因为OpenGL是右⼿原则。

最后附上代码供参考:1 #include <stdio.h>2 #include <gl/glut.h>34/*5功能描述:使⽤OpenGL简单画⼀个旋转的三⾓形6旋转变换函数glRotatef7*/89//输出模式,0-单缓存模式;⾮0双缓存模式10#define OUTPUT_MODE 11112//⾓度13int angle = 0;1415int xyz[3] = {0, 0, 0};1617void display(void)18 {19//printf("xyz={%d, %d, %d\n}", xyz[0], xyz[1], xyz[2]);2021 glClear(GL_COLOR_BUFFER_BIT);222324 glLoadIdentity();25 glRotatef(angle, xyz[0], xyz[1], xyz[2]);2627 glBegin(GL_TRIANGLES);28 {29 glVertex3f(0.0f, 0.0f, 0.0f);30 glVertex3f(0.5f, 0.0f, 0.0f);31 glVertex3f(0.0f, 0.5f, 0.0f);32 }33 glEnd();3435 angle += 1;36 angle %= 360;3738if (OUTPUT_MODE == 0) {39 glFlush();//单缓存GLUT_SINGLE时使⽤40 } else {41 glutSwapBuffers();//因为使⽤的是双缓存GLUT_DOUBLE,所以这⾥必须要交换缓存才会显⽰42 }43 }4445//按键46void keyboard(unsigned char key, int x, int y)47 {48switch (key)49 {50case'x':51case'X':52 xyz[0] = 1;53 xyz[1] = xyz[2] = 0;54break;55case'y':56case'Y':57 xyz[1] = 1;58 xyz[0] = xyz[2] = 0;59break;60case'z':61case'Z':62 xyz[2] = 1;63 xyz[0] = xyz[1] = 0;64break;65case'a':66case'A':67 xyz[0] = xyz[1] = xyz[2] = 0;68break;69case'b':70case'B':71 xyz[0] = xyz[1] = xyz[2] = 1;72break;73default:74break;75 }76 printf("当前绕%c轴旋转\n", key);77 glutPostRedisplay();78 }7980void reshape(int w, int h)81 {82int offset = 50;83int dis = (w > h ? h : w) - offset * 2;8485//配置显⽰物体屏幕的⼤⼩86 glViewport(offset, offset, (GLsizei)dis, (GLsizei)dis);87 printf("reshape: w=%d, h=%d, dis=%d\n", w, h, dis);8889 glMatrixMode(GL_PROJECTION);90 glLoadIdentity();9192 glOrtho(-1.5, 1.5, -1.5, 1.5, 0, 10);93//gluOrtho2D(-1.5, 1.5, -1.5, 1.5);9495 glMatrixMode(GL_MODELVIEW);96 glLoadIdentity();97 }9899int main(int argc, char *argv[])100 {101 printf("可通过按键xyzab控制图形旋转原点/轴\n");102 glutInit(&argc, argv);103104 glutInitDisplayMode(GLUT_RGB | (OUTPUT_MODE == 0 ? GLUT_SINGLE : GLUT_DOUBLE)); 105 glutInitWindowPosition(100, 100);106 glutInitWindowSize(400, 400);107108 glutCreateWindow("第⼀个 OpenGL 程序");109110 glutDisplayFunc(&display);111 glutIdleFunc(display); //设置不断调⽤显⽰函数112 glutReshapeFunc(reshape);113 glutKeyboardFunc(&keyboard);114 glutMainLoop();115return0;116 }。

opengl 3D迷宫 C 实现 源代码之欧阳法创编

opengl 3D迷宫 C  实现 源代码之欧阳法创编

#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <GL/glut.h>#include <math.h>#include <iostream>using namespace std;void drawwalls(void);void drawtop(void);void drawball(void);#define IDM_APPLICATION_EXIT (101)#define IDM_APPLICATION_TEXTURE (102) #define IDM_APPLICATION_BANK (103) #define MAZE_HEIGHT (16)#define MAZE_WIDTH (16)#define STARTING_POINT_X (13.5f);#define STARTING_POINT_Y (1.5f);#define STARTING_HEADING (90.0f);float player_x = STARTING_POINT_X ;float player_y = STARTING_POINT_Y ;float player_h = STARTING_HEADING ; // player's headingfloat player_s = 0.0f; // forward speed of the playerfloat player_m = 1.0f; // speed multiplier of the player float player_t = 0.0f; // player's turning (change in heading)float player_b = 0.0f; // viewpoint bank (roll)static float texcoordX=0.0f;int walllist=0;int mazelist=0;int balllist=0;int status=1;bool searchroute=false;bool keystate[4]={false,false,false,false};char mazedata[MAZE_HEIGHT][MAZE_WIDTH] = { {'H','H','H','H','H','H','H','H','H','H','H','H','H','H','H',' H'},{'H',' ',' ',' ',' ',' ',' ',' ','H',' ',' ',' ',' ',' ',' ','H'},{'H',' ','H',' ','H','H','H',' ','H',' ','H',' ',' ',' ',' ','H'},{'H',' ','H','H',' ',' ','H',' ','H','H',' ','H',' ','H',' ','H'},{'H',' ',' ',' ',' ',' ','H',' ',' ',' ',' ',' ',' ','H',' ','H'},{'H',' ','H','H','H','H','H','H','H','H',' ','H','H','H',' ','H'}, {'H',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H',' ',' ','H'},{'H',' ','H','H','H','H','H',' ','H','H','H',' ','H','H','H','H'}, {'H',' ','H',' ',' ',' ','H',' ',' ',' ','H',' ',' ',' ',' ','H'},{'H',' ',' ',' ','H','H','H','H','H','H','H',' ',' ',' ',' ','H'},{'H',' ','H',' ',' ',' ','H',' ',' ',' ','H',' ',' ','H',' ','H'},{'H',' ','H','H','H','H','H',' ','H','H','H','H',' ','H',' ','H'},{'H',' ',' ',' ',' ',' ','H',' ',' ',' ',' ',' ',' ','H',' ','H'},{'H',' ',' ','H','H',' ','H','H','H','H',' ','H','H','H',' ','H'},{'H',' ',' ',' ','H',' ','H',' ',' ',' ',' ','H',' ',' ',' ','H'},{'H','H','H','H','H','H','H','H','H','H','H','H','H',' ','H','H'}, };void myinit(){glClearColor(0.5f, 0.5f, 0.5f, 0.0f);glColor3f(1.0,1.0,1.0);glEnable(GL_DEPTH_TEST);glEnable(GL_TEXTURE_2D);walllist=glGenLists(2);mazelist=walllist+1;balllist=walllist+2;glNewList(walllist,GL_COMPILE);drawwalls();glEndList();glNewList(mazelist,GL_COMPILE);drawtop();glEndList();glNewList(balllist,GL_COMPILE);drawball();glEndList();glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0, 1.0 , 0.1, 60.0);glMatrixMode(GL_MODELVIEW);glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL _NICEST);//ʹÎÆÀí²»±äÐÎ}bool wall(int x,int y) {return (x>=0 && y>=0 && x<MAZE_WIDTH && y<MAZE_HEIGHT && mazedata[y][x]!=' ');}bool onopen(int x,int y){if(wall(x,y)){return(mazedata[y][x]=='H');}}void closeit(int x,int y) {if(onopen(x,y)){mazedata[y][x]= 'X';}}bool neighbor(int x,int y,int w,int *nx,int *ny){switch(w) {case 0:*nx = x1; *ny=y; break;case 1:*nx = x; *ny=y+1; break;case 2:*nx = x+1; *ny=y; break;case 3:*nx = x; *ny=y1; break;default:break;}return wall(*nx,*ny);}bool diagnal(int x,int y,int w,int *nx,int *ny){ switch(w) {case 0:*nx = x1; *ny=y1; break;case 1:*nx = x1; *ny=y+1; break;case 2:*nx = x+1; *ny=y+1; break;case 3:*nx = x+1; *ny=y1; break;default:break;}return wall(*nx,*ny);}void dw(int x,int y,int p) {int w=p;closeit(x,y);do{int x2=0;int y2=0;if(neighbor(x,y,w,&x2,&y2)){if(onopen(x2,y2)) {dw(x2,y2,(w+3)%4);}else {if((w+1)%4 ==p){return ;}}}else {float fx;float fy;if(diagnal(x,y,w,&x2,&y2) && onopen(x2,y2)) {dw(x2,y2,(w+2)%4);}texcoordX=(texcoordX<0.5)?1.0f:0.0f;fx = (float)x+((w==1||w==2)?1.0f:0.0f);fy = (float)y+((w==0||w==1)?1.0f:0.0f);glTexCoord2f(texcoordX,0.0f);glVertex3f(fx,fy,0.0f);glTexCoord2f(texcoordX,1.0f);glVertex3f(fx,fy,1.0f);}w++;w%=4;}while (w!=p);return ;}void drawwalls() {glEnable(GL_TEXTURE_2D); glBegin(GL_QUAD_STRIP);glColor3f(1.0,1.0,1.0);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0f, 0.0f, 1.0f);dw(0,0,0);glEnd();}void drawtop() {int x,y;glBegin(GL_QUADS);for(y=0;y<MAZE_HEIGHT;y++) { for(x=0;x<MAZE_WIDTH;x++) { if(wall(x,y)) {mazedata[y][x]= 'X';glVertex3f(x+0.0f ,y+0.0f ,1.0f );glVertex3f(x+1.0f ,y+0.0f ,1.0f ); glVertex3f(x+1.0f ,y+1.0f ,1.0f ); glVertex3f(x+0.0f ,y+1.0f ,1.0f ); }}}glEnd();}void forward(float px,float py,float bf) { int x = ((int)player_x);int y = ((int)player_y);int h=0;if((px> x+1.0f bf) && wall(x+1,y)) { px = (float)(x)+1.0fbf;h++;}if(py> y+1.0fbf && wall(x,y+1)) { py = (float)(y)+1.0fbf;h++;}if(px< x+bf && wall(x1,y)) {px = (float)(x)+bf;h++;}if(py< y+bf && wall(x,y1)) {py = (float)(y)+bf;h++;}player_x=px;player_y=py;}void drawball(){glDisable(GL_TEXTURE_2D);glColor3f(1.0,0.0,0.0);glutSolidSphere(0.2f,15,15);}void navmaze1(){forward(player_x+player_s*(float)sin(player_h*3.14/180),player_y+player_s*(float)cos(player_h*3.14/180),0.2f);cout<<player_x<<player_y<<endl;player_h+=player_t;player_b = 3*player_b/4 + player_t/4;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();glPushMatrix();glRotatef(90.0f,1.0f,0.0f,0.0f);glRotatef(player_h,0.0f,0.0f,1.0f);glTranslatef(player_x,player_y,0.5f);glCallList(walllist);glPopMatrix();}void navmaze2(){forward(player_x+player_m*player_s*(float)sin(playe r_h*3.14/180),player_y+player_m*player_s*(float)cos(player_h*3.14/180) ,0.2f);cout<<player_x<<player_x<<endl;player_h+=player_t;player_b = 3*player_b/4 + player_t/4;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();glOrtho(16.0,16.0,16.0,16.0,2.0,20.0);glPushMatrix();glRotatef(90.0f,0.0f,0.0f,1.0f);glTranslatef(MAZE_WIDTH/2,MAZE_HEIGHT/2,0.5f);glCallList(walllist);glCallList(mazelist);glPushMatrix();glTranslatef(player_x,player_y,0.5f);glCallList(balllist);glPopMatrix();glPopMatrix();}void myDisplay(){if(status==1){if(searchroute==true){}else navmaze1();}if(status==3){if(searchroute==true){}else navmaze2();}glFlush();glutSwapBuffers();}void myReshape(int w, int h){glViewport(0,0,w,h);glMatrixMode(GL_PROJECTION);glLoadIdentity();glMatrixMode(GL_MODELVIEW);glLoadIdentity();glutPostRedisplay();}void specialKeys(int key,int x,int y){switch (key){case GLUT_KEY_LEFT:keystate[2] = true;player_t = 2.0f;break;case GLUT_KEY_RIGHT:keystate[3] = true;player_t = 2.0f;break;case GLUT_KEY_UP:keystate[0] = true;player_s = 0.01f;break;case GLUT_KEY_DOWN:keystate[1] = true;player_s = 0.01f;break;default:break;}}void keyboard(unsigned char key,int x,int y){switch (key){case '1':status=1;break;case '3':status=3;break;default:break;}glutPostRedisplay();}void upSpecialKeyboard(int key,int x,int y){switch (key){case GLUT_KEY_LEFT:keystate[2] = false;player_t = 0.0f;break;case GLUT_KEY_RIGHT:keystate[3] = false;player_t = 0.0f;break;case GLUT_KEY_UP:keystate[0] = false;player_s = 0.0f;break;case GLUT_KEY_DOWN:keystate[1] = false;player_s = 0.0f;break;default:break;}// glutPostRedisplay();}void idle(){if(keystate[0]||keystate[1]||keystate[2]||keystate[3]) glutPostRedisplay();else{}}//ÊÍ·Å°´¼üºó¾Í½øÈë¿ÕÏÐ״̬£¬Èç¹û¿ÕÏÐ״̬²»Ò»Ö±Öظ´»æͼ£¬¾Í»á»­ÃæÍ£ÖÍ¡£´Î·½·¨È±µãÊÇ¿ªÏúºÜ´óvoid main(int argc, char** argv){glutInit(&argc,argv);glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);glutInitWindowSize(500, 500);glutCreateWindow("polygon modeler");glutDisplayFunc(myDisplay);myinit ();glutSpecialFunc(specialKeys);glutKeyboardFunc(keyboard);glutSpecialUpFunc(upSpecialKeyboard);glutIdleFunc(idle);glutMainLoop();}。

基于OpenGL 的魔方自动求解算法与实现

基于OpenGL 的魔方自动求解算法与实现

第36卷 第7期2004年7月 哈 尔 滨 工 业 大 学 学 报JOURNA L OF H ARBI N I NSTIT UTE OF TECH NO LOGYV ol 136N o 17July ,2004基于Open G L 的魔方自动求解算法与实现何智勇,贲可荣(海军工程大学计算机系,湖北武汉430033,E 2mail :benkerong @ )摘 要:在魔方分层求解算法的基础上,利用OpenG L 的3D 技术,实现了一个演示自动求解过程的示教系统,同时提供了玩家可以手动操作的游戏平台.关键词:魔方;算法;仿真;OpenG L 中图分类号:TP24文献标识码:A文章编号:0367-6234(2004)07-0893-03Automatic resolving algorithm and realizationof magic cube based on Open G LHE Zhi 2y ong ,BE N K e 2rong(Dept.of C om puter ,Naval University of Engineering ,Wuhan 430033,China ,E 2mail :benkerong @ )Abstract :Based on layer 2by 2layer alg orithm and OpenG L 3D technology ,a dem o system is realized ,which presents a game application platform for the users to res olve the magic cube problem manully.K ey w ords :magic cube ;alg orithm ;simulation ;OpenG L收稿日期:2004-04-26.作者简介:何智勇(1981-),男,硕士研究生;贲可荣(1963-),男,博士,教授,博士生导师. 魔方是人们熟悉的一种益智游戏,变化比较复杂[1,2].本文首先建立魔方合适的数学模型,然后再用程序设计语言中合适的数据结构表示出来,在合理的数据结构基础上,利用一种按层复杂的求解算法,开发了一个3D 演示平台,用户可以利用本平台手动操作魔方,操作简单直观,演示效果逼真,当人工求解遇到困难时,可以自动演示求解步骤.另外,本文对魔方有解情况的判断作了讨论.1 数学模型的建立首先建立如图1所示的坐标系:将魔方的6个面各向外扩充一层,使每一个小块上的每个面都有惟一的坐标表示,即用每个小块的中心坐标表示.至此,魔方各面可用惟一的三维坐标表示(图2). 然后,定义魔方的基本变换的记号.魔方的基本变换是每个面顺时针转动90°.如图1所示,魔方的前、后、左、右、上、下各面的基本操作分别用A 、B 、L 、R 、U 、D 表示.即A ,A 2,A 3分别表示A面转动90°,180°和270°.类似定义其他各面.图1 坐标表示图2 扩展魔方三维坐标 一个操作串(例如AURAB )是一个宏操作.一个有用的宏操作称为宏变换.例如:D 2L 2R 2U 2L 2R 2是一个宏变换,能将(3,2,1)与(1,2,1)对换,(3,2,3)与(1,2,3)对换,其余不变.2 自动求解算法求解的算法很多,这里给出按层次求解的方法.完整求解框图如图3所示.首先解释几个术语.块归位指所需块已经到位,但各面位置并不一定合适,需要通过原地的翻转来调整.还原指块的位置和各面方向都符合要求.魔方各块根据有色面的多少,分为角块、边块和中心块.各块用小块中心坐标表示,如(1,1,3);块上某面用坐标和坐标指向的四元组表示,如(1,1,3,z ),表示此块朝上的面.图3 完整求解流程图 模块1(图4)采用逐块还原,即还原后续块时,保持已还原的块不动.还原最上层边块,使得最上层4个边块朝上的面颜色与最上层中心块同色,同时,4个侧面颜色与侧面中心块颜色一致.图4 模块1 模块2(图5)也采用逐块还原.模块结束后,第一层已经全部还原. 魔方的第二层,实际上只有4个边块需要还原(图6).此处用到了宏变换1:A 2L 3RU 2LR 3,此变换将(3,2,1)转到(1,2,3)的位置,且x ϖx ,z ϖz ;将(3,2,3)转到(3,2,1)的位置,且x ϖx ,z ϖz ;将(1,2,3)转到(3,2,3)的位置,且x ϖx ,z ϖz.模块5(图7)把第三层的4个边块朝上的一面都调成与中心块同色.这里的宏变换2:AUD 3LUD 3BUD 3RUD 3,将4个边块原地翻身.图5 模块2图6 模块4・498・哈 尔 滨 工 业 大 学 学 报 第36卷 图7 模块5图8 模块6 模块7(流程图略)将第三层4个角块归位.其中宏变换3表示ADA 2D 2A 2D 3A 3. 模块8(流程图略)使第三层角块原地顺转或逆转,使魔方全部还原.宏变换4:A 3U 3AU 3A 3U 2AU 2AUA 3UAU 2A 3U 2,将(1,1,3)角块逆时针转120°,将(1,3,3)角块顺时针转动120°.3 程序实现通过简单地扩展一个三维数组的长度,就可得到一种魔方的数据表示.如设定数组C olor [5][5][5]存储各块各面的颜色,则C olor[1][1][4]对应于元组(1,1,3,x ),虽然有部分数据的冗余,但因为整体空间开销很小,可以忽略.通过这种表示,读写每个小块上的每个面的颜色都是直接而方便的.但为了保证每个小块的各面颜色的关联,程序中不应直接操作每面颜色,而应通过定义良好的转动函数进行整体操作. 转动函数目的是为了提供一种直观的操作接口,供用户手动操作魔方和自动求解算法使用.接口形式如下:v oid R otate (Faces face ).其中,Faces 为枚举类型enmu Faces ={A ,B ,U ,D ,L ,R}.表示将相应的面顺时针转动90°. 然后根据流程图将算法用程序实现,并通过OpenG L 提供的三维绘图接口实时将魔方状态展示给用户,最终实现了游戏平台.软件运行界面如图9所示,可用鼠标右键平滑改变用户对魔方的观察角度,鼠标左键转动魔方的任意一层.软件仿真效果逼真,人机界面友好.任意状态下,可按‘A ’自动求解.图9 软件运行界面4 讨 论本软件提供了一个打乱魔方的函数,给用户生成一个初始混乱状态.此函数是通过随机转动魔方数次来实现的,并没有给出一个判断任意魔方状态是否为一可恢复状态的方法.但本文中提出的自动求解算法的所有循环语句,对于可解魔方而言,循环次数存在上界,故整个求解过程可在有限上界的循环次数之内完成.对于不可解魔方状态,则求解过程陷入死循环,所以可以通过设定循环次数上界的办法动态判断魔方是否可解,也可由此防止死循环.参考文献:[1]贲可荣,陈火旺.计算机求解魔方算法[J ].计算技术与自动化,1992,11(3):31-37.[2]W OO M.OpenG L Programming G uide [M].Third Edition.[s.l.]:Addis on 2Wesley ,1999.(编辑 王小唯)・598・第7期何智勇,等:基于OpenG L 的魔方自动求解算法与实现。

任务书

任务书

一、课程设计名称课程设计名称为“基于OpenGL的3D旋转魔方实现”。

当前计算机游戏很流行,作为计算机编程的初学者,设计开发一个基于windows操作系统的小游戏一方面可以提高编程水平,另一方面培养了学生兴趣和动手能力。

在实际生活中我们常玩“魔方体”的智力游戏,通过这个游戏可锻炼我们的空间定位和记忆能力。

如何把这个日常生活中的魔方体变成在计算机中可旋转的魔方体,一定能让很多感到兴趣,这就是我们课程设计的内容。

二、设计目的和要求目的:开发一个计算机OpenGL 3D小程序,实现日常生活中2X2魔方体旋转。

要求:利用Visual C++ 6.0 & OpenGL开发工具,编写一个魔方体旋转模拟显示程序。

三、时间计划(进度安排)计划可分为三个阶段:前期:学习Visual C++ 6.0 & OpenGL开发工具和复习C语言相关知识,掌握OpenGL Win32程序开发流程和框架。

(本学期第五周周三提交总结报告)中期:编写一个Win32下OpenGL开发的旋转立方的程序,实现纹理贴图。

(第十周周三提交总结报告)末期:完成2X2三维魔方体,优化程序结构和功能。

(第十五周周三提交总结报告)每个学生需要提交自己的编写阶段性课程设计报告,作为各人成绩考核依据。

四、课程设计报告要求1、内容格式要求,设计分为六个部分:●程序设计要求和描述●程序设计内容●程序实现过程和关键算法、●程序调试和测试●实践体会和心得●关键程序代码(作为附件,不得作为报告正式内容,否则扣分)2、格式要求终期设计报告需要有封面、目录、页码。

封面有课程设计题目、单位、班级、学号、姓名、指导教师、设计周数,成绩,日期和联系方式等。

报告总页数不得少于10页。

关键算法和流程需配图形说明描述。

3、提交要求⏹初期报告由组长提交一份;⏹中期每人一份;⏹末期报告每人一份,另外将报告、代码(去掉debug目录)压缩成一个rar文件,以“专业+学号+姓名”作为文件名提交。

openGL利用顶点数组旋转立方体以及程序

openGL利用顶点数组旋转立方体以及程序
• void key(unsigned char k,int x,int y) • { • if(k=='1')glutIdleFunc(spinCube);
• if(k=='2')glutIdleFunc(NULL); • if(k=='q')exit(0); • } • void main(int argc, char **argv)//主函数 • { • glutInit(&argc, argv); • glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);//设置模式 • glutInitWindowSize(500, 500);//窗口大小 • glutCreateWindow("colorcube"); • glutReshapeFunc(myReshape);//注册重画回调 • glutDisplayFunc(display);//三个回调函数(显示回调) • glutIdleFunc(spinCube); • glutMouseFunc(mouse); • glEnable(GL_DEPTH_TEST);//启用隐藏-面-消去



• • • • • •
glEnableClientState(GL_COLOR_ARRAY);// 调用颜色数组 glEnableClientState(GL_VERTEX_ARRAY);// 调用顶点数组 glVertexPointer(3,GL_FLOAT,0,vertices);//定 点数组变量存放格式 //参数意义:三维对象的颜色,顶点浮点数据类 型,数据元素间隔为0连续存放,数组指针 glColorPointer(3,GL_FLOAT,0,colors);//颜色 数组变量存放格式 glClearColor(1.0,1.0,1.0,1.0); glColor3f(1.0,1.0,1.0); glutMainLoop(); }
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

华中科技大学电子科学与技术系课程设计报告( 2010-- 2011年度第 2 学期)名称:软件课程设计题目:基于OpenGL的3D旋转魔方实现院系:班级:学号:学生姓名:指导教师:设计周数:成绩:日期:年月日目录1.课程设计介绍............................................................................................ (2)1.1目的.............................................................................................................. (2)1.2内容.............................................................................................................. (2)1.3取得的成果 (2)2.程序分析..................................................................................................... (3)2.1 程序原理 (3)2.2 程序流程 (4)2.3 数据结构 (13)2.4 重要函数 (13)3.程序分析与结果演示 (16)3.1 成果演示 (16)3.2 程序分析 (17)4.出现过的问题 (18)5.心得和小节 (19)1.课程设计介绍1.1目的21世纪是高科技时代,是信息技术时代,而计算机技术无疑会引领各行各业,为我们带来一个全新的时代。

作为新世纪的接班人,我们必须拥有良好的计算机应用能力,才能跟上世界发展的大流,不至于在激烈的竞争中被淘汰。

而程序作为计算机的灵魂,因此编程能力对当代大学生来说至关重要。

通过本课程单元的学习,可以对软件工程项目从整体上有一个较清晰的了解和认识;可以提高自身软件编程能力,培养对计算机编程兴趣,培养良好的编程习惯。

同时编程时的态度和方法对我们今后的学习和工作也有重要影响。

所以整体看来软件课程设计这门课程提高了我们计算机使用水平,培养了我们良好的学习态度,对我们个人的发展而言有着重要的意义。

1.2 内容(1)巩固和加强c语言相关编程知识,学会用Visual C++6.0进行c语言编程。

(2)掌握程序设计流程和思想,模块化结构分析以及程序设计流程,初步培养需求分析、软件测试、调试的能力。

(3)掌握win32相关编程知识,了解windows程序内部运行机制。

(4)掌握OpenGL贴图技术原理与函数实现,掌握OpenGL几何的移动、旋转等模式变化的原理。

(5)掌握魔方图形构造原理,在掌握二阶魔方构造原理的基础上,构造出三阶魔方并实现其旋转。

1.3 取得的成果在理解和掌握老师所给的范例程序的基础上,借助Win32平台进行了一系列调试和学习,熟练掌握了Win32 Application开发流程。

同时也学习和了解了OpenGL的基本知识,掌握了一些OpenGL的重要技术与重要函数的使用,编写了一些简单的OpenGL程序。

在比较透彻的了解了二阶魔方的构造原理后,成功地构造出了三阶魔方,换上了自己班级同学的图片,并且在一个小立方体的六个面上贴上了不同的图片。

能够比较完美的实现三阶魔方各个层面的随机旋转,并且把窗口背景设置为红色。

为了使程序更加有趣,我在程序中导入了刘德华的《爱你一万年》这首歌,使魔方在旋转的同时能够播放歌曲。

除此之外,我还实现了一种三阶魔方自由移动的屏保效果:即三阶魔方在旋转的同时能够在屏幕内部自由移动,并且在边缘无限次的反弹。

在魔方平移的过程中同样可以通过四个方向键来控制魔方的移动。

当松开方向键后,魔方会继续按照先前的方式自由移动。

2.程序分析2.1 程序原理(1)OpenGLOpenGL是为Open Graphics Library的简称,它是3D绘图工业标准,广泛地应用于计算机3D绘图领域。

它是个专业的开放的3D程序接口,是一个功能强大,调用方便的底层3D图形库。

它独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植;OpenGL可以与Visual C++紧密接口,便于实现机械手的有关计算和图形算法,可保证算法的正确性和可靠性;它具有七大功能:建模、变换、颜色模式设置、光照和材质设置、纹理映射、位图显示和图象增强和双缓存动画功能。

OpenGL 使用简便,效率高。

本项目是在Visual C++6.0开发环境下,使用OpenGL函数库,绘制魔方并实现魔方贴图、随机旋转、以及键盘控制等功能。

采用基本图形的绘图函数及定位函数,添加相应纹理来实现魔方模型的绘制。

通过读取载入BMP 文件,应用纹理贴图技术来完成对魔方旋转面的处理。

通过OpenGL中对图形的旋转和平移函数来实现对魔方整体的旋转和平移。

(2)旋转在建立好空间三维模型后,要实现魔方体每一层面的旋转。

而魔方体每一层面的旋转归结于每一个小立方体的旋转。

每个小立方体的旋转又最终归结于每个点的旋转。

对于一个坐标为(x,y,z)的点,如果围绕z轴逆时针旋转角度为a,则旋转之后z坐标不变,x和y坐标分别变为x*cosa - y*sina,x*sina + y*cosa,如图1所示:图1这样,实现了每个点的旋转,针对每个立方体只需采用循环对8个点均采取旋转操作就可实现一个立方体的旋转。

(3)消息循环与定时器由于程序在运行时CPU只能执行一个任务,然而此项目中魔方在旋转的同时要实现平移,所以需要用到Win32中的定时器功能。

此程序中要用到的定时器的函数原型为:SetTimer(HWND hWnd ,UINT nIDEvent,UINT uElapse,TIMERPROC lpTimerFunc)HWND hWnd为窗口句柄,使程序和定时器建立联系,UINT nIDEvent 是定时器ID,用于区分不同的定时器;UINT uElapse为定时器触发周期,意味着多长时间执行一次;,TIMERPROC lpTimerFunc为该定时器执行时触发的函数。

所以控制好不同定时器的触发周期和触发函数,就能使魔方的各个层面的旋转和平移互不冲突。

2.2 程序流程(1)WinMain主函数WinMain主函数是所有Win32程序的入口点。

在WinMain函数里窗体的建立和消息循环,在消息循环中实现键盘、鼠标输入事件处理响应。

在本程序中,要创建Window窗体和构建OpenGL设备绘图环境。

Window窗体创建步骤:●窗体类注册:RegisterClass●设置显示分辨率:ChangeDisplaySettings●设置窗体大小:AdjustWindowRectEx●创建窗体:CreateWindowExOpenGL绘图环境搭建:●获取设备绘图环境(DC,DeviceContext):hDC=GetDC(hWnd)●选择绘图环境像素格式:ChoosePixelFormat(hDC,&pfd),其中pfd为像素格式描述符,如果设置不对,OpenGL绘图失败,看不到正确的显示结果。

●设置绘图环境像素格式:SetPixelFormat(hDC,PixelFormat,&pfd)●获取OpenGL绘图环境:hRC =wglCreateContext(hDC)●设置OpenGL绘图环境:wglMakeCurrent(hDC,hRC)(2)三维建模一个三阶魔方体由27个小立方体构成,每个小立方体由8个顶点组成,而每个顶点又有x,y,z三个方向上的坐标值。

这样由结构体的层层嵌套就可以对魔方体的每个小立方体、每个顶点进行操作。

typedef struct{GLfloat p[3]; //定义一个点的x,y,z 坐标值}stPoint;typedef struct{stPoint CubePoint[8];//定义一个小立方体的8个顶点}stCube;如图2:0(-1.0f, -1.0f, 1.0f)(1.0f, -1.0f, 1.0f)3Y Y图2stCube Cube[27]; //定义魔方体的27个小立方体其中一个难点是怎样根据各个点的坐标值构造出魔方体,其实只要定义好每个顶点的坐标就行了。

但是三阶魔方必须定义27*8=216个顶点的坐标值,而且很难用for循环实现,因为各个顶点的x,y,z坐标值几乎没有什么规律。

但是如果能够将一个小魔方体作为一个整体来看待,工作量似乎会减轻很多。

先在整个魔方体中间定义一个基准小立方体,则整个魔方体的各个小立方体均可以通过这个基准立方体的平移来实现,各个小立方体上各点的平移向量和小立方体中心的平移向量相同。

static stPoint CubePoint[8]= //定义好基准小立方体,边长为1 { -0.5f, -0.5f, 0.5f}, //0 --{ 0.5f, -0.5f, 0.5f }, //1{0.5f, 0.5f, 0.5f }, //2 --{-0.5f, 0.5f, 0.5f}, //3{-0.5f, -0.5f, -0.5f}, //4 --{-0.5f, 0.5f, -0.5f}, //5{0.5f, 0.5f, -0.5f}, //6 --{0.5f, -0.5f, -0.5f}, //7};基准小立方体平移得到一个小立方体Cube[0]:for(int i=0;i<8;i++){Cube[0].CubePoint[i].p[0] = CubePoint[i].p[0] + 1.0f;Cube[0].CubePoint[i].p[1] = CubePoint[i].p[1] - 1.0f;Cube[0].CubePoint[i].p[2] = CubePoint[i].p[2] - 1.0f;}其他26个立方体可通过同样的方法得到。

我认为这是整个程序中最难也是最麻烦的一点。

本程序是通过reset_model()这一函数来构造出整个魔方体的。

(3)OpenGL贴图实现glGenTextures(1, &texture[i]),作用是利用载入的图像生成纹理。

glTexCoord2f(GLfloat s, GLfloat t) 函数用于绘制图形时指定纹理的坐标。

第一个参数是X坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是纹理的右侧。

第二个参数是Y坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部。

为了将纹理正确的映射到四边形上,必须将纹理的四个角与四边形的四个角相对应。

相关文档
最新文档