欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > DOC文档下载  

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

    • 资源ID:4006978       资源大小:480.50KB        全文页数:21页
    • 资源格式: DOC        下载积分:16金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要16金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

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

    华中科技大学电子科学与技术系课程设计报告( 2010- 2011年度第 2 学期)名 称: 软件课程设计 题 目: 基于OpenGL的3D旋转魔方实现 院 系: 班 级: 学 号: 学生姓名: 指导教师: 设计周数: 成 绩: 日期: 年 月 日目 录1.课程设计介绍. 21.1目的. 21.2内容. 21.3取得的成果22.程序分析. 32.1 程序原理32.2 程序流程42.3 数据结构132.4 重要函数133.程序分析与结果演示16 3.1 成果演示16 3.2 程序分析174.出现过的问题185.心得和小节191.课程设计介绍 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窗体创建步骤:l 窗体类注册:RegisterClassl 设置显示分辨率:ChangeDisplaySettingsl 设置窗体大小:AdjustWindowRectExl 创建窗体:CreateWindowExOpenGL绘图环境搭建:l 获取设备绘图环境(DC,DeviceContext):hDC=GetDC(hWnd)l 选择绘图环境像素格式:ChoosePixelFormat(hDC,&pfd),其中pfd为像素格式描述符,如果设置不对,OpenGL绘图失败,看不到正确的显示结果。l 设置绘图环境像素格式:SetPixelFormat(hDC,PixelFormat,&pfd)l 获取OpenGL绘图环境:hRC =wglCreateContext(hDC)l 设置OpenGL绘图环境:wglMakeCurrent(hDC,hRC)(2)三维建模一个三阶魔方体由27个小立方体构成,每个小立方体由8个顶点组成,而每个顶点又有x,y,z三个方向上的坐标值。这样由结构体的层层嵌套就可以对魔方体的每个小立方体、每个顶点进行操作。typedef struct GLfloat p3; /定义一个点的x,y,z坐标值stPoint;typedef struct stPoint CubePoint8;/定义一个小立方体的8个顶点stCube;如图2: 图2 stCube Cube27; /定义魔方体的27个小立方体其中一个难点是怎样根据各个点的坐标值构造出魔方体,其实只要定义好每个顶点的坐标就行了。但是三阶魔方必须定义27*8=216个顶点的坐标值,而且很难用for循环实现,因为各个顶点的x,y,z坐标值几乎没有什么规律。但是如果能够将一个小魔方体作为一个整体来看待,工作量似乎会减轻很多。先在整个魔方体中间定义一个基准小立方体,则整个魔方体的各个小立方体均可以通过这个基准立方体的平移来实现,各个小立方体上各点的平移向量和小立方体中心的平移向量相同。static stPoint CubePoint8= /定义好基准小立方体,边长为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,/50.5f, 0.5f, -0.5f,/6 -0.5f, -0.5f, -0.5f,/7; 基准小立方体平移得到一个小立方体Cube0:for(int i=0;i<8;i+)Cube0.CubePointi.p0 = CubePointi.p0 + 1.0f;Cube0.CubePointi.p1 = CubePointi.p1 - 1.0f;Cube0.CubePointi.p2 = CubePointi.p2 - 1.0f;其他26个立方体可通过同样的方法得到。我认为这是整个程序中最难也是最麻烦的一点。本程序是通过reset_model()这一函数来构造出整个魔方体的。(3)OpenGL贴图实现glGenTextures(1, &texturei),作用是利用载入的图像生成纹理。glTexCoord2f(GLfloat s, GLfloat t) 函数用于绘制图形时指定纹理的坐标。第一个参数是X坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是纹理的右侧。第二个参数是Y坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部。为了将纹理正确的映射到四边形上,必须将纹理的四个角与四边形的四个角相对应。否则图形在四边形上显示时将会有错误。如果要将一张格式合格的图片(采用的是256*256的图片)贴到正方体的一个面上,则需要联合使用glTexCoord2f和glVertex3f函数,如下:glBegin(GL_QUADS);/ 发布四边形绘图指令glTexCoord2f(0.0f, 0.0f); glVertex3fv( CubePoint0.p); glTexCoord2f(1.0f, 0.0f); glVertex3fv( CubePoint1.p);glTexCoord2f(1.0f, 1.0f); glVertex3fv( CubePoint2.p);glTexCoord2f(0.0f, 1.0f); glVertex3fv( CubePoint3.p);这样可以用同样的方法在其他5个面贴上相应的纹理图。这样就可以得到6个面均贴好纹理图的小立方体。glBindTexture是OpenGL核心函数库中的一个函数。作用是选择生成的纹理。glBindTexture(GL_TEXTURE_2D,texturei),作用是选择生成的纹理。将texture1中的图片纹理绑定到程序中,然后就可以画出6个面均是该纹理的小立方体。这样画出的小立方体的六个面上的图片是相同的。以此类推,便可画出其他的小立方体。而我在该程序中实现了将小立方体的六个面贴上不同的图片,原理与上面类似。只需要在给每个面贴图片时都载入不同的纹理即可。OpenGL贴图具体流程如下: 图3(4)魔方整体旋转和平移OpenGL中有给定的函数来实现图形的旋转和平移:glTranslatef和glRotatef。其中,glTranslatef用于平移和确定图形在界面上的位置。glTranslatef(x,y,z)作用是将图形平移到坐标为(x,y,z) 的点。其中,x,y分别为屏幕横向和纵向。z轴为垂直屏幕方向,沿屏幕向外为正方向。屏幕中心默认坐标为(0,0,0)。glRotatef函数控制魔方整体的旋转。如glRotatef(xrot,1.0f,0.0f,0.0f); 控制魔方围绕向量为(1,0,0)的直线(即x轴)旋转 xrot角度。控制魔方整体绕y轴和z轴的旋转可以用同样的方法实现。综合以上分析结果,便可以写出控制有纹理贴图的一阶立方体的旋转程序。程序运行效果如下图4: 图4(5)魔方各个层面的随机旋转和同步更新索引27个立方体构成3X3魔方矩阵,对每个立方体进行编号。魔方体某层的旋转是基于选中的9个立方体绕魔方体的中心轴变化的。由此定义魔方体每个层面包含的子立方体集合初始索引编号:const BYTE SZP9 = 0,1,2,3,4,5,6,7,8; const BYTE SZS9 = 9,10,11,12,13,14,15,16,17; const BYTE SZM9 = 18,19,20,21,22,23,24,25,26; const BYTE SYM9 = 0,1,2,11,10,9,18,19,20;const BYTE SYS9 = 3,4,5,14,13,12,21,22,23; const BYTE SYP9 = 6,7,8,17,16,15,24,25,26;const BYTE SXM9 =2,3,8,17,12,11,20,21,26;const BYTE SXS9 =1,4,7,16,13,10,19,22,25;const BYTE SXP9 = 0,5,6,15,14,9,18,23,24;预定义好这些层面目的是确定好旋转前后各个子立方体的相对位置。为了记录魔方体旋转之后各子立方的绝对位置,为此专门定义了同上类似的数组结构:BYTE ZP9 = 0,1,2,3,4,5,6,7,8; BYTE ZS9 = 9,10,11,12,13,14,15,16,17; BYTE ZM9 = 18,19,20,21,22,23,24,25,26; BYTE YM9 = 0,1,2,11,10,9,18,19,20; BYTE YS9 = 3,4,5,14,13,12,21,22,23; BYTE YP9 = 6,7,8,17,16,15,24,25,26; BYTE XM9 =2,3,8,17,12,11,20,21,26; BYTE XS9 = 1,4,7,16,13,10,19,22,25; BYTE XP9 = 0,5,6,15,14,9,18,23,24; 魔方体几何位置旋转本质上就是同步更新各层面内的小立方的索引表。如,更新z方向上的第一层的小立方的索引表的部分代码如下:for( i=0;i<27;i+)for( j=0;j<9;j+)if( is_equal( &Cubei, &Static_Cube SZMj ) ZMk+ = i;is_equal()是判断旋转后的魔方体Cube的那些子立方Cubei与静态的魔方体Static_Cube的SZM层面内的子立方重合,找出之后作为ZM的新成员。最终能找到9个子立方作为新成员。而在前面已经讨论了如何实现立方体围绕某个轴旋转的问题。对某一层面内的9个小立方体均进行旋转操作,然后进行更新索引,就可以得到旋转之后的魔方体。在本程序中我定义了Rotate_XM(),Rotate_XS(),Rotate_XP(),Rotate_YM(),Rotate_YS(),Rotate_YP(),Rotate_ZM(),Rotate_ZS(),Rotate_ZP()这9个函数,分别控制各个层面的旋转。由于魔方体各个方向上不同层面不能同时旋转,所以要在程序中保证各个层面之间的旋转互不冲突。在本程序中我定义了enable_XM_roatate(),enable_XS_roatate(),enable_XP_roatate(),enable_YM_roatate(),enable_YS_roatate(),enable_YP_roatate(),enable_ZM_roatate(),enable_ZS_roatate(),enable_ZP_roatate()这9个函数,用于判断某一方向上某一层面是否可以旋转。并且设置了rotX,rotY,rotZ三个全局变量。在以上9个函数中分别对这3个变量之一进行赋值。在enable_XM_roatate(),enable_XS_roatate(),enable_XP_roatate()三个函数中分别将rotX赋值为1,2,3,在enable_YM_roatate(),enable_YS_roatate(),enable_YP_roatate()三个函数中分别将rotY赋值为1,2,3,在enable_ZM_roatate(),enable_ZS_roatate(),enable_ZP_roatate()三个函数中分别将rotZ赋值为1,2,3,同时保证rotX,rotY,rotZ一次只有一个不为零,这样就保证了各个层面旋转之间互相不冲突。(6)背景音乐的添加我在该程序中载入了背景音乐,方法比较简单。#include<mmsystem.h> /提供与多媒体有关的接口#pragma comment(lib, "WINMM.LIB") /导入winmm.lib库,实现对多媒体编程的支持在所建工程的文件夹中新建名为sound的文件夹,并在其中放入wav格式的音乐爱你一万年。编写函数loadsound(),其调用函数PlaySound("sound爱你一万年.wav",NULL,SND_LOOP|SND_ASYNC|SND_FILENAME)加载爱你一万年背景音乐。(7)定时器的调用我认为本程序中使用Win32系统的定时器很关键,因为程序只能一次执行一个线程,而魔方在自身旋转的同时还有各个层面的自由随机旋转,还加上自身的平移等,所以必须用到定时器。在本程序中我用到了3个定时器::SetTimer(hWnd,1,2,NULL),:SetTimer(hWnd,2,1,TimerProc),:SetTimer(hWnd,3,0.5,CubeWalk)。定时器:SetTimer(hWnd,1,2,NULL)的作用是把把其产生的消息加入消息队列中,由WM_TIMER接收并处理,以实现立方体的旋转。定时器:SetTimer(hWnd,2,1,TimerProc)的回调函数是TimerProc。函数TimerProc用来产生随机数。要控制各个层面的随机旋转,一共有18种情况,包括每个方向上每个层面上的正转和反转。故在TimerProc函数中对随机数的情况进行判断:int r = rand(); if( r%18=0)enable_XM_roatate(1);以上是18中情况中的一种,使魔方的XM层能够旋转,即在enable_XM_roatate(1)中进行如下赋值:rotAngle = 1 rotCount = 0 rotX = 1 rotDirect =1在WM_TIMER中判断rotX,rotY,rotZ的值并进行相应的旋转操作。本程序中的另外一个定时器:SetTimer(hWnd,3,0.5,CubeWalk)作用是控制魔方的平移。前面已经介绍了魔方自身的平移函数glTranslatef。在程序的最开始定义变量RX和RY,glTranslatef(RX,0.0f,0.0f);glTranslatef(0.0f,RY,0.0f);则RX和RY代表魔方中心的横纵坐标。在回调函数CubeWalk中对RX和RY值进行处理和改变就可以控制魔方的平移了。定时器的使用及其控制魔方的旋转和平移流程图如图5: 图5 定时器使用流程图2.3 数据结构分析 在本程序中为了很好的表示一个魔方体并且便于更好地计算,采用结构体和数组层层嵌套的形式。定义一个点的结构体,由3个坐标值构成: typedef struct GLfloat p3; stPoint;定义一个立方体的结构体,由8个顶点构成:typedef struct stPoint CubePoint8; stCube;定义由27个小立方体构成的数组:stCube Cube27; 2.4 重要函数分析 (1)窗口创建 程序中的函数GLvoid resizeScene(GLsizei width,GLsizei height )目的是重置OpenGL窗口的大小,具体又包含以下几个函数: glViewport(0,0,width,height)是OpenGL中的视口变化函数,作用是把视景体截取的图像按照怎样的高和宽显示到屏幕上。 glMatrixMode():指定哪一个矩阵是当前矩阵。glMatrixMode设置当前矩阵模式:GL_MODEVIEW,对模型视景矩阵堆栈应用随后的矩阵操作。GL_PROJECTION,对投影矩阵应用随后的矩阵操作。 glLoadIdentity()将矩阵清为单位矩阵,避免受其它矩阵操作的干扰,作用是将当前的用户坐标系的原点移到屏幕中心。 gluPerspective的作用是设置透视投影矩阵,即越远的东西看起来越小的效果。gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f)45.0f表示将视角设置为45度,(GLfloat)width/(GLfloat)height表示窗口的纵横比,0.1f表示沿z轴方向的两裁面之间的距离的近处为0.1,100f表示沿z轴方向的两裁面之间的距离的远处为100,即图像在z轴方向上的坐标必须介于-0.1到-100之间,否则无法显示出来。(2)初始化在InitGL(GLvoid)中对窗体进行初始化效果:glShadeModel(GL_SMOOTH)作用是启用阴影平滑。glClearColor(0.5f, 0.0f, 0.0f, 0.5f)作用是设置背景为红色。glClearDepth(1.0f),作用是设置深度缓存。glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST),作用是做精细的透视修正。loadsound(),作用是导入歌曲爱你一万年。(3)OpenGL贴图 glGenTextures(1, &texturei),作用是利用载入的图像生成纹理。glBindTexture(GL_TEXTURE_2D, texturei),作用是选择生成的纹理。glTexCoord2f(0.0f,0.0f),作用是设置纹理坐标。glVertex3fv( CubePoint0.p),作用是设置对应的立方体的顶点坐标。glEnable(GL_TEXTURE_2D),作用是启用纹理映射,此点很关键。 如果不用这个函数,图片将不能贴到立方体的六个面上。(4)旋转和平移在本程序中用到了OpenGL中的平移函数glTranslatef(x,y,z)和旋转函数。glTranslatef(x,y,z)表示图形中心平移到坐标为(x,y,z)的点处。与其类似,glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)表示图形绕经过原点和点(x,y,z)的轴旋转角度angle。方向满足右手定则。而本程序中控制魔方层面旋转的函数前面已经介绍过,一共有9个函数,分别控制三个方向上各三个层面的旋转,旋转方向由全局变量rotDirect是1或-1来决定。(5)消除累计误差为了避免魔方体层面的旋转之后带来的累计误差,在判断两个立方体是否重合时,必须消除这种累计误差。所以判断两个点是否重合时,如果两个点的三个坐标值均相差较小,应该令其分别相等,以消除误差。 if( fabs(x1 - x2)<1e-1 && fabs(y1-y2)<1e-1 && fabs(z1-z2)<1e-1) pc1->CubePointi.p0 = pc2->CubePointj.p0; pc1->CubePointi.p1 = pc2->CubePointj.p1;pc1->CubePointi.p2 = pc2->CubePointj.p2;(6)屏保函数控制魔方移动是通过定时器Timer3来实现的,而Timer3的回调函数为CubeWalk()。在该函数中,只要控制RX和RY的增减即可。RX和RY为全局变量,初值为零,所以魔方最初的位置是在屏幕的中心。RX+=0.1RY+=0.1就可以控制魔方每次向斜方向运动。为了实现魔方的反弹效果,需要另外定义两个全局变量turn_x和turn_y,初值分别为1。且令RX+=(turn_x*0.01)RY+=(turn_y*0.01)当魔方达到边界时,将turn_x和turn_y中的一个值取相反值,就可以使RX或RY反向增长,从而达到反弹的效果。经过试验,确定屏幕横向宽大致为16,纵向宽大致为8。而判断魔方达到边界时不能用“=”来进行判断,因为会有误差。为了消除误差,采用fabs()函数来进行一定范围内的判断。if(fabs(RX+8)<0.01|fabs(RX-8)<0.01)else if(fabs(RY+4)<0.01|fabs(RY-4)<0.01)3.程序分析与结果演示 3.1 成果展示3.2程序分析程序整体流程图分析如下:图6 程序整体流程图4.出现过的问题其实编程不可能一遍成功,我在编程的过程中也遇到了很多问题。(1)我开始将范例程序看懂之后,一气呵成将三阶魔方的程序编写出来了,但是写出来的程序只能控制三阶魔方的一部分层面旋转。于是我想实现三阶魔方任一层面随机旋转的效果,但是程序写完时候运行结果却出人意料之外。可以明显的看到魔方各个层面的旋转发生冲突,导致魔方产生扭曲。于是我仔细分析产生这种的原因,想了很久,后来想到会不会是写程序时控制各个层面的旋转的控制量的值有重复,从而产生冲突。然后我就把一个方向上的三个层面旋转的控制量的值改成不同的1,2,3,结果就可以正常运行了。(2)我在实现三阶魔方效果后,就想实现三阶魔方的自由反弹效果,我构思的算法自认为是对的,其实也比较简单,当时控制其反弹的源码如下:if(RX=-8|RX=8)turn_x=(-turn_x);else if(RY=-4|RY=4)turn_y=(-turn_y);RX+=(turn_x*0.01);RY+=(turn_y*0.01);但是实际运行效果就是与我预想的不一样。魔方到了边界,总是不反弹,径直的跑到屏幕外面去,不见了踪影。这个问题困扰了我很久,一直得不到解决。我曾经想过是不是与屏幕长宽表示错了有关,但是无论我把屏幕长宽设为多少,魔方总是不反弹。后来我偶然想到,会不会是因为定时器的执行周期太短,一次移动距离太短,产生了误差,所以到达边界时程序没有判断出来。于是我用了fabs函数,给RX和RY设定了一定的误差范围,程序竟然可以运行成功了。这说明我的假设是对的。所以以后碰到问题要认真思考,也许灵感就在一瞬间闪现。5 心得和小节 这段时间以来觉得自己收获还是挺大的。开始选这个课题是觉得三阶旋转魔方肯定比较有意思,看着也比较有挑战性。经过这段时间以来的学习,我加深了对三阶旋转魔方实现的认识,觉得这个课题的确是在我们的能力范围内,除了OpenGL的绘图知识比较陌生以外,其他的比如魔方的建模、控制魔方的旋转以及定时器的使用等函数或算法都是我们能力所能及的,当然这必须建立在有比较好的c语言基础上,能对c语言的数组、函数、指针及结构体有比较好的掌握。 其实编程是一个考验人耐心的事,有时候看着一个大型的程序,真有点无奈的感觉。当我对杨老师给的范例程序进行分析时,开始确实被吓着了,代码有一千多行。而里面又有很多函数,也不知道哪些是库函数,哪些是自定义的函数。但是万变不离其宗,程序再怎么复杂,也总会遵循一定的规律,也会最终被分析透彻。于是我开始逐行逐行的分析范例程序。遇到不懂的代码我就上网查资料,看老师给的指导书,然后再旁边加上我理解的注释。大概花了两三个半天的时间,就基本上把范例程序全部看懂了。全部看懂之后的那个晚上,我躺在床上就一直在想二阶旋转魔方的实现过程,并考虑如何用类似的算法实现三阶旋转魔方。第二天上午打开电脑,趁着思路比较清晰,我就开始在范例程序的基础上写三阶旋转魔方的程序,改了一些我认为应该修改的地方。这个过程还不是那么简单的,特别是构建魔方、计算魔方体顶点坐标时需要特别细致。修改的过程花了我一个多小时的时间。在修改完之后,我点了运行按钮,本来以为会有一大串error的,没想到竟然一次运行成功了,并且能够显示旋转的三阶魔方。当时真是欣喜若狂。因为这在我编程的经历中是很少出现的,说明了细致对编程的重要性。 有时编程会出现意想不到的错误,甚至都不知道错误在什么地方,也许就是那个地方的分号没写,就会有几个error。这时候就是考验人的细心和耐心的时候了。要沉得住气去找错误,解决错误,吸取教训。我想这种品质对我们今后的学习和工作有着重要的意义。没有十全十美的程序,也没有十全十美的人,只有不断学习,不断改进,才能不断完善。 在此感谢杨老师和帮助过我的同学,有了你们的帮助和指导,我在有些地方也少走了不少弯路,编写程序显得更为轻松和从容了。 总结我的程序,我也发现仍有很多不足,也是我接下来需要努力的方向。一、程序现在运行的不是很流畅,魔方层面旋转时会有一点卡。我也不知道是不是正常现象,能不能加以改进。二、程序运行的背景有点单调,我原本想在后面加上背景图片的,由于时间关系,我没有加图片。三、我现在的屏幕保护效果不是很令人满意,我想做成有很多小立方体在屏幕上自由反弹,相互碰撞的效果。虽然看起来有点难,但是我会继续研究这个程序,争取能够实现预期的效果。参考文献1(美)施瑞奈尔.OpenGL编程指南.第七版.2012年,第5次:第5页.2刘正林.周纯杰编著.最新c语言程序设计教程.武汉:华中科技大学出版社,20033谭浩强编著.c语言程序设计.北京:清华大学出版社,2002

    注意事项

    本文(基于OpenGL的3D旋转魔方实现汇总.doc)为本站会员(小飞机)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开