基于OpenGL的3D旋轉(zhuǎn)魔方的實現(xiàn)_第1頁
基于OpenGL的3D旋轉(zhuǎn)魔方的實現(xiàn)_第2頁
基于OpenGL的3D旋轉(zhuǎn)魔方的實現(xiàn)_第3頁
基于OpenGL的3D旋轉(zhuǎn)魔方的實現(xiàn)_第4頁
基于OpenGL的3D旋轉(zhuǎn)魔方的實現(xiàn)_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、華中科技大學電子科學與技術(shù)系課程設計報告( 2011- 2012年度第 2 學期)名 稱: 軟件課程設計 題 目: 基于OpenGL的3D旋轉(zhuǎn)魔方實現(xiàn)院 系: XXXXXX 班 級: XXXXX 學 號: U201014185 學生姓名: X X X 指導教師: X X X 設計周數(shù): XXXX 成 績: 日期: 2012 年 5月 24日目 錄1課程設計介紹 11.1.內(nèi)容 1 1 12程序分析 2 2.1. 程序原理 22.1. 程序流程 3. 數(shù)據(jù)結(jié)構(gòu) 8 2.4. 重要函數(shù)用法分析 83結(jié)果演示與程序分析 9. 成果演示 9. 程序分析 114編程中遇到的問題125課程設計小結(jié)13參考

2、文獻14 基于OpenGL的3D旋轉(zhuǎn)魔方實現(xiàn)課程設計介紹目的當今計算機技術(shù)流行,引領(lǐng)了各行各業(yè)。而程序是計算機的靈魂,因此編程能力對當今的學生而言至關(guān)重要。雖然我們在前期已經(jīng)學習了C語言,但是還只對程序有一些簡單的認識,說實話,是很淺顯的認識。通過本軟件課程設計的學習,可以從整體上對軟件工程和項目有全面的認識。通過此次課程設計,可以鍛煉編程能力,激發(fā)對編程的興趣,同時也能培養(yǎng)良好的編程習慣。這對于個人今后的學習,今后的工作乃至今后的生活都會產(chǎn)生重要的影響。對于國家而言,極大的推動了計算機普及教育,提高了大學生的計算機使用水平,具有重大的意義。內(nèi)容通過此次項目掌握軟件開發(fā)模式,模塊化結(jié)構(gòu)分析以及

3、程序設計流程掌握有關(guān)程序設計的思想,數(shù)據(jù)結(jié)構(gòu)的知識,掌握C語言算法,掌握OpenGL編程知識如貼圖與鍵盤控制掌握win32編程知識,了解windows程序內(nèi)部運行機制初步培養(yǎng)需求分析、軟件測試、調(diào)試的能力在2X2魔方的基礎上,嘗試編寫3X3的魔方,并實現(xiàn)其旋轉(zhuǎn)取得的成果在理解Magic2D例子程序的基礎上,借助了Win32平臺進行了一系列調(diào)試和學習。在此次項目中,學習了Visual C+6.0軟件開發(fā)環(huán)境,熟練掌握了Win32 Application開發(fā)流程。同時也學習了OpenGL的基本知識,掌握了一些OpenGL的重要技術(shù)與重要函數(shù)的使用,編寫了一些簡單的OpenGL程序。參考Magic2

4、D例子流程,我對原程序進行了比較大的修改,并換上了自己的圖片,實現(xiàn)了一個立方體貼六張不同的圖片,并編寫出了自己的2X2魔方程序。根據(jù)相似度分析,成功的編寫出了3X3旋轉(zhuǎn)魔方,并自己設計了算法,實現(xiàn)了各個層面的轉(zhuǎn)動,轉(zhuǎn)動效果很完美。同時,為了增加程序的娛樂效果,我加入了歌曲最炫民族風,雖然很簡單,不過感覺非常實用且有趣。程序分析2.1 程序原理 (1)OpenGLOpenGL是一個開放的三維圖形 HYPERLINK :/baike.baidu /view/600107.htm t _blank 軟件包,它獨立于窗口系統(tǒng)和操作系統(tǒng),以它為基礎開發(fā)的應用程序可以十分方便地在各種平臺間移植;OpenG

5、L可以與 HYPERLINK :/baike.baidu /view/100377.htm t _blank Visual C+緊密接口,便于實現(xiàn)機械手的有關(guān)計算和圖形算法,可保證算法的正確性和可靠性;OpenGL使用簡便,效率高。本設計是在環(huán)境下,使用OpenGL(Open Graphics Library)函數(shù)庫,繪制魔方并實現(xiàn)魔方的繪制、隨機旋轉(zhuǎn)、貼圖以及鍵盤控制等功能。采用基本圖形的繪圖函數(shù)及定位函數(shù),添加相應紋理來實現(xiàn)魔方模型的繪制。通過讀取載入BMP文件,應用紋理貼圖技術(shù)來完成對魔方旋轉(zhuǎn)面的處理。 (2)模型的旋轉(zhuǎn)首先對立方體進行建模。一個立方體由8個點組成,8個點組成6個面片,對

