版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、华中科技大学电子科学与技术系课程设计报告( 2011- 2012年度第 2 学期)名 称: 软件课程设计 题 目: 基于OpenGL的3D旋转魔方实现院 系: XXXXXX 班 级: XXXXX 学 号: U201014185 学生姓名: X X X 指导教师: X X X 设计周数: XXXX 成 绩: 日期: 2012 年 5月 24日目 录1课程设计介绍 11.1.内容 1 1 12程序分析 2 2.1. 程序原理 22.1. 程序流程 3. 数据结构 8 2.4. 重要函数用法分析 83结果演示与程序分析 9. 成果演示 9. 程序分析 114编程中遇到的问题125课程设计小结13参考
2、文献14 基于OpenGL的3D旋转魔方实现课程设计介绍目的当今计算机技术流行,引领了各行各业。而程序是计算机的灵魂,因此编程能力对当今的学生而言至关重要。虽然我们在前期已经学习了C语言,但是还只对程序有一些简单的认识,说实话,是很浅显的认识。通过本软件课程设计的学习,可以从整体上对软件工程和项目有全面的认识。通过此次课程设计,可以锻炼编程能力,激发对编程的兴趣,同时也能培养良好的编程习惯。这对于个人今后的学习,今后的工作乃至今后的生活都会产生重要的影响。对于国家而言,极大的推动了计算机普及教育,提高了大学生的计算机使用水平,具有重大的意义。内容通过此次项目掌握软件开发模式,模块化结构分析以及
3、程序设计流程掌握有关程序设计的思想,数据结构的知识,掌握C语言算法,掌握OpenGL编程知识如贴图与键盘控制掌握win32编程知识,了解windows程序内部运行机制初步培养需求分析、软件测试、调试的能力在2X2魔方的基础上,尝试编写3X3的魔方,并实现其旋转取得的成果在理解Magic2D例子程序的基础上,借助了Win32平台进行了一系列调试和学习。在此次项目中,学习了Visual C+6.0软件开发环境,熟练掌握了Win32 Application开发流程。同时也学习了OpenGL的基本知识,掌握了一些OpenGL的重要技术与重要函数的使用,编写了一些简单的OpenGL程序。参考Magic2
4、D例子流程,我对原程序进行了比较大的修改,并换上了自己的图片,实现了一个立方体贴六张不同的图片,并编写出了自己的2X2魔方程序。根据相似度分析,成功的编写出了3X3旋转魔方,并自己设计了算法,实现了各个层面的转动,转动效果很完美。同时,为了增加程序的娱乐效果,我加入了歌曲最炫民族风,虽然很简单,不过感觉非常实用且有趣。程序分析2.1 程序原理 (1)OpenGLOpenGL是一个开放的三维图形 HYPERLINK :/baike.baidu /view/600107.htm t _blank 软件包,它独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植;OpenG
5、L可以与 HYPERLINK :/baike.baidu /view/100377.htm t _blank Visual C+紧密接口,便于实现机械手的有关计算和图形算法,可保证算法的正确性和可靠性;OpenGL使用简便,效率高。本设计是在环境下,使用OpenGL(Open Graphics Library)函数库,绘制魔方并实现魔方的绘制、随机旋转、贴图以及键盘控制等功能。采用基本图形的绘图函数及定位函数,添加相应纹理来实现魔方模型的绘制。通过读取载入BMP文件,应用纹理贴图技术来完成对魔方旋转面的处理。 (2)模型的旋转首先对立方体进行建模。一个立方体由8个点组成,8个点组成6个面片,对
6、立方体的几何操作本质上就是对这6个平面的操作(绘制、纹理、旋转和平移等)。点的索引号确定后,每个面片也就确定了,如0,1,2,3四个点构成Z向正投影面。立方体在空间的旋转,归根到底是其顶点的旋转,如空间点(x, y, z)绕Z轴旋转a对应的旋转矩阵:cosa sina-sina cosa一个立方体pCube绕Z轴旋转a后对应的坐标变化为:for( int i=0;iCubePointi.p0; y= pCube-CubePointi.p1; pCube-CubePointi.p0 = x*cosa - y*sina; pCube-CubePointi.p1 = x*sina + y*cosa;
7、其它轴的旋转类似。由于魔方体层面的旋转是90,在某个层面内一个子立方体Ci会被另外一个Cj完全替换,因此旋转后必须同步更新魔方体Cube各层面内包含的子立方的索引号。为了简化算法,只需查找旋转后Cubei在Static_Cube中对应的小立方编号j与i的位置匹配。 2.2 程序的流程 通过分析,整个程序大致可以分为6个子功能模块Win32应用程序框架WinMain主函数是所有Win32程序的入口点。在WinMain函数里实现Window是窗体的建立和消息循环,在消息循环中实现键盘、鼠标输入事件处理响应,具体内容可参考VC程序参考手册。在本课程程序中,不仅要创建Window窗体,而且构建Open
8、GL设备绘图环境。 Window窗体创建步骤:窗体类注册:RegisterClass设置显示分辨率:ChangeDisplaySettings设置窗体大小:AdjustWindowRectEx创建窗体:CreateWindowExOpenGL绘图环境搭建: 获取设备绘图环境(DC,DeviceContext):hDC=GetDC(hWnd) 选择绘图环境像素格式:ChoosePixelFormat(hDC,&pfd),其中pfd为像素格式描述符,如果设置不对,OpenGL绘图失败,看不到正确的显示结果。 设置绘图环境像素格式:SetPixelFormat(hDC,PixelFormat,&pf
9、d) 获取OpenGL绘图环境:hRC =wglCreateContext(hDC) 设置OpenGL绘图环境:wglMakeCurrent(hDC,hRC)(2)空间建模得到3阶魔方 显然,要建立3X3的魔方必须首先建立单个魔方的模型,然后通过对单个立方体进行平移从而得到3X3的魔方。 平移单个立方体通过reset_model( )函数中的语句实现 for(i=0;i8;i+)Cube0.CubePointi.p0 = CubePointi.p0-2.0f ;Cube0.CubePointi.p1 = CubePointi.p1-2.0f ;Cube0.CubePointi.p2 = Cub
10、ePointi.p2+2.0f;上述代码只得到了编号为0的立方体,其他编号的立方体同理可以得到构成2X2的魔方需要8个立方体,构建3X3的魔方则需要27个立方体。根据2阶魔方的一些方法,类比到3阶魔方。则首先对魔方的立方体进行编号,然后通过编号得到魔方各层所包含立方体的编号。其中编号为BYTE ZP9 = 0,1,2,3,4,5,6,7,8; /z轴方向正向一层BYTE ZZ9 = 9,10,11,12,13,14,15,16,17; /z轴方向中间一层BYTE ZM9 = 18,19,20,21,22,23,24,25,26; /z轴方向负向一层BYTE YM9 = 0,1,2,11,10,
11、9,18,19,20; /y轴方向负向一层BYTE YZ9 = 3,4,5,14,13,12,21,22,23; /y轴方向中间一层BYTE YP9 = 6,7,8,17,16,15,24,25,26; /y轴方向正向一层BYTE XM9 = 2,3,8,17,12,11,20,21,26; /x轴方向正向一层BYTE XZ9 = 1,4,7,16,13,10,19,22,25; /x轴方向中间一层BYTE XP9 = 0,5,6,15,14,9,18,23,24; /x轴方向负向一层(3)OpenGL纹理贴图以下是纹理贴图的流程,其中实现了一个立方体贴六张图片 GLuint texture6
12、创建纹理存储AUX_RGBImageRec* TextureImage6; 创建纹理的存储空间 TextuteImagei=auxDIBImageLoad(“picture/y1.bmp)调用此函数六次载入六张不同的图片glGenTexTures(1,&texturei)用载入的图像生成六个纹理glBindTextures(GL_TEXTURE_2D,texturei选择生成的纹理glBegin(GL_QUADS);glTexCoord(0.0f,0.0f);glVertex3fv(CubePoint0.p);glEnd();每次选择不同的纹理,然后利用OpenGL是状态机的性质,可以给每个面
13、贴上不同的图片(4)同步更新索引在整个程序中,同步更新索引所涉及到的算法可以算是最核心的了。当然,你也可以让每层每个周期转动360度,这样就不需要动态更新索引了,因为每次转动前后,立方体的相对坐标位置并没有改变。但是这样得到的旋转效果并不好,因为这并没有考虑到魔方旋转的所有情况,每次旋转后魔方都没有被打乱。由于涉及到动态刷新索引,于是按照常理定义一个静态的魔方与动态的魔方进行比较。类似动态魔方的编号可以得到静态魔方的编号。const BYTE SZP9 = 0,1,2,3,4,5,6,7,8; /z轴方向正向一层const BYTE SZZ9 = 9,10,11,12,13,14,15,16,
14、17; /z轴方向中间一层const BYTE SZM9 = 18,19,20,21,22,23,24,25,26; /z轴方向负向一层const BYTE SYM9 = 0,1,2,11,10,9,18,19,20; /y轴方向负向一层const BYTE SYZ9 = 3,4,5,14,13,12,21,22,23; /y轴方向中间一层const BYTE SYP9 = 6,7,8,17,16,15,24,25,26; /y轴方向正向一层const BYTE SXM9 = 2,3,8,17,12,11,20,21,26; /x轴方向正向一层const BYTE SXZ9 = 1,4,7,1
15、6,13,10,19,22,25; /x轴方向中间一层const BYTE SXP9 = 0,5,6,15,14,9,18,23,24; /x轴方向负向一层然后编写一个函数int is_equal(stCube *pc1,stCube *pc2)判断两个立方体是否重合,这个函数的算法就是比较立方体所有顶点的坐标是否相同。最后一步编写函数void Update_Cube_index(),由于魔方转动情况总体上有九种情况,则该函数必须编写九块功能类似的代码,现在只列出X轴负向一层刷新索引的算法。int i,j,k=0;k =0 ;for( i=0;i9;i+) for( j=0;j27;j+) i
16、f( is_equal( &Cubej, &Static_Cube SZMi ) )ZMk+ = j; (5)魔方的旋转以及键盘控制对魔方的平移魔方层面的旋转已经在前面介绍,此处除了层面旋转还有魔方的整体旋转。只需调用库函数即可即可。glRotatef(xrot,1.0,0.0,0.0); /使魔方绕x轴转动xrot度glRotatef(yrot,0.0,1.0,0.0); /使魔方绕y轴转动yrot度glRotatef(zrot,0.0,0.0,1.0); /使魔方绕z轴转动zrot度(6)定时器对魔方层面旋转的控制 为了控制魔方的转动,首先定义了函数void enable_X_roatat
17、e(int direction),void enable_Y_roatate(int direction),void enable_Z_roatate(int direction)以确定旋转轴和旋转方向,同时定义了void Rotate_X(int ii),void Rotate_Y(int ii),void Rotate_Z(int ii)来指定是哪一层的旋转。然后定义两个计时器Time1和Time2,其中Timer1的消息由WM_TIMER接收并处理,以实现立方体的旋转。Timer2的消息由TimerProc函数处理,用于生成控制量以控制旋转轴和旋转方向。流程如图:魔方的层面旋转r除6得到
18、控制参数r=rand()得到随机数rTimer2cs除3的余数得到控制参数Timer1实现旋转cs=rand()得到随机数cs(7)背景音乐的添加 为了程序有更丰富的效果,我添加了歌曲最炫民族风,方法也很简单。 #include /提供与多媒体有关的接口 #pragma comment(lib, WINMM.LIB) /导入winmm.lib库,实现对多媒体编程的支持 编写函数loadsound(),其调用函数PlaySound(sound最炫民族风.wav,NULL,SND_LOOP|SND_ASYNC|SND_FILENAME)加载最炫民族风味背景音乐。(8)窗口文字的添加 为了添加自己的
19、信息,我在程序窗口中加了文字void drawString(const char* str),实现添加英文字符。void drawCNString(const char* str)实现添加中文字符void selectFont(int size, int charset, const char* face),实现变换字体 2.3 数据结构本程序定义了记录魔方体每个小块编号的数组Cubei及相应的定态数组Static_Cube,用来对魔方体变化过程中的相对位置进行索引及重新定位。定义了立方体记录顶点位置的数组CubePointi及相应静态数组stPoint CubePointi,用来确定魔方体的
20、旋转,因为旋转归根结底是其顶点位置的旋转。定义了用来记录魔方体各个面上子块编号的数组ZP/ZZ/ZM,YP/YZ/YM,XP/XZ/XM,及其对应静态数组。定义了数组TextureImagei来接收纹理。 2.4 重要函数用法分析(1)窗口创建GLvoid resizeScene(GLsizei width,GLsizei height )这个函数的目的是重置OpenGL窗口的大小,具体又包含以下五个函数glViewport(0,0,width,height);glViewport是OpenGL中视口变化函数,根据窗口的实时变化重绘窗口,它负责把视景体截取的图像按照怎样的高和宽显示到屏幕上。g
21、lMatrixMode(GL_PROJECTION)、glMatrixMode(GL_MODELVIEW) 这两个函数原型都是glMatrixMode函数。glMatrixMode这个函数其实就是要指定操作的是哪种矩阵。如果参数是GL_PROJECTION,这个是投影的意思,如果参数是GL_MODELVIEW,这个是对模型视景的操作,用于对三维场景中坐标系的变换操作。glLoadIdentity()glLoadIdentity该函数的功能是将当前的用户坐标系的原点移到了屏幕中心,就像一个复位操作gluPerspective(45.0f,(GLfloat)width/(GLfloat)heigh
22、t,0.1f,100.0f)gluPerspective的作用是设置透视投影矩阵,意味着越远的东西看起来越小。45.0f表示将视角设置为45度,(GLfloat)width/(GLfloat)height沿z轴方向的两裁面之间的距离的近处为0.1,100f表示沿z轴方向的两裁面之间的距离的远处为100 (2)初始化操作 glShadeModel(GL_SMOOTH),作用是启用阴影平滑。 glClearColor(, , , ),作用是将背景设置为黑色。 glClearDepth(),作用是设置深度缓存。 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NIC
23、EST),作用是做精细的透视修正。 loadsound(),作用是导入歌曲最炫民族风。 (3)OpenGL贴图 glGenTextures(1, &texturei),作用是利用载入的图像生成纹理。 glBindTexture(GL_TEXTURE_2D, texturei),作用是选择生成的纹理。 glTexCoord2f(,),作用是设置纹理坐标。 glEnable(GL_TEXTURE_2D),作用是启用纹理映射,此点很关键。 (4)平移与旋转 glTranslatef(x, y, z) 平移函数。表示相对于当前所在的屏幕位置沿着 X, Y 和 Z 轴移动x,y和z个单位。glRotat
24、ef(angle, x, y, z)旋转函数。与glTranslatef(x, y, z)类似,glRotatef(angle, x, y, z)也是对坐标系进行操作。旋转轴经过原点,方向为(x,y,z),旋转角度为angle,方向满足右手定则。(5)添加窗口文字void drawString(const char* str),实现添加英文字符。void drawCNString(const char* str)实现添加中文字符void selectFont(int size, int charset, const char* face),实现变换字体结果演示与程序分析魔方体旋转对魔方定位对魔
25、方进行编号程序分析纹理绑定循环调用生成纹理 3X3魔方有27个小块,对每个小块分别进行编号。先画出一个子块,经过向相应方向的平移,获得完整的魔方体。 魔方由函数glTranslatef(float x,float y,float z)定位,再由函数glRotate(float angle,float x,float y,float z)进行旋转,然后由函数glBindTexture(GLenum target,GLunit textureName)进行纹理与相应面的绑定(纹理已由glGenTextures()函数来产生),最后再用函数glBegin(GL_QUADS)画出正方面,从而描绘出了魔
26、方的一个小面。循环调用就可以绘制出的魔方。循环调用程序的纹理绑定和旋转过程就实现了魔方体的旋转变化。4.编程中遇到的问题 在对2X2魔方理解的基础上,我经过自己的摸索终于在末期做出了自己的3阶魔方。其中,遇到了很多问题,不过都被我解决了。以下是我认为的比较重要的问题(1)在编写判断两个立方体是否重合的函数时,开始我没有消除累计误差。说实话,当时我对这个程序并不是很了解。没有加入这个功能,程序运行结果如下:刚开始时还比较正常,运行一段时间后,魔方错位了。想了很久,看了指导书才知道原来还差消除累计误差这个功能。其实,这也很好解释。因为我们编写的旋转函数涉及到计算cosa以及sina的值,而计算机计
27、算这些值是不是很准确的。在一个旋转周期中,要计算180次cosa和sina的值,因此误差会被放大,则消除累计误差成了必须。只需判断两个数在一定误差范围内相等即可。 (2)魔方循环控制算法的设计中,我遇到了前所未有的问题。单独编写控制最外面一层或是中间一层旋转的函数确实比较简单,但是如何实现一个实现外层和中间一层同时都可旋转的魔方还是很有难度的,这涉及到如何合理调度的问题。在多方调试后,我想到了一个很好的算法,就是再引入一个控制变量cs,可是变量应该选择在哪里赋值呢?刚开始我毫不犹豫的就选择在TimerProc函数里面赋值,可是一下子就出错了。后来我将Timer2的定时时间设置为1800ms,目
28、的是等于Timer1的180倍,以实现转一个周期cs重新赋值一次,可结果表明我再次错了。因为转动的延迟,所以转动一个周期所需时间是不定的,但肯定不等于1800ms。在重新阅读一遍程序后,我发现在void Rotate_ZM()函数中有转动一个周期后的初始化操作,受到启发后,我于是将cs的赋值移到了这个函数中,运行了观察很久后都没有出错,果然成功了。(3)编程过程中还有一些小问题,不过只要是因为C语言编程的一些知识都忘记了,于是我又重新复习了一下C语言的有关知识,果然编起来得心应手多了。5.课程设计小结编程是一件急需细心和耐心的事,刚开始调试过程中遇到了很多弄不清楚原因的报错现象,但是经过不断地
29、修改,那些问题也都没有了。一开始写3X3程序的时候,为了避免犯错误,我是没有加旋转的,只是建了一个魔方的模型并将其绘制出。 加了旋转函数后果然遇到了一些问题,旋转过程中有时候会出现折叠和重叠现象,经过仔细的检查修改,发现原因是在调用旋转函数时,有部分子块的运动没有写入函数,于是问题得到了部分解决。但是随后编写循环控制算法遇到了很大问题,刚开始都弄烦了,但是休息一段时间后,沉下心来仔细思考,我想到了非常好的控制算法,终于问题全部解决了。 这次课程设计,我确实学到了很多。不仅有提升编程能力,而且也学习到了很多做人的道理。刚开始入手这个项目,感觉压力非常大,因为我之前在3D设计方面还是零基础,Ope
30、nGL让我感觉是那么的复杂。随后,我掌握了OpenGL贴图技术,并充分利用OpenGL的特性实现了一个立方体贴六张不同的图片。在我以为实现了一个旋转立方体后,实现2阶魔方就难度不大时,我再次因为我自己的无知而停下了脚步。阅读完老师的代码,总感觉思维很混乱。于是此后很久都没有进展。一段时间过后,当我再次仔细阅读这些算法时,我终于将它们完美的串接了起来,实现了2阶魔方。由2阶魔方到3阶魔方是类似的,但是循环控制算法要难一些。好在我再次编写出来了很好的控制算法,感觉效果很好总的来说总的来说,本次软件课程设计,对我来说收获不小。不仅复习了C语言知识,也对编程及3D设计产生了一定的兴趣,分析问题和解决问
31、题的能力也得到了不小的提高。而且,我也学到了很多人生的道理。在做一件看似很难的事时,我们要有一个总体的框架,不要有畏难心理。静下心来,沉着的分析问题,问题总会迎刃而解的。因此,成功的关键在于你是否拥有这样的心理。参考文献1孙鑫 VC+深入详解 第三版 北京 电子工业出版社 2007年 1-262杨柏林,陈根浪,徐静 OpenGL编程精粹 第三版 北京 机械工业出版社 2010年 1-1213周纯杰,刘正林,何顶新,周凯波 标准C语言程序设计及应用 第二版 武汉 华中科技大学出版社 2008年 1-2634Dave Shreiner,The Khronons OpenGLARB Working
32、Group OpenGL编程指南 第七版 北京 机械工业出版社 2010年 21-328 附上源码第一个文件-头文件#ifndef _MO_FANG_H_#define _MO_FANG_H_#include / windows的头文件#include #include / 包含OpenGL核心库#include / 包含OpenGL实用库#include / 包含OpenGL辅助库#include / 包含数学函数库#define PI2 6.2831853f #define CYCLE_COUNT 90#define MAX_CHAR 128 /用于在窗口显示文字而定义的常数#define
33、 FRONT 0#define BACK 1#define LEFT 2#define RIGHT 3#define TOP 4#define BOTTOM 5typedef struct GLfloat vx,vy,vz;CubeVertex;typedef struct GLfloat p3;stPoint;typedef struct stPoint CubePoint8;stCube;void reset_model(); void Rotate_ZM();void Rotate_ZZ();void Rotate_ZP();void Rotate_XM();void Rotate_XZ
34、();void Rotate_XP();void Rotate_YM();void Rotate_YZ();void Rotate_YP();void Rotate_Z(int ii);void Rotate_Y(int ii);void Rotate_X(int ii);void enable_X_roatate(int direction);void enable_Y_roatate(int direction);void enable_Z_roatate(int direction);void selectFont(int size, int charset, const char* f
35、ace);void drawCNString(const char* str);void drawString(const char* str);extern stCube Cube27;extern int rotAngle;extern int rotCount;extern int rotX,rotY,rotZ; extern GLfloat Vx,Vy;#endif 第二个文件/* *这个cpp文件包含三阶魔方变换的常规函数 * 作者为张世清 学号U201014185 *当然成果还离不开组员徐兮、雷韦拉以及何兆华的支持 */加入自己编写的魔方头文件,其中包含一些变量定义与函数声明#in
36、clude MoFang.h /对立方体各顶点编号static stPoint CubePoint8= -1.0f, -1.0f, 1.0f, /0 1.0f, -1.0f, 1.0f , /1 1.0f, 1.0f, 1.0f , /2 -1.0f, 1.0f, 1.0f, /3-1.0f, -1.0f, -1.0f, /4 -1.0f, 1.0f, -1.0f, /51.0f, 1.0f, -1.0f, /6 1.0f, -1.0f, -1.0f, /7 ;extern int cs;stCube Cube27; /定义一个3阶魔方stCube Static_Cube27; /定义一个静态
37、的3阶魔方/旋转控制int rotAngle = 1; /旋转角度int rotCount; /一个旋转周期内旋转次数 CYCLE_COUNT = 90/rotAngle;int rotX,rotY,rotZ; /指定那个轴旋转int rotDirect=1; /正反向旋转/对当前魔方各个立方体进行编号BYTE ZP9 = 0,1,2,3,4,5,6,7,8; /z轴方向正向一层BYTE ZZ9 = 9,10,11,12,13,14,15,16,17; /z轴方向中间一层BYTE ZM9 = 18,19,20,21,22,23,24,25,26; /z轴方向负向一层BYTE YM9 = 0,1
38、,2,11,10,9,18,19,20; /y轴方向负向一层BYTE YZ9 = 3,4,5,14,13,12,21,22,23; /y轴方向中间一层BYTE YP9 = 6,7,8,17,16,15,24,25,26; /y轴方向正向一层BYTE XM9 = 2,3,8,17,12,11,20,21,26; /x轴方向正向一层BYTE XZ9 = 1,4,7,16,13,10,19,22,25; /x轴方向中间一层BYTE XP9 = 0,5,6,15,14,9,18,23,24; /x轴方向负向一层/对静态魔方各个立方体进行编号const BYTE SZP9 = 0,1,2,3,4,5,6
39、,7,8; /z轴方向正向一层const BYTE SZZ9 = 9,10,11,12,13,14,15,16,17; /z轴方向中间一层const BYTE SZM9 = 18,19,20,21,22,23,24,25,26; /z轴方向负向一层const BYTE SYM9 = 0,1,2,11,10,9,18,19,20; /y轴方向负向一层const BYTE SYZ9 = 3,4,5,14,13,12,21,22,23; /y轴方向中间一层const BYTE SYP9 = 6,7,8,17,16,15,24,25,26; /y轴方向正向一层const BYTE SXM9 = 2,3
40、,8,17,12,11,20,21,26; /x轴方向正向一层const BYTE SXZ9 = 1,4,7,16,13,10,19,22,25; /x轴方向中间一层const BYTE SXP9 = 0,5,6,15,14,9,18,23,24; /x轴方向负向一层void Rotate(stCube *pCube,float angle,float x0,float y0,float z0); /声明旋转函数/判断两个立方体是否重合,即判断两个立方体所包含的所有顶点坐标是否相同int is_equal(stCube *pc1,stCube *pc2) float x1,x2,y1,y2,z
41、1,z2; int isFind = 0; for( int i=0;iCubePointi.p0; y1 = pc1-CubePointi.p1; z1 = pc1-CubePointi.p2; isFind = 0; for(int j=0;jCubePointj.p0; y2 = pc2-CubePointj.p1; z2 = pc2-CubePointj.p2; if( fabs(x1 - x2)1e-1 & fabs(y1-y2)1e-1 & fabs(z1-z2)CubePointi.p0 = pc2-CubePointj.p0; /消除累计误差 pc1-CubePointi.p1
42、 = pc2-CubePointj.p1; pc1-CubePointi.p2 = pc2-CubePointj.p2; isFind = 1; break; if( isFind = 0) return 0; return 1;/旋转之后,查找当前旋转面里面包含新的角点void Update_Cube_index()int i,j,k=0; /根据逐一判断立方体是否重合来更新每一层所包含的立方体的索引,总共三个方向有九层k =0 ;for( i=0;i9;i+) for( j=0;j27;j+) if( is_equal( &Cubej, &Static_Cube SZMi ) )ZMk+
43、= j;k=0;for(i=0;i9;i+)for(j=0;j27;j+)if(is_equal( &Cubej, &Static_Cube SZZi )ZZk+=j;k = 0;for( i=0;i9;i+)for( j=0;j27;j+)if( is_equal( &Cubej , &Static_Cube SZPi ) )ZPk+ = j; k =0 ;for( i=0;i9;i+) for( j=0;j27;j+) if( is_equal( &Cubej, &Static_Cube SXMi ) ) XMk+ = j; k =0 ;for( i=0;i9;i+) for( j=0;j
44、27;j+)if( is_equal( &Cubej, &Static_Cube SXZi ) )XZk+ = j;k = 0;for( i=0;i9;i+) for(j=0;j27;j+) if( is_equal( &Cubej, &Static_Cube SXPi ) ) XPk+ = j; k =0 ;for( i=0;i9;i+) for(j=0;j27;j+)if( is_equal( &Cubej, &Static_Cube SYMi ) )YMk+ = j;k =0 ;for( i=0;i9;i+) for(j=0;j27;j+)if( is_equal( &Cubej, &S
45、tatic_Cube SYZi ) )YZk+ = j; k = 0;for( i=0;i9;i+) for( j=0;j27;j+) if( is_equal( &Cubej, &Static_Cube SYPi ) ) YPk+ = j; /z轴负向一层绕着z轴转void Rotate_ZM() for(int i=0;i9;i+) Rotate(&Cube ZMi ,rotAngle*rotDirect, 0.0,0.0, 1.0);/转180度后重新更新立方体索引 if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_
46、Cube_index();rotAngle = 0;rotZ = 0;/z轴中间一层绕着z轴转void Rotate_ZZ() for(int i=0;i9;i+) Rotate(&Cube ZZi ,rotAngle*rotDirect, 0.0,0.0, 1.0);/转180度后重新更新立方体索引 if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_Cube_index();rotAngle = 0;rotZ = 0;/z轴正向一层绕着z轴转void Rotate_ZP() for(int i=0;i9;i+) Rota
47、te(&Cube ZPi ,rotAngle*rotDirect, 0.0,0.0, 1.0);/转180度后重新更新立方体索引 if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_Cube_index();rotAngle = 0;rotZ = 0;/x轴负向一层绕着x轴转void Rotate_XM() for(int i=0;i9;i+) Rotate(&Cube XMi ,rotAngle*rotDirect, 1.0,0.0, 0.0);/转180度后重新更新立方体索引if( rotCount+=CYCLE_COU
48、NT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_Cube_index();rotAngle = 0;rotX = 0;/x轴中间一层绕着x轴转void Rotate_XZ() for(int i=0;i9;i+) Rotate(&Cube XZi ,rotAngle*rotDirect, 1.0,0.0, 0.0);/转180度后重新更新立方体索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_Cube_index();rotAngle = 0;rotX = 0;/x轴正向一层绕着x轴转voi
49、d Rotate_XP() for(int i=0;i9;i+) Rotate(&Cube XPi ,rotAngle*rotDirect, 1.0,0.0, 0.0);/转180度后重新更新立方体索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_Cube_index();rotAngle = 0;rotX = 0;/y轴负向一层绕着y轴转void Rotate_YM() for(int i=0;i9;i+) Rotate(&Cube YMi ,rotAngle*rotDirect, 0.0,1.0, 0.0);/转1
50、80度后重新更新立方体索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_Cube_index();rotAngle = 0;rotY = 0;/y轴中间一层绕着y轴转void Rotate_YZ() for(int i=0;i9;i+) Rotate(&Cube YZi ,rotAngle*rotDirect, 0.0,1.0, 0.0);/转180度后重新更新立方体索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每转一个周期后重新对cs赋值Update_Cube_index();r
51、otAngle = 0;rotY = 0;/y轴正向一层绕着y轴转void Rotate_YP() for(int i=0;i1e-2 ) for( i=0;iCubePointi.p1; z= pCube-CubePointi.p2; pCube-CubePointi.p1 = y*cosa - z*sina; pCube-CubePointi.p2 = y*sina + z*cosa; if ( fabs(y0)1e-2 ) for( i=0;iCubePointi.p0; z= pCube-CubePointi.p2; pCube-CubePointi.p0 = x*cosa - z*s
52、ina; pCube-CubePointi.p2 = x*sina + z*cosa; if ( fabs(z0)1e-2 ) for( i=0;iCubePointi.p0; y= pCube-CubePointi.p1; pCube-CubePointi.p0 = x*cosa - y*sina; pCube-CubePointi.p1 = x*sina + y*cosa; /还原模型,即根据平移得倒所有27个立方体的坐标位置void reset_model()int i;for(i=0;i8;i+)Cube0.CubePointi.p0 = CubePointi.p0-2.0f ;Cub
53、e0.CubePointi.p1 = CubePointi.p1-2.0f ;Cube0.CubePointi.p2 = CubePointi.p2+2.0f;for( i=0;i8;i+)Cube1.CubePointi.p0 = CubePointi.p0+0.0f ;Cube1.CubePointi.p1 = CubePointi.p1-2.0f;Cube1.CubePointi.p2 = CubePointi.p2+2.0f; for( i=0;i8;i+)Cube2.CubePointi.p0 = CubePointi.p0+2.0f ;Cube2.CubePointi.p1 = C
54、ubePointi.p1-2.0f;Cube2.CubePointi.p2 = CubePointi.p2+2.0f;for( i=0;i8;i+)Cube3.CubePointi.p0 = CubePointi.p0+2.0f ;Cube3.CubePointi.p1 = CubePointi.p1+0.0f;Cube3.CubePointi.p2 = CubePointi.p2+2.0f;for( i=0;i8;i+)Cube4.CubePointi.p0 = CubePointi.p0+0.0f ;Cube4.CubePointi.p1 = CubePointi.p1+0.0f;Cube
55、4.CubePointi.p2 = CubePointi.p2+2.0f;for( i=0;i8;i+)Cube5.CubePointi.p0 = CubePointi.p0-2.0f ;Cube5.CubePointi.p1 = CubePointi.p1+0.0f;Cube5.CubePointi.p2 = CubePointi.p2+2.0f;for( i=0;i8;i+)Cube6.CubePointi.p0 = CubePointi.p0-2.0f ;Cube6.CubePointi.p1 = CubePointi.p1+2.0f;Cube6.CubePointi.p2 = Cube
56、Pointi.p2+2.0f;for( i=0;i8;i+)Cube7.CubePointi.p0 = CubePointi.p0+0.0f ;Cube7.CubePointi.p1 = CubePointi.p1+2.0f;Cube7.CubePointi.p2 = CubePointi.p2+2.0f;for( i=0;i8;i+)Cube8.CubePointi.p0 = CubePointi.p0+2.0f ;Cube8.CubePointi.p1 = CubePointi.p1+2.0f;Cube8.CubePointi.p2 = CubePointi.p2+2.0f;for(i=0
57、;i8;i+)Cube9.CubePointi.p0 = CubePointi.p0-2.0f ;Cube9.CubePointi.p1 = CubePointi.p1-2.0f ;Cube9.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube10.CubePointi.p0 = CubePointi.p0+0.0f ;Cube10.CubePointi.p1 = CubePointi.p1-2.0f ;Cube10.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube11.CubeP
58、ointi.p0 = CubePointi.p0+2.0f ;Cube11.CubePointi.p1 = CubePointi.p1-2.0f ;Cube11.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube12.CubePointi.p0 = CubePointi.p0+2.0f ;Cube12.CubePointi.p1 = CubePointi.p1+0.0f ;Cube12.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube13.CubePointi.p0 = CubeP
59、ointi.p0+0.0f ;Cube13.CubePointi.p1 = CubePointi.p1+0.0f ;Cube13.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube14.CubePointi.p0 = CubePointi.p0-2.0f ;Cube14.CubePointi.p1 = CubePointi.p1+0.0f ;Cube14.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube15.CubePointi.p0 = CubePointi.p0-2.0f ;C
60、ube15.CubePointi.p1 = CubePointi.p1+2.0f ;Cube15.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube16.CubePointi.p0 = CubePointi.p0+0.0f ;Cube16.CubePointi.p1 = CubePointi.p1+2.0f ;Cube16.CubePointi.p2 = CubePointi.p2+0.0f;for(i=0;i8;i+)Cube17.CubePointi.p0 = CubePointi.p0+2.0f ;Cube17.CubePointi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 平板印刷工(中级)考试题库及答案
- 基于蛋白质组学技术分析牦牛初乳与成熟乳乳清的差异蛋白
- 2016年新苏教版五年级下册数学期末测试卷(三套)
- 2026届湖南省永州市高三上学期二模化学试卷
- xx针织厂色光管控办法
- 学校作业管理工作自查整改落实报告
- 部编版2026年一年级语文上册第三单元测试题及答案
- 2026年ACOG妇产科临床处理指南-临产和分娩时预防性抗生素的使用
- 部编人教版二年级语文上册期末复习字词达标专项训练测试题卷及答案
- 斜疝术后病人心理护理查房
- 多模式镇痛临床实践与应用
- 2026吉林农业大学三江实验室办公室招聘工作人员笔试备考试题及答案解析
- 脑中风科普知识讲座
- 历史试题-汕头市2025-2026学年度普通高中毕业班教学质量监测(含解析)
- 部队食堂制度规范标准
- 二十届中纪委五次全会知识测试题及答案解析
- 2026年沈阳艺考乐理真题及答案
- 房内装修拆除合同范本
- DB23∕T 3242-2022 秸秆固化成型燃料站设计技术规范
- 生菜课件教学课件
- 5年(2021-2025)高考1年模拟化学真题分类汇编专题12 化工流程综合题(北京专用)(解析版)(北京专用)
评论
0/150
提交评论