歡迎來到裝配圖網(wǎng)! | 幫助中心 裝配圖網(wǎng)zhuangpeitu.com!
裝配圖網(wǎng)
ImageVerifierCode 換一換
首頁 裝配圖網(wǎng) > 資源分類 > DOC文檔下載  

基于OpenGL的3D旋轉(zhuǎn)魔方的實(shí)現(xiàn)終期報(bào)告加源碼

  • 資源ID:37938093       資源大?。?span id="ctmevrp" class="font-tahoma">842.50KB        全文頁數(shù):61頁
  • 資源格式: DOC        下載積分:0積分
快捷下載 游客一鍵下載
會(huì)員登錄下載
微信登錄下載
三方登錄下載: 微信開放平臺(tái)登錄 支付寶登錄   QQ登錄   微博登錄  
二維碼
微信掃一掃登錄
下載資源需要0積分
郵箱/手機(jī):
溫馨提示:
用戶名和密碼都是您填寫的郵箱或者手機(jī)號(hào),方便查詢和重復(fù)下載(系統(tǒng)自動(dòng)生成)
支付說明:
本站最低充值0.01積分,下載本資源后余額將會(huì)存入您的賬戶,您可在我的個(gè)人中心查看。
驗(yàn)證碼:   換一換

 
賬號(hào):
密碼:
驗(yàn)證碼:   換一換
  忘記密碼?
    
友情提示
2、PDF文件下載后,可能會(huì)被瀏覽器默認(rèn)打開,此種情況可以點(diǎn)擊瀏覽器菜單,保存網(wǎng)頁到桌面,就可以正常下載了。
3、本站不支持迅雷下載,請(qǐng)使用電腦自帶的IE瀏覽器,或者360瀏覽器、谷歌瀏覽器下載即可。
4、本站資源下載后的文檔和圖紙-無水印,預(yù)覽文檔經(jīng)過壓縮,下載后原文更清晰。
5、試題試卷類文檔,如果標(biāo)題沒有明確說明有答案則都視為沒有答案,請(qǐng)知曉。

基于OpenGL的3D旋轉(zhuǎn)魔方的實(shí)現(xiàn)終期報(bào)告加源碼