6、立方體的幾何操作本質(zhì)上就是對這6個平面的操作(繪制、紋理、旋轉(zhuǎn)和平移等)。點的索引號確定后,每個面片也就確定了,如0,1,2,3四個點構(gòu)成Z向正投影面。立方體在空間的旋轉(zhuǎn),歸根到底是其頂點的旋轉(zhuǎn),如空間點(x, y, z)繞Z軸旋轉(zhuǎn)a對應的旋轉(zhuǎn)矩陣:cosa sina-sina cosa一個立方體pCube繞Z軸旋轉(zhuǎn)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、其它軸的旋轉(zhuǎn)類似。由于魔方體層面的旋轉(zhuǎn)是90,在某個層面內(nèi)一個子立方體Ci會被另外一個Cj完全替換,因此旋轉(zhuǎn)后必須同步更新魔方體Cube各層面內(nèi)包含的子立方的索引號。為了簡化算法,只需查找旋轉(zhuǎn)后Cubei在Static_Cube中對應的小立方編號j與i的位置匹配。 2.2 程序的流程 通過分析,整個程序大致可以分為6個子功能模塊Win32應用程序框架WinMain主函數(shù)是所有Win32程序的入口點。在WinMain函數(shù)里實現(xiàn)Window是窗體的建立和消息循環(huán),在消息循環(huán)中實現(xiàn)鍵盤、鼠標輸入事件處理響應,具體內(nèi)容可參考VC程序參考手冊。在本課程程序中,不僅要創(chuàng)建Window窗體,而且構(gòu)建Open

8、GL設備繪圖環(huán)境。 Window窗體創(chuàng)建步驟:窗體類注冊:RegisterClass設置顯示分辨率:ChangeDisplaySettings設置窗體大小:AdjustWindowRectEx創(chuàng)建窗體:CreateWindowExOpenGL繪圖環(huán)境搭建: 獲取設備繪圖環(huán)境(DC,DeviceContext):hDC=GetDC(hWnd) 選擇繪圖環(huán)境像素格式:ChoosePixelFormat(hDC,&pfd),其中pfd為像素格式描述符,如果設置不對,OpenGL繪圖失敗,看不到正確的顯示結(jié)果。 設置繪圖環(huán)境像素格式:SetPixelFormat(hDC,PixelFormat,&pf

9、d) 獲取OpenGL繪圖環(huán)境:hRC =wglCreateContext(hDC) 設置OpenGL繪圖環(huán)境:wglMakeCurrent(hDC,hRC)(2)空間建模得到3階魔方 顯然,要建立3X3的魔方必須首先建立單個魔方的模型,然后通過對單個立方體進行平移從而得到3X3的魔方。 平移單個立方體通過reset_model( )函數(shù)中的語句實現(xiàn) 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的立方體,其他編號的立方體同理可以得到構(gòu)成2X2的魔方需要8個立方體,構(gòu)建3X3的魔方則需要27個立方體。根據(jù)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紋理貼圖以下是紋理貼圖的流程,其中實現(xiàn)了一個立方體貼六張圖片 GLuint texture6

12、創(chuàng)建紋理存儲AUX_RGBImageRec* TextureImage6; 創(chuàng)建紋理的存儲空間 TextuteImagei=auxDIBImageLoad(“picture/y1.bmp)調(diào)用此函數(shù)六次載入六張不同的圖片glGenTexTures(1,&texturei)用載入的圖像生成六個紋理glBindTextures(GL_TEXTURE_2D,texturei選擇生成的紋理glBegin(GL_QUADS);glTexCoord(0.0f,0.0f);glVertex3fv(CubePoint0.p);glEnd();每次選擇不同的紋理,然后利用OpenGL是狀態(tài)機的性質(zhì),可以給每個面

13、貼上不同的圖片(4)同步更新索引在整個程序中,同步更新索引所涉及到的算法可以算是最核心的了。當然,你也可以讓每層每個周期轉(zhuǎn)動360度,這樣就不需要動態(tài)更新索引了,因為每次轉(zhuǎn)動前后,立方體的相對坐標位置并沒有改變。但是這樣得到的旋轉(zhuǎn)效果并不好,因為這并沒有考慮到魔方旋轉(zhuǎn)的所有情況,每次旋轉(zhuǎn)后魔方都沒有被打亂。由于涉及到動態(tài)刷新索引,于是按照常理定義一個靜態(tài)的魔方與動態(tài)的魔方進行比較。類似動態(tài)魔方的編號可以得到靜態(tài)魔方的編號。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軸方向負向一層然后編寫一個函數(shù)int is_equal(stCube *pc1,stCube *pc2)判斷兩個立方體是否重合,這個函數(shù)的算法就是比較立方體所有頂點的坐標是否相同。最后一步編寫函數(shù)void Update_Cube_index(),由于魔方轉(zhuǎn)動情況總體上有九種情況,則該函數(shù)必須編寫九塊功能類似的代碼,現(xiàn)在只列出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)魔方的旋轉(zhuǎn)以及鍵盤控制對魔方的平移魔方層面的旋轉(zhuǎn)已經(jīng)在前面介紹,此處除了層面旋轉(zhuǎn)還有魔方的整體旋轉(zhuǎn)。只需調(diào)用庫函數(shù)即可即可。glRotatef(xrot,1.0,0.0,0.0); /使魔方繞x軸轉(zhuǎn)動xrot度glRotatef(yrot,0.0,1.0,0.0); /使魔方繞y軸轉(zhuǎn)動yrot度glRotatef(zrot,0.0,0.0,1.0); /使魔方繞z軸轉(zhuǎn)動zrot度(6)定時器對魔方層面旋轉(zhuǎn)的控制 為了控制魔方的轉(zhuǎn)動,首先定義了函數(shù)void enable_X_roatat

17、e(int direction),void enable_Y_roatate(int direction),void enable_Z_roatate(int direction)以確定旋轉(zhuǎn)軸和旋轉(zhuǎn)方向,同時定義了void Rotate_X(int ii),void Rotate_Y(int ii),void Rotate_Z(int ii)來指定是哪一層的旋轉(zhuǎn)。然后定義兩個計時器Time1和Time2,其中Timer1的消息由WM_TIMER接收并處理,以實現(xiàn)立方體的旋轉(zhuǎn)。Timer2的消息由TimerProc函數(shù)處理,用于生成控制量以控制旋轉(zhuǎn)軸和旋轉(zhuǎn)方向。流程如圖:魔方的層面旋轉(zhuǎn)r除6得到

18、控制參數(shù)r=rand()得到隨機數(shù)rTimer2cs除3的余數(shù)得到控制參數(shù)Timer1實現(xiàn)旋轉(zhuǎn)cs=rand()得到隨機數(shù)cs(7)背景音樂的添加 為了程序有更豐富的效果,我添加了歌曲最炫民族風,方法也很簡單。 #include /提供與多媒體有關(guān)的接口 #pragma comment(lib, WINMM.LIB) /導入winmm.lib庫,實現(xiàn)對多媒體編程的支持 編寫函數(shù)loadsound(),其調(diào)用函數(shù)PlaySound(sound最炫民族風.wav,NULL,SND_LOOP|SND_ASYNC|SND_FILENAME)加載最炫民族風味背景音樂。(8)窗口文字的添加 為了添加自己的

19、信息,我在程序窗口中加了文字void drawString(const char* str),實現(xiàn)添加英文字符。void drawCNString(const char* str)實現(xiàn)添加中文字符void selectFont(int size, int charset, const char* face),實現(xiàn)變換字體 2.3 數(shù)據(jù)結(jié)構(gòu)本程序定義了記錄魔方體每個小塊編號的數(shù)組Cubei及相應的定態(tài)數(shù)組Static_Cube,用來對魔方體變化過程中的相對位置進行索引及重新定位。定義了立方體記錄頂點位置的數(shù)組CubePointi及相應靜態(tài)數(shù)組stPoint CubePointi,用來確定魔方體的

20、旋轉(zhuǎn),因為旋轉(zhuǎn)歸根結(jié)底是其頂點位置的旋轉(zhuǎn)。定義了用來記錄魔方體各個面上子塊編號的數(shù)組ZP/ZZ/ZM,YP/YZ/YM,XP/XZ/XM,及其對應靜態(tài)數(shù)組。定義了數(shù)組TextureImagei來接收紋理。 2.4 重要函數(shù)用法分析(1)窗口創(chuàng)建GLvoid resizeScene(GLsizei width,GLsizei height )這個函數(shù)的目的是重置OpenGL窗口的大小,具體又包含以下五個函數(shù)glViewport(0,0,width,height);glViewport是OpenGL中視口變化函數(shù),根據(jù)窗口的實時變化重繪窗口,它負責把視景體截取的圖像按照怎樣的高和寬顯示到屏幕上。g

21、lMatrixMode(GL_PROJECTION)、glMatrixMode(GL_MODELVIEW) 這兩個函數(shù)原型都是glMatrixMode函數(shù)。glMatrixMode這個函數(shù)其實就是要指定操作的是哪種矩陣。如果參數(shù)是GL_PROJECTION,這個是投影的意思,如果參數(shù)是GL_MODELVIEW,這個是對模型視景的操作,用于對三維場景中坐標系的變換操作。glLoadIdentity()glLoadIdentity該函數(shù)的功能是將當前的用戶坐標系的原點移到了屏幕中心,就像一個復位操作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),作用是啟用紋理映射,此點很關(guān)鍵。 (4)平移與旋轉(zhuǎn) glTranslatef(x, y, z) 平移函數(shù)。表示相對于當前所在的屏幕位置沿著 X, Y 和 Z 軸移動x,y和z個單位。glRotat