華中科技大學(xué)電子科學(xué)與技術(shù)系課程設(shè)計(jì)報(bào)告( 2011- 2012年度第 2 學(xué)期)名 稱: 軟件課程設(shè)計(jì) 題 目: 基于OpenGL的3D旋轉(zhuǎn)魔方實(shí)現(xiàn)院 系: XXXXXX 班 級(jí): XXXXX 學(xué) 號(hào): U201014185 學(xué)生姓名: X X X 指導(dǎo)教師: X X X 設(shè)計(jì)周數(shù): XXXX 成 績: 日期: 2012 年 5月 24日1目 錄1課程設(shè)計(jì)介紹 11.1.內(nèi)容 1 1.2.目的 11.3.取得的成果 12程序分析 2 2.1. 程序原理 22.1. 程序流程 32.3. 數(shù)據(jù)結(jié)構(gòu) 8 2.4. 重要函數(shù)用法分析 83結(jié)果演示與程序分析 93.1. 成果演示 93.2. 程序分析 114編程中遇到的問題125課程設(shè)計(jì)小結(jié)13參考文獻(xiàn)14 基于OpenGL的3D旋轉(zhuǎn)魔方實(shí)現(xiàn)1 課程設(shè)計(jì)介紹1.1 目的當(dāng)今計(jì)算機(jī)技術(shù)流行,引領(lǐng)了各行各業(yè)。而程序是計(jì)算機(jī)的靈魂,因此編程能力對(duì)當(dāng)今的學(xué)生而言至關(guān)重要。雖然我們?cè)谇捌谝呀?jīng)學(xué)習(xí)了C語言,但是還只對(duì)程序有一些簡(jiǎn)單的認(rèn)識(shí),說實(shí)話,是很淺顯的認(rèn)識(shí)。通過本軟件課程設(shè)計(jì)的學(xué)習(xí),可以從整體上對(duì)軟件工程和項(xiàng)目有全面的認(rèn)識(shí)。通過此次課程設(shè)計(jì),可以鍛煉編程能力,激發(fā)對(duì)編程的興趣,同時(shí)也能培養(yǎng)良好的編程習(xí)慣。這對(duì)于個(gè)人今后的學(xué)習(xí),今后的工作乃至今后的生活都會(huì)產(chǎn)生重要的影響。對(duì)于國家而言,極大的推動(dòng)了計(jì)算機(jī)普及教育,提高了大學(xué)生的計(jì)算機(jī)使用水平,具有重大的意義。1.2 內(nèi)容(1) 通過此次項(xiàng)目掌握軟件開發(fā)模式,模塊化結(jié)構(gòu)分析以及程序設(shè)計(jì)流程(2) 學(xué)會(huì)使用VC+6.0進(jìn)行編程(3) 掌握有關(guān)程序設(shè)計(jì)的思想,數(shù)據(jù)結(jié)構(gòu)的知識(shí),掌握C語言算法,掌握OpenGL編程知識(shí)如貼圖與鍵盤控制(4) 掌握win32編程知識(shí),了解windows程序內(nèi)部運(yùn)行機(jī)制(5) 初步培養(yǎng)需求分析、軟件測(cè)試、調(diào)試的能力(6) 在2X2魔方的基礎(chǔ)上,嘗試編寫3X3的魔方,并實(shí)現(xiàn)其旋轉(zhuǎn)1.3 取得的成果在理解Magic2D例子程序的基礎(chǔ)上,借助了Win32平臺(tái)進(jìn)行了一系列調(diào)試和學(xué)習(xí)。在此次項(xiàng)目中,學(xué)習(xí)了Visual C+6.0軟件開發(fā)環(huán)境,熟練掌握了Win32 Application開發(fā)流程。同時(shí)也學(xué)習(xí)了OpenGL的基本知識(shí),掌握了一些OpenGL的重要技術(shù)與重要函數(shù)的使用,編寫了一些簡(jiǎn)單的OpenGL程序。參考Magic2D例子流程,我對(duì)原程序進(jìn)行了比較大的修改,并換上了自己的圖片,實(shí)現(xiàn)了一個(gè)立方體貼六張不同的圖片,并編寫出了自己的2X2魔方程序。根據(jù)相似度分析,成功的編寫出了3X3旋轉(zhuǎn)魔方,并自己設(shè)計(jì)了算法,實(shí)現(xiàn)了各個(gè)層面的轉(zhuǎn)動(dòng),轉(zhuǎn)動(dòng)效果很完美。同時(shí),為了增加程序的娛樂效果,我加入了歌曲最炫民族風(fēng),雖然很簡(jiǎn)單,不過感覺非常實(shí)用且有趣。2 程序分析2.1 程序原理 (1)OpenGLOpenGL是一個(gè)開放的三維圖形軟件包,它獨(dú)立于窗口系統(tǒng)和操作系統(tǒng),以它為基礎(chǔ)開發(fā)的應(yīng)用程序可以十分方便地在各種平臺(tái)間移植;OpenGL可以與Visual C+緊密接口,便于實(shí)現(xiàn)機(jī)械手的有關(guān)計(jì)算和圖形算法,可保證算法的正確性和可靠性;OpenGL使用簡(jiǎn)便,效率高。本設(shè)計(jì)是在Visual C+6.0開發(fā)環(huán)境下,使用OpenGL(Open Graphics Library)函數(shù)庫,繪制魔方并實(shí)現(xiàn)魔方的繪制、隨機(jī)旋轉(zhuǎn)、貼圖以及鍵盤控制等功能。采用基本圖形的繪圖函數(shù)及定位函數(shù),添加相應(yīng)紋理來實(shí)現(xiàn)魔方模型的繪制。通過讀取載入BMP文件,應(yīng)用紋理貼圖技術(shù)來完成對(duì)魔方旋轉(zhuǎn)面的處理。 (2)模型的旋轉(zhuǎn)首先對(duì)立方體進(jìn)行建模。一個(gè)立方體由8個(gè)點(diǎn)組成,8個(gè)點(diǎn)組成6個(gè)面片,對(duì)立方體的幾何操作本質(zhì)上就是對(duì)這6個(gè)平面的操作(繪制、紋理、旋轉(zhuǎn)和平移等)。點(diǎn)的索引號(hào)確定后,每個(gè)面片也就確定了,如0,1,2,3四個(gè)點(diǎn)構(gòu)成Z向正投影面。立方體在空間的旋轉(zhuǎn),歸根到底是其頂點(diǎn)的旋轉(zhuǎn),如空間點(diǎn)(x, y, z)繞Z軸旋轉(zhuǎn)a對(duì)應(yīng)的旋轉(zhuǎn)矩陣:cosa sina-sina cosa一個(gè)立方體pCube繞Z軸旋轉(zhuǎn)a后對(duì)應(yīng)的坐標(biāo)變化為:for( int i=0;i<8;i+) float x,y; x= pCube->CubePointi.p0; y= pCube->CubePointi.p1; pCube->CubePointi.p0 = x*cosa - y*sina; pCube->CubePointi.p1 = x*sina + y*cosa;其它軸的旋轉(zhuǎn)類似。由于魔方體層面的旋轉(zhuǎn)是90,在某個(gè)層面內(nèi)一個(gè)子立方體Ci會(huì)被另外一個(gè)Cj完全替換,因此旋轉(zhuǎn)后必須同步更新魔方體Cube各層面內(nèi)包含的子立方的索引號(hào)。為了簡(jiǎn)化算法,只需查找旋轉(zhuǎn)后Cubei在Static_Cube中對(duì)應(yīng)的小立方編號(hào)j與i的位置匹配。 2.2 程序的流程 通過分析,整個(gè)程序大致可以分為6個(gè)子功能模塊(1) Win32應(yīng)用程序框架WinMain主函數(shù)是所有Win32程序的入口點(diǎn)。在WinMain函數(shù)里實(shí)現(xiàn)Window是窗體的建立和消息循環(huán),在消息循環(huán)中實(shí)現(xiàn)鍵盤、鼠標(biāo)輸入事件處理響應(yīng),具體內(nèi)容可參考VC程序參考手冊(cè)。在本課程程序中,不僅要?jiǎng)?chuàng)建Window窗體,而且構(gòu)建OpenGL設(shè)備繪圖環(huán)境。 Window窗體創(chuàng)建步驟:l 窗體類注冊(cè):RegisterClassl 設(shè)置顯示分辨率:ChangeDisplaySettingsl 設(shè)置窗體大?。篈djustWindowRectExl 創(chuàng)建窗體:CreateWindowExOpenGL繪圖環(huán)境搭建:l 獲取設(shè)備繪圖環(huán)境(DC,DeviceContext):hDC=GetDC(hWnd)l 選擇繪圖環(huán)境像素格式:ChoosePixelFormat(hDC,&pfd),其中pfd為像素格式描述符,如果設(shè)置不對(duì),OpenGL繪圖失敗,看不到正確的顯示結(jié)果。l 設(shè)置繪圖環(huán)境像素格式:SetPixelFormat(hDC,PixelFormat,&pfd)l 獲取OpenGL繪圖環(huán)境:hRC =wglCreateContext(hDC)l 設(shè)置OpenGL繪圖環(huán)境:wglMakeCurrent(hDC,hRC)(2)空間建模得到3階魔方 顯然,要建立3X3的魔方必須首先建立單個(gè)魔方的模型,然后通過對(duì)單個(gè)立方體進(jìn)行平移從而得到3X3的魔方。 平移單個(gè)立方體通過reset_model( )函數(shù)中的語句實(shí)現(xiàn) for(i=0;i<8;i+)Cube0.CubePointi.p0 = CubePointi.p0-2.0f ;Cube0.CubePointi.p1 = CubePointi.p1-2.0f ;Cube0.CubePointi.p2 = CubePointi.p2+2.0f;上述代碼只得到了編號(hào)為0的立方體,其他編號(hào)的立方體同理可以得到構(gòu)成2X2的魔方需要8個(gè)立方體,構(gòu)建3X3的魔方則需要27個(gè)立方體。根據(jù)2階魔方的一些方法,類比到3階魔方。則首先對(duì)魔方的立方體進(jìn)行編號(hào),然后通過編號(hào)得到魔方各層所包含立方體的編號(hào)。其中編號(hào)為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軸方向負(fù)向一層BYTE YM9 = 0,1,2,11,10,9,18,19,20; /y軸方向負(fù)向一層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軸方向負(fù)向一層(3)OpenGL紋理貼圖以下是紋理貼圖的流程,其中實(shí)現(xiàn)了一個(gè)立方體貼六張圖片 GLuint texture6創(chuàng)建紋理存儲(chǔ)AUX_RGBImageRec* TextureImage6; 創(chuàng)建紋理的存儲(chǔ)空間 TextuteImagei=auxDIBImageLoad(“picture/y1.bmp)調(diào)用此函數(shù)六次載入六張不同的圖片glGenTexTures(1,&texturei)用載入的圖像生成六個(gè)紋理glBindTextures(GL_TEXTURE_2D,texturei選擇生成的紋理glBegin(GL_QUADS);glTexCoord(0.0f,0.0f);glVertex3fv(CubePoint0.p);glEnd();每次選擇不同的紋理,然后利用OpenGL是狀態(tài)機(jī)的性質(zhì),可以給每個(gè)面貼上不同的圖片(4)同步更新索引在整個(gè)程序中,同步更新索引所涉及到的算法可以算是最核心的了。當(dāng)然,你也可以讓每層每個(gè)周期轉(zhuǎn)動(dòng)360度,這樣就不需要?jiǎng)討B(tài)更新索引了,因?yàn)槊看无D(zhuǎn)動(dòng)前后,立方體的相對(duì)坐標(biāo)位置并沒有改變。但是這樣得到的旋轉(zhuǎn)效果并不好,因?yàn)檫@并沒有考慮到魔方旋轉(zhuǎn)的所有情況,每次旋轉(zhuǎn)后魔方都沒有被打亂。由于涉及到動(dòng)態(tài)刷新索引,于是按照常理定義一個(gè)靜態(tài)的魔方與動(dòng)態(tài)的魔方進(jìn)行比較。類似動(dòng)態(tài)魔方的編號(hào)可以得到靜態(tài)魔方的編號(hào)。const BYTE SZP9 = 0,1,2,3,4,5,6,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軸方向負(fù)向一層const BYTE SYM9 = 0,1,2,11,10,9,18,19,20; /y軸方向負(fù)向一層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,16,13,10,19,22,25; /x軸方向中間一層const BYTE SXP9 = 0,5,6,15,14,9,18,23,24; /x軸方向負(fù)向一層然后編寫一個(gè)函數(shù)int is_equal(stCube *pc1,stCube *pc2)判斷兩個(gè)立方體是否重合,這個(gè)函數(shù)的算法就是比較立方體所有頂點(diǎn)的坐標(biāo)是否相同。最后一步編寫函數(shù)void Update_Cube_index(),由于魔方轉(zhuǎn)動(dòng)情況總體上有九種情況,則該函數(shù)必須編寫九塊功能類似的代碼,現(xiàn)在只列出X軸負(fù)向一層刷新索引的算法。int i,j,k=0;k =0 ;for( i=0;i<9;i+) for( j=0;j<27;j+) if( is_equal( &Cubej, &Static_Cube SZMi ) )ZMk+ = j; (5)魔方的旋轉(zhuǎn)以及鍵盤控制對(duì)魔方的平移魔方層面的旋轉(zhuǎn)已經(jīng)在前面介紹,此處除了層面旋轉(zhuǎn)還有魔方的整體旋轉(zhuǎn)。只需調(diào)用庫函數(shù)即可即可。glRotatef(xrot,1.0,0.0,0.0); /使魔方繞x軸轉(zhuǎn)動(dòng)xrot度glRotatef(yrot,0.0,1.0,0.0); /使魔方繞y軸轉(zhuǎn)動(dòng)yrot度glRotatef(zrot,0.0,0.0,1.0); /使魔方繞z軸轉(zhuǎn)動(dòng)zrot度(6)定時(shí)器對(duì)魔方層面旋轉(zhuǎn)的控制 為了控制魔方的轉(zhuǎn)動(dòng),首先定義了函數(shù)void enable_X_roatate(int direction),void enable_Y_roatate(int direction),void enable_Z_roatate(int direction)以確定旋轉(zhuǎn)軸和旋轉(zhuǎn)方向,同時(shí)定義了void Rotate_X(int ii),void Rotate_Y(int ii),void Rotate_Z(int ii)來指定是哪一層的旋轉(zhuǎn)。然后定義兩個(gè)計(jì)時(shí)器Time1和Time2,其中Timer1的消息由WM_TIMER接收并處理,以實(shí)現(xiàn)立方體的旋轉(zhuǎn)。Timer2的消息由TimerProc函數(shù)處理,用于生成控制量以控制旋轉(zhuǎn)軸和旋轉(zhuǎn)方向。流程如圖:魔方的層面旋轉(zhuǎn)r除6得到控制參數(shù)r=rand()得到隨機(jī)數(shù)rTimer2cs除3的余數(shù)得到控制參數(shù)Timer1實(shí)現(xiàn)旋轉(zhuǎn)cs=rand()得到隨機(jī)數(shù)cs(7)背景音樂的添加 為了程序有更豐富的效果,我添加了歌曲最炫民族風(fēng),方法也很簡(jiǎn)單。 #include<mmsystem.h> /提供與多媒體有關(guān)的接口 #pragma comment(lib, "WINMM.LIB") /導(dǎo)入winmm.lib庫,實(shí)現(xiàn)對(duì)多媒體編程的支持 編寫函數(shù)loadsound(),其調(diào)用函數(shù)PlaySound("sound最炫民族風(fēng).wav",NULL,SND_LOOP|SND_ASYNC|SND_FILENAME)加載最炫民族風(fēng)味背景音樂。(8)窗口文字的添加 為了添加自己的信息,我在程序窗口中加了文字void drawString(const char* str),實(shí)現(xiàn)添加英文字符。void drawCNString(const char* str)實(shí)現(xiàn)添加中文字符void selectFont(int size, int charset, const char* face),實(shí)現(xiàn)變換字體 2.3 數(shù)據(jù)結(jié)構(gòu)本程序定義了記錄魔方體每個(gè)小塊編號(hào)的數(shù)組Cubei及相應(yīng)的定態(tài)數(shù)組Static_Cube,用來對(duì)魔方體變化過程中的相對(duì)位置進(jìn)行索引及重新定位。定義了立方體記錄頂點(diǎn)位置的數(shù)組CubePointi及相應(yīng)靜態(tài)數(shù)組stPoint CubePointi,用來確定魔方體的旋轉(zhuǎn),因?yàn)樾D(zhuǎn)歸根結(jié)底是其頂點(diǎn)位置的旋轉(zhuǎn)。定義了用來記錄魔方體各個(gè)面上子塊編號(hào)的數(shù)組ZP/ZZ/ZM,YP/YZ/YM,XP/XZ/XM,及其對(duì)應(yīng)靜態(tài)數(shù)組。定義了數(shù)組TextureImagei來接收紋理。 2.4 重要函數(shù)用法分析(1)窗口創(chuàng)建GLvoid resizeScene(GLsizei width,GLsizei height )這個(gè)函數(shù)的目的是重置OpenGL窗口的大小,具體又包含以下五個(gè)函數(shù)glViewport(0,0,width,height);glViewport是OpenGL中視口變化函數(shù),根據(jù)窗口的實(shí)時(shí)變化重繪窗口,它負(fù)責(zé)把視景體截取的圖像按照怎樣的高和寬顯示到屏幕上。glMatrixMode(GL_PROJECTION)、glMatrixMode(GL_MODELVIEW) 這兩個(gè)函數(shù)原型都是glMatrixMode函數(shù)。glMatrixMode這個(gè)函數(shù)其實(shí)就是要指定操作的是哪種矩陣。如果參數(shù)是GL_PROJECTION,這個(gè)是投影的意思,如果參數(shù)是GL_MODELVIEW,這個(gè)是對(duì)模型視景的操作,用于對(duì)三維場(chǎng)景中坐標(biāo)系的變換操作。glLoadIdentity()glLoadIdentity該函數(shù)的功能是將當(dāng)前的用戶坐標(biāo)系的原點(diǎn)移到了屏幕中心,就像一個(gè)復(fù)位操作gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f)gluPerspective的作用是設(shè)置透視投影矩陣,意味著越遠(yuǎn)的東西看起來越小。45.0f表示將視角設(shè)置為45度,(GLfloat)width/(GLfloat)height表示窗口的縱橫比,0.1f表示沿z軸方向的兩裁面之間的距離的近處為0.1,100f表示沿z軸方向的兩裁面之間的距離的遠(yuǎn)處為100 (2)初始化操作 glShadeModel(GL_SMOOTH),作用是啟用陰影平滑。 glClearColor(0.0f, 0.0f, 0.0f, 0.5f),作用是將背景設(shè)置為黑色。 glClearDepth(1.0f),作用是設(shè)置深度緩存。 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST),作用是做精細(xì)的透視修正。 loadsound(),作用是導(dǎo)入歌曲最炫民族風(fēng)。 (3)OpenGL貼圖 glGenTextures(1, &texturei),作用是利用載入的圖像生成紋理。 glBindTexture(GL_TEXTURE_2D, texturei),作用是選擇生成的紋理。 glTexCoord2f(0.0f,0.0f),作用是設(shè)置紋理坐標(biāo)。 glEnable(GL_TEXTURE_2D),作用是啟用紋理映射,此點(diǎn)很關(guān)鍵。 (4)平移與旋轉(zhuǎn) glTranslatef(x, y, z) 平移函數(shù)。表示相對(duì)于當(dāng)前所在的屏幕位置沿著 X, Y 和 Z 軸移動(dòng)x,y和z個(gè)單位。glRotatef(angle, x, y, z)旋轉(zhuǎn)函數(shù)。與glTranslatef(x, y, z)類似,glRotatef(angle, x, y, z)也是對(duì)坐標(biāo)系進(jìn)行操作。旋轉(zhuǎn)軸經(jīng)過原點(diǎn),方向?yàn)?x,y,z),旋轉(zhuǎn)角度為angle,方向滿足右手定則。(5)添加窗口文字void drawString(const char* str),實(shí)現(xiàn)添加英文字符。void drawCNString(const char* str)實(shí)現(xiàn)添加中文字符void selectFont(int size, int charset, const char* face),實(shí)現(xiàn)變換字體3 結(jié)果演示與程序分析3.1成果展示魔方體旋轉(zhuǎn)對(duì)魔方定位對(duì)魔方進(jìn)行編號(hào)3.2程序分析紋理綁定循環(huán)調(diào)用生成紋理 3X3魔方有27個(gè)小塊,對(duì)每個(gè)小塊分別進(jìn)行編號(hào)。先畫出一個(gè)子塊,經(jīng)過向相應(yīng)方向的平移,獲得完整的魔方體。 魔方由函數(shù)glTranslatef(float x,float y,float z)定位,再由函數(shù)glRotate(float angle,float x,float y,float z)進(jìn)行旋轉(zhuǎn),然后由函數(shù)glBindTexture(GLenum target,GLunit textureName)進(jìn)行紋理與相應(yīng)面的綁定(紋理已由glGenTextures()函數(shù)來產(chǎn)生),最后再用函數(shù)glBegin(GL_QUADS)畫出正方面,從而描繪出了魔方的一個(gè)小面。循環(huán)調(diào)用就可以繪制出的魔方。循環(huán)調(diào)用程序的紋理綁定和旋轉(zhuǎn)過程就實(shí)現(xiàn)了魔方體的旋轉(zhuǎn)變化。4.編程中遇到的問題 在對(duì)2X2魔方理解的基礎(chǔ)上,我經(jīng)過自己的摸索終于在末期做出了自己的3階魔方。其中,遇到了很多問題,不過都被我解決了。以下是我認(rèn)為的比較重要的問題(1)在編寫判斷兩個(gè)立方體是否重合的函數(shù)時(shí),開始我沒有消除累計(jì)誤差。說實(shí)話,當(dāng)時(shí)我對(duì)這個(gè)程序并不是很了解。沒有加入這個(gè)功能,程序運(yùn)行結(jié)果如下:剛開始時(shí)還比較正常,運(yùn)行一段時(shí)間后,魔方錯(cuò)位了。想了很久,看了指導(dǎo)書才知道原來還差消除累計(jì)誤差這個(gè)功能。其實(shí),這也很好解釋。因?yàn)槲覀兙帉懙男D(zhuǎn)函數(shù)涉及到計(jì)算cosa以及sina的值,而計(jì)算機(jī)計(jì)算這些值是不是很準(zhǔn)確的。在一個(gè)旋轉(zhuǎn)周期中,要計(jì)算180次cosa和sina的值,因此誤差會(huì)被放大,則消除累計(jì)誤差成了必須。只需判斷兩個(gè)數(shù)在一定誤差范圍內(nèi)相等即可。 (2)魔方循環(huán)控制算法的設(shè)計(jì)中,我遇到了前所未有的問題。單獨(dú)編寫控制最外面一層或是中間一層旋轉(zhuǎn)的函數(shù)確實(shí)比較簡(jiǎn)單,但是如何實(shí)現(xiàn)一個(gè)實(shí)現(xiàn)外層和中間一層同時(shí)都可旋轉(zhuǎn)的魔方還是很有難度的,這涉及到如何合理調(diào)度的問題。在多方調(diào)試后,我想到了一個(gè)很好的算法,就是再引入一個(gè)控制變量cs,可是變量應(yīng)該選擇在哪里賦值呢?剛開始我毫不猶豫的就選擇在TimerProc函數(shù)里面賦值,可是一下子就出錯(cuò)了。后來我將Timer2的定時(shí)時(shí)間設(shè)置為1800ms,目的是等于Timer1的180倍,以實(shí)現(xiàn)轉(zhuǎn)一個(gè)周期cs重新賦值一次,可結(jié)果表明我再次錯(cuò)了。因?yàn)檗D(zhuǎn)動(dòng)的延遲,所以轉(zhuǎn)動(dòng)一個(gè)周期所需時(shí)間是不定的,但肯定不等于1800ms。在重新閱讀一遍程序后,我發(fā)現(xiàn)在void Rotate_ZM()函數(shù)中有轉(zhuǎn)動(dòng)一個(gè)周期后的初始化操作,受到啟發(fā)后,我于是將cs的賦值移到了這個(gè)函數(shù)中,運(yùn)行了觀察很久后都沒有出錯(cuò),果然成功了。(3)編程過程中還有一些小問題,不過只要是因?yàn)镃語言編程的一些知識(shí)都忘記了,于是我又重新復(fù)習(xí)了一下C語言的有關(guān)知識(shí),果然編起來得心應(yīng)手多了。5.課程設(shè)計(jì)小結(jié)編程是一件急需細(xì)心和耐心的事,剛開始調(diào)試過程中遇到了很多弄不清楚原因的報(bào)錯(cuò)現(xiàn)象,但是經(jīng)過不斷地修改,那些問題也都沒有了。一開始寫3X3程序的時(shí)候,為了避免犯錯(cuò)誤,我是沒有加旋轉(zhuǎn)的,只是建了一個(gè)魔方的模型并將其繪制出。 加了旋轉(zhuǎn)函數(shù)后果然遇到了一些問題,旋轉(zhuǎn)過程中有時(shí)候會(huì)出現(xiàn)折疊和重疊現(xiàn)象,經(jīng)過仔細(xì)的檢查修改,發(fā)現(xiàn)原因是在調(diào)用旋轉(zhuǎn)函數(shù)時(shí),有部分子塊的運(yùn)動(dòng)沒有寫入函數(shù),于是問題得到了部分解決。但是隨后編寫循環(huán)控制算法遇到了很大問題,剛開始都弄煩了,但是休息一段時(shí)間后,沉下心來仔細(xì)思考,我想到了非常好的控制算法,終于問題全部解決了。 這次課程設(shè)計(jì),我確實(shí)學(xué)到了很多。不僅有提升編程能力,而且也學(xué)習(xí)到了很多做人的道理。剛開始入手這個(gè)項(xiàng)目,感覺壓力非常大,因?yàn)槲抑霸?D設(shè)計(jì)方面還是零基礎(chǔ),OpenGL讓我感覺是那么的復(fù)雜。隨后,我掌握了OpenGL貼圖技術(shù),并充分利用OpenGL的特性實(shí)現(xiàn)了一個(gè)立方體貼六張不同的圖片。在我以為實(shí)現(xiàn)了一個(gè)旋轉(zhuǎn)立方體后,實(shí)現(xiàn)2階魔方就難度不大時(shí),我再次因?yàn)槲易约旱臒o知而停下了腳步。閱讀完老師的代碼,總感覺思維很混亂。于是此后很久都沒有進(jìn)展。一段時(shí)間過后,當(dāng)我再次仔細(xì)閱讀這些算法時(shí),我終于將它們完美的串接了起來,實(shí)現(xiàn)了2階魔方。由2階魔方到3階魔方是類似的,但是循環(huán)控制算法要難一些。好在我再次編寫出來了很好的控制算法,感覺效果很好總的來說總的來說,本次軟件課程設(shè)計(jì),對(duì)我來說收獲不小。不僅復(fù)習(xí)了C語言知識(shí),也對(duì)編程及3D設(shè)計(jì)產(chǎn)生了一定的興趣,分析問題和解決問題的能力也得到了不小的提高。而且,我也學(xué)到了很多人生的道理。在做一件看似很難的事時(shí),我們要有一個(gè)總體的框架,不要有畏難心理。靜下心來,沉著的分析問題,問題總會(huì)迎刃而解的。因此,成功的關(guān)鍵在于你是否擁有這樣的心理。參考文獻(xiàn)1孫鑫 VC+深入詳解 第三版 北京 電子工業(yè)出版社 2007年 1-262楊柏林,陳根浪,徐靜 OpenGL編程精粹 第三版 北京 機(jī)械工業(yè)出版社 2010年 1-1213周純杰,劉正林,何頂新,周凱波 標(biāo)準(zhǔn)C語言程序設(shè)計(jì)及應(yīng)用 第二版 武漢 華中科技大學(xué)出版社 2008年 1-2634Dave Shreiner,The Khronons OpenGLARB Working Group OpenGL編程指南 第七版 北京 機(jī)械工業(yè)出版社 2010年 21-328 附上源碼第一個(gè)文件-頭文件MoFang.h#ifndef _MO_FANG_H_#define _MO_FANG_H_#include <windows.h>/ windows的頭文件#include <stdio.h>#include <gl/gl.h>/ 包含OpenGL核心庫#include <gl/glu.h>/ 包含OpenGL實(shí)用庫#include <gl/glaux.h>/ 包含OpenGL輔助庫#include <math.h> / 包含數(shù)學(xué)函數(shù)庫#define PI2 6.2831853f #define CYCLE_COUNT 90#define MAX_CHAR 128 /用于在窗口顯示文字而定義的常數(shù)#define 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();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* face);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 第二個(gè)文件MoFang.cpp/* *這個(gè)cpp文件包含三階魔方變換的常規(guī)函數(shù) * 作者為張世清 學(xué)號(hào)U201014185 *華中科技大學(xué)電子系集成1001班 2012.5.19 *當(dāng)然成果還離不開組員徐兮、雷韋拉以及何兆華的支持 */加入自己編寫的魔方頭文件,其中包含一些變量定義與函數(shù)聲明#include "MoFang.h" /對(duì)立方體各頂點(diǎn)編號(hào)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; /定義一個(gè)3階魔方stCube Static_Cube27; /定義一個(gè)靜態(tài)的3階魔方/旋轉(zhuǎn)控制int rotAngle = 1; /旋轉(zhuǎn)角度int rotCount; /一個(gè)旋轉(zhuǎn)周期內(nèi)旋轉(zhuǎn)次數(shù) CYCLE_COUNT = 90/rotAngle;int rotX,rotY,rotZ; /指定那個(gè)軸旋轉(zhuǎn)int rotDirect=1; /正反向旋轉(zhuǎn)/對(duì)當(dāng)前魔方各個(gè)立方體進(jìn)行編號(hào)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軸方向負(fù)向一層BYTE YM9 = 0,1,2,11,10,9,18,19,20; /y軸方向負(fù)向一層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軸方向負(fù)向一層/對(duì)靜態(tài)魔方各個(gè)立方體進(jìn)行編號(hào)const BYTE SZP9 = 0,1,2,3,4,5,6,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軸方向負(fù)向一層const BYTE SYM9 = 0,1,2,11,10,9,18,19,20; /y軸方向負(fù)向一層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,16,13,10,19,22,25; /x軸方向中間一層const BYTE SXP9 = 0,5,6,15,14,9,18,23,24; /x軸方向負(fù)向一層void Rotate(stCube *pCube,float angle,float x0,float y0,float z0); /聲明旋轉(zhuǎn)函數(shù)/判斷兩個(gè)立方體是否重合,即判斷兩個(gè)立方體所包含的所有頂點(diǎn)坐標(biāo)是否相同int is_equal(stCube *pc1,stCube *pc2) float x1,x2,y1,y2,z1,z2; int isFind = 0; for( int i=0;i<8;i+) x1 = pc1->CubePointi.p0; y1 = pc1->CubePointi.p1; z1 = pc1->CubePointi.p2; isFind = 0; for(int j=0;j<8;j+) x2 = pc2->CubePointj.p0; y2 = pc2->CubePointj.p1; z2 = pc2->CubePointj.p2; if( fabs(x1 - x2)<1e-1 && fabs(y1-y2)<1e-1 && fabs(z1-z2)<1e-1) pc1->CubePointi.p0 = pc2->CubePointj.p0; /消除累計(jì)誤差 pc1->CubePointi.p1 = pc2->CubePointj.p1; pc1->CubePointi.p2 = pc2->CubePointj.p2; isFind = 1; break; if( isFind = 0) return 0; return 1;/旋轉(zhuǎn)之后,查找當(dāng)前旋轉(zhuǎn)面里面包含新的角點(diǎn)void Update_Cube_index()int i,j,k=0; /根據(jù)逐一判斷立方體是否重合來更新每一層所包含的立方體的索引,總共三個(gè)方向有九層k =0 ;for( i=0;i<9;i+) for( j=0;j<27;j+) if( is_equal( &Cubej, &Static_Cube SZMi ) )ZMk+ = j;k=0;for(i=0;i<9;i+)for(j=0;j<27;j+)if(is_equal( &Cubej, &Static_Cube SZZi )ZZk+=j;k = 0;for( i=0;i<9;i+)for( j=0;j<27;j+)if( is_equal( &Cubej , &Static_Cube SZPi ) )ZPk+ = j; k =0 ;for( i=0;i<9;i+) for( j=0;j<27;j+) if( is_equal( &Cubej, &Static_Cube SXMi ) ) XMk+ = j; k =0 ;for( i=0;i<9;i+) for( j=0;j<27;j+)if( is_equal( &Cubej, &Static_Cube SXZi ) )XZk+ = j;k = 0;for( i=0;i<9;i+) for(j=0;j<27;j+) if( is_equal( &Cubej, &Static_Cube SXPi ) ) XPk+ = j; k =0 ;for( i=0;i<9;i+) for(j=0;j<27;j+)if( is_equal( &Cubej, &Static_Cube SYMi ) )YMk+ = j;k =0 ;for( i=0;i<9;i+) for(j=0;j<27;j+)if( is_equal( &Cubej, &Static_Cube SYZi ) )YZk+ = j; k = 0;for( i=0;i<9;i+) for( j=0;j<27;j+) if( is_equal( &Cubej, &Static_Cube SYPi ) ) YPk+ = j; /z軸負(fù)向一層繞著z軸轉(zhuǎn)void Rotate_ZM() for(int i=0;i<9;i+) Rotate(&Cube ZMi ,rotAngle*rotDirect, 0.0,0.0, 1.0);/轉(zhuǎn)180度后重新更新立方體索引 if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotZ = 0;/z軸中間一層繞著z軸轉(zhuǎn)void Rotate_ZZ() for(int i=0;i<9;i+) Rotate(&Cube ZZi ,rotAngle*rotDirect, 0.0,0.0, 1.0);/轉(zhuǎn)180度后重新更新立方體索引 if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotZ = 0;/z軸正向一層繞著z軸轉(zhuǎn)void Rotate_ZP() for(int i=0;i<9;i+) Rotate(&Cube ZPi ,rotAngle*rotDirect, 0.0,0.0, 1.0);/轉(zhuǎn)180度后重新更新立方體索引 if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotZ = 0;/x軸負(fù)向一層繞著x軸轉(zhuǎn)void Rotate_XM() for(int i=0;i<9;i+) Rotate(&Cube XMi ,rotAngle*rotDirect, 1.0,0.0, 0.0);/轉(zhuǎn)180度后重新更新立方體索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotX = 0;/x軸中間一層繞著x軸轉(zhuǎn)void Rotate_XZ() for(int i=0;i<9;i+) Rotate(&Cube XZi ,rotAngle*rotDirect, 1.0,0.0, 0.0);/轉(zhuǎn)180度后重新更新立方體索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotX = 0;/x軸正向一層繞著x軸轉(zhuǎn)void Rotate_XP() for(int i=0;i<9;i+) Rotate(&Cube XPi ,rotAngle*rotDirect, 1.0,0.0, 0.0);/轉(zhuǎn)180度后重新更新立方體索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotX = 0;/y軸負(fù)向一層繞著y軸轉(zhuǎn)void Rotate_YM() for(int i=0;i<9;i+) Rotate(&Cube YMi ,rotAngle*rotDirect, 0.0,1.0, 0.0);/轉(zhuǎn)180度后重新更新立方體索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotY = 0;/y軸中間一層繞著y軸轉(zhuǎn)void Rotate_YZ() for(int i=0;i<9;i+) Rotate(&Cube YZi ,rotAngle*rotDirect, 0.0,1.0, 0.0);/轉(zhuǎn)180度后重新更新立方體索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotY = 0;/y軸正向一層繞著y軸轉(zhuǎn)void Rotate_YP() for(int i=0;i<9;i+) Rotate(&Cube YPi ,rotAngle*rotDirect, 0.0,1.0, 0.0);/轉(zhuǎn)180度后重新更新立方體索引if( rotCount+=CYCLE_COUNT)cs=rand()%3; /每轉(zhuǎn)一個(gè)周期后重新對(duì)cs賦值Update_Cube_index();rotAngle = 0;rotY = 0;/通過控制量ii來確定是那一層面繞Z軸轉(zhuǎn)動(dòng)void Rotate_Z(int ii)switch(ii)case 0: Rotate_ZP();

注意事項(xiàng)

本文(基于OpenGL的3D旋轉(zhuǎn)魔方的實(shí)現(xiàn)終期報(bào)告加源碼)為本站會(huì)員(1777****777)主動(dòng)上傳,裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)上載內(nèi)容本身不做任何修改或編輯。 若此文所含內(nèi)容侵犯了您的版權(quán)或隱私,請(qǐng)立即通知裝配圖網(wǎng)(點(diǎn)擊聯(lián)系客服),我們立即給予刪除!

溫馨提示:如果因?yàn)榫W(wǎng)速或其他原因下載失敗請(qǐng)重新下載,重復(fù)下載不扣分。




關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號(hào):ICP2024067431號(hào)-1 川公網(wǎng)安備51140202000466號(hào)


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺(tái),本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請(qǐng)立即通知裝配圖網(wǎng),我們立即給予刪除!