24、ef(angle, x, y, z)旋轉(zhuǎn)函數(shù)。與glTranslatef(x, y, z)類似,glRotatef(angle, x, y, z)也是對坐標系進行操作。旋轉(zhuǎn)軸經(jīng)過原點,方向為(x,y,z),旋轉(zhuǎn)角度為angle,方向滿足右手定則。(5)添加窗口文字void drawString(const char* str),實現(xiàn)添加英文字符。void drawCNString(const char* str)實現(xiàn)添加中文字符void selectFont(int size, int charset, const char* face),實現(xiàn)變換字體結(jié)果演示與程序分析魔方體旋轉(zhuǎn)對魔方定位對魔

25、方進行編號程序分析紋理綁定循環(huán)調(diào)用生成紋理 3X3魔方有27個小塊,對每個小塊分別進行編號。先畫出一個子塊,經(jīng)過向相應方向的平移,獲得完整的魔方體。 魔方由函數(shù)glTranslatef(float x,float y,float z)定位,再由函數(shù)glRotate(float angle,float x,float y,float z)進行旋轉(zhuǎn),然后由函數(shù)glBindTexture(GLenum target,GLunit textureName)進行紋理與相應面的綁定(紋理已由glGenTextures()函數(shù)來產(chǎn)生),最后再用函數(shù)glBegin(GL_QUADS)畫出正方面,從而描繪出了魔

26、方的一個小面。循環(huán)調(diào)用就可以繪制出的魔方。循環(huán)調(diào)用程序的紋理綁定和旋轉(zhuǎn)過程就實現(xiàn)了魔方體的旋轉(zhuǎn)變化。4.編程中遇到的問題 在對2X2魔方理解的基礎上,我經(jīng)過自己的摸索終于在末期做出了自己的3階魔方。其中,遇到了很多問題,不過都被我解決了。以下是我認為的比較重要的問題(1)在編寫判斷兩個立方體是否重合的函數(shù)時,開始我沒有消除累計誤差。說實話,當時我對這個程序并不是很了解。沒有加入這個功能,程序運行結(jié)果如下:剛開始時還比較正常,運行一段時間后,魔方錯位了。想了很久,看了指導書才知道原來還差消除累計誤差這個功能。其實,這也很好解釋。因為我們編寫的旋轉(zhuǎn)函數(shù)涉及到計算cosa以及sina的值,而計算機計

27、算這些值是不是很準確的。在一個旋轉(zhuǎn)周期中,要計算180次cosa和sina的值,因此誤差會被放大,則消除累計誤差成了必須。只需判斷兩個數(shù)在一定誤差范圍內(nèi)相等即可。 (2)魔方循環(huán)控制算法的設計中,我遇到了前所未有的問題。單獨編寫控制最外面一層或是中間一層旋轉(zhuǎn)的函數(shù)確實比較簡單,但是如何實現(xiàn)一個實現(xiàn)外層和中間一層同時都可旋轉(zhuǎn)的魔方還是很有難度的,這涉及到如何合理調(diào)度的問題。在多方調(diào)試后,我想到了一個很好的算法,就是再引入一個控制變量cs,可是變量應該選擇在哪里賦值呢?剛開始我毫不猶豫的就選擇在TimerProc函數(shù)里面賦值,可是一下子就出錯了。后來我將Timer2的定時時間設置為1800ms,目

28、的是等于Timer1的180倍,以實現(xiàn)轉(zhuǎn)一個周期cs重新賦值一次,可結(jié)果表明我再次錯了。因為轉(zhuǎn)動的延遲,所以轉(zhuǎn)動一個周期所需時間是不定的,但肯定不等于1800ms。在重新閱讀一遍程序后,我發(fā)現(xiàn)在void Rotate_ZM()函數(shù)中有轉(zhuǎn)動一個周期后的初始化操作,受到啟發(fā)后,我于是將cs的賦值移到了這個函數(shù)中,運行了觀察很久后都沒有出錯,果然成功了。(3)編程過程中還有一些小問題,不過只要是因為C語言編程的一些知識都忘記了,于是我又重新復習了一下C語言的有關(guān)知識,果然編起來得心應手多了。5.課程設計小結(jié)編程是一件急需細心和耐心的事,剛開始調(diào)試過程中遇到了很多弄不清楚原因的報錯現(xiàn)象,但是經(jīng)過不斷地修改,那些問題也都沒

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論