畢業(yè)設(shè)計(jì)-----基于opengl的3d游戲的設(shè)計(jì)與實(shí)現(xiàn)_第1頁
已閱讀1頁,還剩35頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、<p>  基于OpenGL的簡單3d游戲的設(shè)計(jì)與實(shí)現(xiàn)</p><p>  姓   名 </p><p>  系 別、 專 業(yè) </p><p>  導(dǎo) 師 、 職 稱 <

2、/p><p>  完 成 時(shí) 間 </p><p><b>  目 錄</b></p><p><b>  摘 要Ⅰ</b></p><p>

3、  AbstractⅡ</p><p>  1 OpenGL概述1</p><p>  1.1 OpenGL的特點(diǎn)及功能1</p><p>  1.2 OpenGL工作流程4</p><p>  1.3 OpenGL繪圖流程4</p><p>  2 系統(tǒng)分析與設(shè)計(jì)5</p><p>

4、;  2.1系統(tǒng)結(jié)構(gòu)總框架設(shè)計(jì)6</p><p><b>  2.2系統(tǒng)目的7</b></p><p>  3 OpenGL的配置7</p><p>  3.1程序運(yùn)行環(huán)境的配置7</p><p>  4 基礎(chǔ)類的實(shí)現(xiàn)7</p><p>  4.1頭文件包含類Stdafx7</p

5、><p>  4.2向量類Vector8</p><p>  4.3窗口類GLWindow9</p><p>  4.4位圖載入類CBMPLoader10</p><p>  4.4.1 BMP圖像文件格式11</p><p>  4.4.1位圖載入類CBMPLoader流程圖11</p><

6、p>  4.5基本框架的組成12</p><p><b>  5視角控制12</b></p><p>  5.1攝像機(jī)類結(jié)構(gòu)圖12</p><p>  5.2設(shè)置攝像機(jī)的位置12</p><p>  5.3攝像機(jī)旋轉(zhuǎn)功能的實(shí)現(xiàn)13</p><p>  6 游戲場景設(shè)計(jì)16<

7、/p><p>  6.1地面的構(gòu)造17</p><p>  6.2天空的構(gòu)造19</p><p><b>  7 模型設(shè)計(jì)24</b></p><p>  7.1 模型概述24</p><p>  7.2 MD2格式說明24</p><p>  7.3編譯原理25&

8、lt;/p><p>  7.4 讀取MD2文件方法的實(shí)現(xiàn)26</p><p><b>  游戲運(yùn)行截圖27</b></p><p>  注 釋30</p><p><b>  參考文獻(xiàn)31</b></p><p><b>  致 謝32</

9、b></p><p><b>  摘 要</b></p><p>  隨著電腦進(jìn)入千家萬戶,人們對電腦游戲的要求也越來越高,而3D游戲正滿足人們對這方面的需求。人們對游戲的畫面,動畫的逼真度,易操作性以及游戲的思想,故事情節(jié)越來越重視。許多大型的3D游戲大部分都產(chǎn)自國外,而國內(nèi)目前對3D游戲的制作還不夠成熟,特別是一些游戲畫面的逼真度,還有游戲的制作思想,以

10、及游戲的可玩性都尚有不足。近幾年國內(nèi)制作的3D游戲也慢慢上了軌道,在這方面要加大對培養(yǎng)制作游戲人才的力度,力爭做到像《魔獸世界》一樣水平的3D游戲。目前使用openGL實(shí)現(xiàn)其游戲畫面方面的效果還是主流之一。本課題就是基于Visual Studio 2005 平臺的3D游戲,雖然目前的程序有些簡單,但這是為制作復(fù)雜3D游戲打下基礎(chǔ)。</p><p>  本游戲主要由四個(gè)部分組成:視角控制,天空,地面和模型載入。首先

11、要建立一些系統(tǒng)必備的基礎(chǔ)文件,如各種頭文件載入的一個(gè)文件集合Stdafx,以方便其他文件調(diào)用函數(shù)庫里的文件(如OpenGL庫文件,數(shù)學(xué)函數(shù)庫文件等)。在此基礎(chǔ)上建立一些如字體類(組要用來顯示數(shù)字的),向量類,位圖載入類和系統(tǒng)基礎(chǔ)框架類等系統(tǒng)運(yùn)行必備的一些基礎(chǔ)類。建立好了這些游戲運(yùn)行必備的一些基礎(chǔ)類后,我們就可以建立天空類,地形類了。然后用一個(gè)SkyAndTerrain把這兩個(gè)文件封裝起來。</p><p>  關(guān)

12、鍵詞:電腦;3D游戲;OpenGL;Visual Studio 2005</p><p><b>  Abstract</b></p><p>  With computers in every household, people are demanding more and more computer games, whereas the 3D game is to

13、 meet the needs of people in this area. People on the game screen, animation is realistic, easy to operate and game ideas, more and more emphasis on storyline. Many large-scale 3D game produced in most foreign countries,

14、 while domestic production of the current 3D game is not mature enough yet, especially the fidelity of the game screen, there are the production thought the game, and ga</p><p>  1 OpenGL概述</p><p&

15、gt;  OpenGL作為一個(gè)性能優(yōu)越的圖形應(yīng)用程序設(shè)計(jì)界面(API)適合于廣泛的計(jì)算機(jī)環(huán)境,從個(gè)人計(jì)算機(jī)、工作站到超級計(jì)算機(jī),OpenGL都能實(shí)現(xiàn)高性能的三維圖形功能。由于許多在計(jì)算機(jī)界具有領(lǐng)導(dǎo)地位的計(jì)算機(jī)公司紛紛采用OpenGL作為三維圖形應(yīng)用程序設(shè)計(jì)界面,OpenGL應(yīng)用程序具有廣泛的移植性。OpenGL已成為目前的三維圖形開發(fā)標(biāo)準(zhǔn)。</p><p>  OpenGL(OpenGL Graphics Lib

16、rary,開發(fā)性圖形庫)是目前用于開發(fā)可移植的、可交換的2D和3D圖形應(yīng)用程序的首選環(huán)境,是行業(yè)領(lǐng)域中最為廣泛接納的2D/3D圖形API,也是目前應(yīng)用最為廣泛的計(jì)算機(jī)圖形標(biāo)準(zhǔn),其自誕生至今已催生了各種計(jì)算機(jī)平臺及設(shè)備上的數(shù)千優(yōu)秀應(yīng)用程序。通過對OpenGL的特點(diǎn)、功能、工作流程和繪圖流程的學(xué)習(xí),我們將會對OpenGL有一個(gè)初步的了解,建立起基本的概念。</p><p>  1.1 OpenGL的特點(diǎn)及功能<

17、/p><p>  OpenGL作為一個(gè)性能優(yōu)越的圖形應(yīng)用程序設(shè)計(jì)界面,具有以下幾個(gè)特點(diǎn),如圖1.1所示</p><p>  圖1.1 OpenGL特點(diǎn)</p><p>  1.1.1 OpenGL的特點(diǎn) [1]</p><p>  圖形質(zhì)量高、性能好:在CAD/CAM/CAE、醫(yī)學(xué)圖像處理、虛擬實(shí)現(xiàn)、娛樂、廣告等不同領(lǐng)域中,開發(fā)人員可以利用Ope

18、nGL的這些能力自由發(fā)揮自己的創(chuàng)造力。</p><p>  標(biāo)準(zhǔn)化:OpenGL是唯一真正開放的、獨(dú)立于供應(yīng)商的跨平臺的圖形標(biāo)準(zhǔn)。</p><p>  穩(wěn)定性:OpenGL已經(jīng)在各種平臺上應(yīng)用多年,它具有明確而控制良好的規(guī)范,并具有向后兼容性,使現(xiàn)有的應(yīng)用程序不會失效。</p><p>  可靠性和可移植性:利用OpenGL技術(shù)開發(fā)的應(yīng)用圖形軟件與硬件無關(guān),只要硬件

19、支持OpenGL API 標(biāo)準(zhǔn)就可以了,也就是說,OpenGL應(yīng)用可以運(yùn)行在支持OpenGL API標(biāo)準(zhǔn)的任何硬件上。</p><p>  可擴(kuò)展性:通過OpenGL擴(kuò)展機(jī)制,可以利用API進(jìn)行功能擴(kuò)充。如今,許多OpenGL開發(fā)商在OpenGL核心技術(shù)規(guī)范的基礎(chǔ)上,增強(qiáng)了圖形繪制功能,從而使O</p><p>  +能緊跟最新硬件發(fā)展和計(jì)算機(jī)圖形繪制算法的發(fā)展。對于硬件特性的升級可以體現(xiàn)

20、在OpenGL擴(kuò)展機(jī)制及OpenGL API 中,一個(gè)成功的OpenGL擴(kuò)展會被融入在未來的OpenGL版本中。</p><p>  可縮放性:基于OpenGL的應(yīng)用程序可以在各種平臺上運(yùn)行。</p><p>  易用性:OpenGL具有良好的結(jié)構(gòu)、直觀的設(shè)計(jì)和邏輯命令。與其他的圖形程序包相比,OpenGL應(yīng)用程序的代碼行數(shù)少。此外,OpenGL封裝了有關(guān)基本硬件信息,使開發(fā)人員無須針對具

21、體的硬件進(jìn)行專門的設(shè)計(jì)。</p><p>  靈活性:盡管OpenGL有一套獨(dú)特的圖形處理標(biāo)準(zhǔn),但各平臺開發(fā)商可以自由地開發(fā)適合各自系統(tǒng)的OpenGL執(zhí)行實(shí)例。在這些實(shí)例中,OpenGL功能可由特定的硬件實(shí)現(xiàn),也可用純軟件例程實(shí)現(xiàn),或者以軟硬件結(jié)合的方式實(shí)現(xiàn)。</p><p>  1.1.2 OpenGL的七大功能</p><p><b>  如圖1.2所

22、示:</b></p><p>  圖1.2 OpenGL功能</p><p><b>  各功能說明如下:</b></p><p>  建模:OpenGL圖形庫除了提供基本的點(diǎn)、線、多邊形的繪制函數(shù)外,還提供了復(fù)雜的三維物體(球,錐,多面體,茶壺等),以及復(fù)雜曲線和曲面(例如Bezier、Nurbs等曲線或曲面)繪制函數(shù)。</

23、p><p>  變換:OpenGL圖形庫的變換包括基本變換和投影變換?;咀儞Q有平移、旋轉(zhuǎn)、變比、鏡像4種變換,投影變換有平行投影(又稱正射投影)和透視投影兩種變換。</p><p>  顏色模式設(shè)置:OpenGL顏色模式有兩種,即RGBA模式和顏色索引模式(Color Index)模式。</p><p>  紋理映射(Texture Mapping):利用OpenGL

24、紋理映射功能可以十分逼真的表現(xiàn)物體表面細(xì)節(jié)。</p><p>  光照和材質(zhì)設(shè)置:OpenGL光有輻射光(Emitted Light)、環(huán)境光(Ambient Light)、慢反射光(Biffuse Light)和鏡面光(Specular Light)。材質(zhì)是用光反射率來表示。場景(Scene)中物體最終反映到人眼的顏色是紅、綠、藍(lán)、分量與材質(zhì)紅、綠、藍(lán)分量的反射率相乘后形成的顏色。</p><

25、;p>  雙緩存動畫(Double Buffering):雙緩存即前臺緩存和后天緩存。后臺緩存計(jì)算場景、生產(chǎn)動畫,前天緩存顯示后臺緩存已經(jīng)畫好的畫面。</p><p>  特殊效果:利用OpenGL還能實(shí)現(xiàn)深度暗示(Depth Cue)、運(yùn)動模糊(Motion Blur)、融合(Blending)、反走樣(Antialiasing)和霧(Fog)等特殊效果。運(yùn)動模糊和繪圖方式(motion-blured),

26、模擬物體運(yùn)動時(shí)人眼觀察說感覺的動感現(xiàn)象。深度域效果(depth-of-effects)類似于照相機(jī)的鏡頭效果,模型在聚焦點(diǎn)處清晰,反之則模糊。</p><p>  1.2 OpenGL工作流程</p><p>  OpenGL被設(shè)計(jì)成獨(dú)立于硬件、以流水線的方式工作,工作流程圖如圖3所示</p><p>  圖1.3 OpenGL工作流程圖</p>&l

27、t;p>  OpenGL工作流程的輸入端可以是圖像或幾何圖元,但最終結(jié)果都是光柵化后的圖像。這些圖像進(jìn)入幀緩沖區(qū)后,由硬件顯示在輸出設(shè)備上。OpenGL的所有繪圖對象(包括幾何圖元和圖像)既可以存儲在顯示列表中(延遲模式),也可以立即處理(立即模式)。</p><p>  對于圖像,OpenGL首先通過像素解包把其像素格式轉(zhuǎn)換成OpenGL內(nèi)部格式,然后通過像素操作后直接光柵化輸出或者作為其他物體的表現(xiàn)紋理

28、。對于幾何圖元,OpenGL中的所有圖元都是用頂點(diǎn)來描述的。OpenGL首先通過頂點(diǎn)解包將不同格式的頂點(diǎn)轉(zhuǎn)化為內(nèi)部的標(biāo)準(zhǔn)格式,然后對頂點(diǎn)及相關(guān)數(shù)據(jù)(坐標(biāo)、顏色、法向量、紋理坐標(biāo)、邊標(biāo)識等)進(jìn)行操作,在進(jìn)行光柵化,最終得到可見的圖像。</p><p>  1.3 OpenGL繪圖流程</p><p>  OpenGL的繪圖流程如圖1.4所示</p><p>  圖1.

29、4 OpenGL繪圖流程圖</p><p>  設(shè)置像素格式:主要包括建立OpenGL繪制風(fēng)格、顏色模式、顏色位數(shù)、深度位數(shù)等。</p><p>  建立景物模型:根據(jù)基本圖形單元建立景物模型,并且對所建立的模型進(jìn)行數(shù)學(xué)描述。在OpenGL中把點(diǎn)、線、多邊形、圖像和位圖都作為基本圖形單元。</p><p>  舞臺布景:把景物模型放在三維空間中合適的位置,并且設(shè)置視

30、點(diǎn)(Viewpoint)以觀察所感興趣的景觀。</p><p>  效果處理:設(shè)置物體對象的材質(zhì)(顏色、光學(xué)性能及紋理映射等 ),加入光照和光照條件。</p><p>  光柵化:把景物模型的數(shù)學(xué)描述及其色彩信息轉(zhuǎn)換至可在計(jì)算機(jī)上顯示的像素信息,這個(gè)過程就是光柵化(rasterization)。</p><p><b>  2 系統(tǒng)分析與設(shè)計(jì)</b&

31、gt;</p><p>  2.1系統(tǒng)結(jié)構(gòu)總框架設(shè)計(jì)</p><p>  本游戲系統(tǒng)主要分成四大模塊,這些模塊又是由若干個(gè)子模塊構(gòu)成的,形成一個(gè)功能明確的游戲系統(tǒng)。系統(tǒng)結(jié)構(gòu)總框架設(shè)計(jì)如圖2.1所示: </p><p><b>  圖2.1系統(tǒng)結(jié)構(gòu)圖</b></p><p><b>  2.2系統(tǒng)目的</

32、b></p><p>  玩家以第一人稱視角觀察周圍環(huán)境,并可以進(jìn)行旋轉(zhuǎn)視角,前后移動等操作。</p><p>  3 OpenGL的配置</p><p>  3.1程序運(yùn)行環(huán)境的配置 </p><p>  在建立程序框架前首先要下好OpenGL庫文件,把解壓好的庫文件分別按如下路徑放到文件夾里, 對于VS2005可以如下設(shè)置[2]1

33、、把 glut.h 復(fù)制到 VC 安裝路徑下的 PlatFormSDK\include\gl 文件夾2、把 glut32.lib 復(fù)制到 VC 安裝路徑下的 PlatFormSDK\lib 文件夾3、把 glut32.dll 復(fù)制到 Windows\System32 文件夾4、在 VC 中創(chuàng)建控制臺應(yīng)用程序,在選項(xiàng)中清除“使用預(yù)編譯頭”(以免影響可移植性)5、在 VC 中打開項(xiàng)目->屬性對話框進(jìn)行如下設(shè)置:將“配置”下拉框

34、選則為“所有配置”,打開 “鏈接器--輸入”項(xiàng)。在“附加依賴項(xiàng)”中增加:OpenGL32.lib glu32.lib glut32.lib</p><p><b>  4 基礎(chǔ)類的實(shí)現(xiàn)</b></p><p>  4.1頭文件包含類Stdafx</p><p>  在Stdafx.h中包含了常用的頭文件,以方便其他文件的調(diào)用,這樣就不用

35、每個(gè)用到如下頭文件的文件都去寫這些頭文件了。</p><p><b>  常用頭文件:</b></p><p>  #include <windows.h></p><p>  #include <stdio.h></p><p>  #include <math.h>

36、 </p><p>  #include <time.h></p><p><b>  gl頭文件:</b></p><p>  #include <gl\gl.h> </p><p>  #include <gl\glu.h></p

37、><p>  #include <gl\glaux.h></p><p>  #include <gl\glext.h></p><p>  OpenGL鏈接庫文件:</p><p>  #pragma comment(lib, "opengl32.lib")</p><p>

38、;  #pragma comment(lib, "glu32.lib")</p><p>  #pragma comment(lib, "glaux.lib")</p><p>  另外還進(jìn)行了用算符重載的操作</p><p><b>  定義地面網(wǎng)格:</b></p>&l

39、t;p>  const unsigned int MAP_WIDTH = 1024; //位圖的寬度 </p><p>  const unsigned int CELL_WIDTH = 16; //單元格的寬度</p><p>  4.2 向量類Vector</p><p>  主要計(jì)算向量的點(diǎn)積和叉積(詳細(xì)參考附錄)<

40、/p><p><b>  算法的代碼實(shí)現(xiàn)為:</b></p><p><b>  點(diǎn)積:</b></p><p>  float Vector3::dotProduct(const Vector3& v)</p><p><b>  {</b></p><

41、;p>  return ( x * v.x + y * v.y + z * v.z );</p><p><b>  }</b></p><p><b>  叉積:</b></p><p>  Vector3 Vector3::crossProduct(const Vector3& v)</p>

42、<p><b>  {</b></p><p>  Vector3 vec;</p><p>  vec.x = y * v.z - z * v.y;</p><p>  vec.y = z * v.x - x * v.z;</p><p>  vec.z = x * v.y - y * v.x;</p

43、><p>  return vec;</p><p><b>  }</b></p><p>  4.3 窗口類GLWindow</p><p>  4.3.1 窗口類概述</p><p>  任何一個(gè)Windows程序都必須處理設(shè)備描述表(Device Context),它告訴Windows怎樣在一

44、窗口中顯示圖形信息。一個(gè)設(shè)備描述表(DC)說明了筆和畫刷的顏色繪制模式,調(diào)色盤信息,映射模式,以及其他Windows必須知道的怎樣顯示圖形的屬性。與其他的Windows應(yīng)用程序一樣,OpenGL應(yīng)用程序也必須應(yīng)用DC。不過我們將其稱為著色描述表(Rendering Context,RC),由它通知Windows在窗口中繪制圖形。每一個(gè)OpenGL都被連接到一個(gè)RC上。RC將所有的OpenGL調(diào)用命令連接到DC上,應(yīng)用程序必須在繪圖之前調(diào)

45、用專用函數(shù)wglCreateContext()創(chuàng)建自己的RC,調(diào)用wglMakeCurrent使其當(dāng)前化,退出OpenGL時(shí)使RC非當(dāng)前化。</p><p>  4.3.2 GLWindow.h及GLWindow.cpp主要要完成窗口的設(shè)置:</p><p>  intm_WindowPosX; /**< 窗口的左上角的X位置*/</p><p&g

46、t;  intm_WindowPosY; /**< 窗口的左上角的Y位置*/</p><p>  intm_WindowWidth; /**< 窗口的寬度*/</p><p>  intm_WindowHeight; /**< 窗口的高度*/</p><p>  intm_Scre

47、enWidth; /**< 全屏的寬度*/</p><p>  intm_ScreenHeight; /**< 全屏的高度*/</p><p>  intm_BitsPerPixel; /**< 顏色位深*/</p><p>  bool m_IsFullScreen

48、; /**< 是否全屏*/</p><p>  以及設(shè)置像素格式,設(shè)置像素格式首先要填充PIXELFORMATDESCRIPTOR結(jié)構(gòu),其默認(rèn)設(shè)置如下</p><p>  PIXELFORMATDESCRIPTOR pfd = /**< 設(shè)置像素描述結(jié)構(gòu)*/</p><p><b>  {</b></

49、p><p>  sizeof(PIXELFORMATDESCRIPTOR),/**< 像素描述結(jié)構(gòu)的大小*/ </p><p>  1, /**< 版本號*/</p><p>  PFD_DRAW_TO_WINDOW|/**< 緩存區(qū)的輸出顯示在一個(gè)窗口中*/</p><p> 

50、 PFD_SUPPORT_OPENGL|/**< 緩存區(qū)支持OpenGL繪圖*/</p><p>  PFD_STEREO| /**< 顏色緩存區(qū)是立體緩存*/</p><p>  PFD_DOUBLEBUFFER, /**< 顏色緩存區(qū)是雙緩存*/</p><p>  PFD_TYPE_RGBA

51、, /**< 使用RGBA顏色格式*/</p><p>  m_BitsPerPixel, /**< 顏色緩存區(qū)中顏色值所占的位深*/</p><p>  0, 0, 0, 0, 0, 0, /**< 使用默認(rèn)的顏色設(shè)置*/</p><p>  0,

52、 /**< 無Alpha緩存*/</p><p>  0, /**< 顏色緩存區(qū)中alpha成分的移位計(jì)數(shù)*/</p><p>  0, /**< 無累計(jì)緩存區(qū)*/</p><p>  0, 0, 0, 0, /**< 累計(jì)緩存區(qū)無移位*/

53、</p><p>  32, /**< 32位深度緩存*/</p><p>  0, /**< 無蒙版緩存*/</p><p>  0, /**< 無輔助緩存區(qū)*/</p><p>  PFD_MAIN_PLANE,

54、 /**< 必須為PFD_MAIN_PLANE,設(shè)置為主繪圖層*/</p><p>  0, /**< 表示OpenGL實(shí)現(xiàn)所支持的上層或下層平面的數(shù)量*/</p><p>  0, 0, 0 /**< 過時(shí),已不再使用*/</p><p><

55、b>  };</b></p><p>  4.4 位圖載入類CBMPLoader</p><p>  4.4.1 BMP圖像文件格式[3]</p><p>  BMP是一種與硬件設(shè)備無關(guān)的圖像文件格式,使用非常廣。它采用位映射存儲格式,除了圖像深度可選以外,不采用其他任何壓縮,因此,BMP文件所占用的空間很大。BMP文件的圖像深度可選lbit、4b

56、it、8bit及24bit。BMP文件存儲數(shù)據(jù)時(shí),圖像的掃描方式是按從左到右、從下到上的順序。</p><p>  由于BMP文件格式是Windows環(huán)境中交換與圖有關(guān)的數(shù)據(jù)的一種標(biāo)準(zhǔn),因此在Windows環(huán)境中運(yùn)行的圖形圖像軟件都支持BMP圖像格式。</p><p>  典型的BMP圖像文件由三部分組成:位圖文件頭數(shù)據(jù)結(jié)構(gòu),它包含BMP圖像文件的類型、顯示內(nèi)容等信息;位圖信息數(shù)據(jù)結(jié)構(gòu),它

57、包含有BMP圖像的寬、高、壓縮方法,以及定義顏色等信息。</p><p>  BMP 是(Windows 位圖 ) Windows 位圖可以用任何顏色深度(從黑白到 24 位顏色)存儲單個(gè)光柵圖像。Windows 位圖文件格式與其他 Microsoft Windows 程序兼容。它不支持文件壓縮,也不適用于 Web 頁。 從總體上看,Windows 位圖文件格式的缺點(diǎn)超過了它的優(yōu)點(diǎn)。為了保證照片圖像的質(zhì)量,請使用

58、 PNG 、JPEG、TIFF 文件。BMP 文件適用于 Windows 中的墻紙。</p><p>  優(yōu)點(diǎn):BMP 支持 1 位到 24 位顏色深度。</p><p>  BMP 格式與現(xiàn)有 Windows 程序(尤其是較舊的程序)廣泛兼容。</p><p>  缺點(diǎn): BMP 不支持壓縮,這會造成文件非常大。 BMP 文件不受 Web 瀏覽器支持。</p

59、><p>  4.4.1位圖載入類CBMPLoader流程圖</p><p><b>  如圖4.1所示:</b></p><p>  圖4.1 位圖載入類流程圖</p><p>  4.5 基本框架的組成</p><p>  鍵盤類和程序框架類(GLFrame):</p><p&

60、gt;<b>  鍵盤類:</b></p><p>  class Keys </p><p><b>  {</b></p><p>  public: </p><p>  Keys()

61、{ Clear(); } /** 構(gòu)造函數(shù)*/</p><p>  void Clear() { ZeroMemory(&m_KeyDown, sizeof(m_KeyDown)); }/** 清空所有的按鍵信息*/</p><p>  bool IsPressed(unsigned int key){ return (key < MAX_KEYS) ? (

62、m_KeyDown[key] == true) : false; }/** 判斷某個(gè)鍵是否按下*/</p><p>  void SetPressed(unsigned int key){ if (key < MAX_KEYS) m_KeyDown[key] = true; }/** 設(shè)置某個(gè)鍵被按下*/</p><p>  void SetReleased(unsigned in

63、t key){ if (key < MAX_KEYS) m_KeyDown[key] = false; }/** 設(shè)置某個(gè)鍵被釋放*/</p><p><b>  private:</b></p><p>  static const unsigned int MAX_KEYS = 256;</p><p>  bool m_KeyDow

64、n[MAX_KEYS];/**< 保存各按鍵的狀態(tài)*/</p><p><b>  };</b></p><p>  在繼承類中完成以下函數(shù)的實(shí)現(xiàn)</p><p>  GLApplication * GLApplication::Create(const char * class_name) //創(chuàng)建子類的一個(gè)實(shí)例

65、</p><p>  bool Init();//執(zhí)行所有的初始化工作,如果成功函數(shù)返回true</p><p>  void Uninit();//執(zhí)行所有的卸載工作</p><p>  void Update(DWORD milliseconds);//執(zhí)行所有的更新操作,傳入的參數(shù)為兩次操作經(jīng)過的時(shí)間,以毫秒

66、 //為單位</p><p>  void Draw();//執(zhí)行所有的繪制操作</p><p>  windowExtendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;/**< 使窗口具有3D外觀*/</p><p><b>  5視角控制</b><

67、;/p><p>  5.1攝像機(jī)類解構(gòu)圖</p><p><b>  如圖5.1所示</b></p><p>  圖5.1 攝像機(jī)類結(jié)構(gòu)圖</p><p>  5.2設(shè)置攝像機(jī)的位置</p><p>  攝像機(jī)類主要的功能是實(shí)現(xiàn)三維漫游。第一要做的事就是設(shè)置攝像機(jī)的位置:</p><

68、;p>  設(shè)置攝像機(jī)的位置,朝向和向上向量。設(shè)置函數(shù)為:</p><p>  void Camera::setCamera( float positionX, float positionY, float positionZ,</p><p>  float viewX, float viewY, float viewZ,</p><p>  

69、float upVectorX, float upVectorY, float upVectorZ)</p><p>  5.3 攝像機(jī)旋轉(zhuǎn)功能的實(shí)現(xiàn)</p><p>  5.3.1 旋轉(zhuǎn)攝像機(jī)</p><p>  旋轉(zhuǎn)攝像機(jī)方向函數(shù)為:</p><p>  void Camera::rotateView(float angle, float

70、 x, float y, float z)</p><p>  Angle為旋轉(zhuǎn)的角度值,X,Y,Z為初始的位置。Angle值由庫函數(shù)獲取。</p><p>  下面是實(shí)現(xiàn)計(jì)算攝像機(jī)在空間中旋轉(zhuǎn)了angle弧度后,計(jì)算其視點(diǎn)View更新的值newView。</p><p>  Vector3 view = m_View - m_Position;/** 計(jì)算方向向

71、量*/</p><p>  /** 計(jì)算sin 和cos值*/</p><p>  float cosTheta = (float)cos(angle);</p><p>  float sinTheta = (float)sin(angle);</p><p>  /** 計(jì)算旋轉(zhuǎn)向量的x值*/</p><p>  

72、newView.x = (cosTheta + (1 - cosTheta) * x * x)* view.x;</p><p>  newView.x += ((1 - cosTheta) * x * y - z * sinTheta)* view.y;</p><p>  newView.x += ((1 - cosTheta) * x * z + y * sinTheta)

73、* view.z;</p><p>  /** 計(jì)算旋轉(zhuǎn)向量的y值*/</p><p>  newView.y = ((1 - cosTheta) * x * y + z * sinTheta)* view.x;</p><p>  newView.y += (cosTheta + (1 - cosTheta) * y * y)* view.y;</p

74、><p>  newView.y += ((1 - cosTheta) * y * z - x * sinTheta)* view.z;</p><p>  /** 計(jì)算旋轉(zhuǎn)向量的z值*/</p><p>  newView.z = ((1 - cosTheta) * x * z - y * sinTheta)* view.x;</p><p&

75、gt;  newView.z += ((1 - cosTheta) * y * z + x * sinTheta)* view.y;</p><p>  newView.z += (cosTheta + (1 - cosTheta) * z * z)* view.z;</p><p>  /** 更新攝像機(jī)的方向*/</p><p>  m_View = m_

76、Position + newView;</p><p>  5.3.2 攝像機(jī)于鼠標(biāo)相連</p><p>  設(shè)置鼠標(biāo)位置在屏幕中心,如果鼠標(biāo)不移動,則不用更新其位置。用鼠標(biāo)旋轉(zhuǎn)攝像機(jī)的重要函數(shù)為</p><p>  void Camera::setViewByMouse()</p><p><b>  {</b><

77、;/p><p>  POINT mousePos; /**< 保存當(dāng)前鼠標(biāo)位置*/</p><p>  int middleX = GetSystemMetrics(SM_CXSCREEN) >> 1; /**< 得到屏幕寬度的一半*/</p><p>  int middleY = GetSystemMetri

78、cs(SM_CYSCREEN) >> 1; /**< 得到屏幕高度的一半*/</p><p>  float angleY = 0.0f; /**< 攝像機(jī)左右旋轉(zhuǎn)角度*/</p><p>  float angleZ = 0.0f; /**< 攝像機(jī)上下旋轉(zhuǎn)角度*

79、/</p><p>  static float currentRotX = 0.0f;</p><p>  用函數(shù)GetCursorPos(&mousePos);得到當(dāng)前鼠標(biāo)位置。</p><p>  5.3.3 注意事項(xiàng)</p><p>  實(shí)時(shí)跟蹤攝像機(jī)的上下的旋轉(zhuǎn)角度如果上下旋轉(zhuǎn)弧度大于1.0(或者小于-1.0),則

80、要截取到1.0(或-1.0)并旋轉(zhuǎn),要不就會出現(xiàn)本該看的的物體不在我們的視野之內(nèi),跑到視野外去了,這就不符合我們的期望了。</p><p>  5.3.4 前后移動和速度Speed相關(guān)</p><p>  前后移動最重要的就是要和移動速度關(guān)聯(lián)起來,根據(jù)物體的速度時(shí)刻改變攝像機(jī)的位置。前后移動的函數(shù)為moveCamera(float speed)。前后移動攝像機(jī)其主要的就是要和攝像機(jī)的速度聯(lián)

81、系起來</p><p>  void Camera::moveCamera(float speed)</p><p><b>  {</b></p><p>  /** 計(jì)算方向向量*/</p><p>  Vector3 vector = m_View - m_Position;</p><p>

82、;  vector = vector.normalize(); /**< 單位化*/</p><p>  /** 更新攝像機(jī)*/</p><p>  m_Position.x += vector.x * speed; /**< 根據(jù)速度更新位置*/</p><p>  m_Position.z += vector.z * speed

83、;</p><p>  m_Position.y += vector.y * speed;</p><p>  m_View.x += vector.x * speed; /**< 根據(jù)速度更新方向*/</p><p>  m_View.y += vector.y * speed;</p><p>  m_View.z += v

84、ector.z * speed;</p><p><b>  }</b></p><p>  以下是鍵盤與攝像機(jī)前后移動關(guān)聯(lián)的主要實(shí)現(xiàn)代碼</p><p>  /** 鍵盤按鍵響應(yīng)*/</p><p>  if(m_Keys.IsPressed(VK_SHIFT)) /**<

85、; 按下SHIFT鍵時(shí)加速*/</p><p><b>  {</b></p><p>  m_Camera.setSpeed(0.6f);</p><p><b>  }</b></p><p>  if(!m_Keys.IsPressed(VK_SHIFT))</p><p&

86、gt;<b>  {</b></p><p>  m_Camera.setSpeed(0.2f);</p><p><b>  }</b></p><p>  if(m_Keys.IsPressed(VK_UP) || m_Keys.IsPressed('W')) /**< 向上方向鍵或'

87、W'鍵按下*/</p><p>  m_Camera.moveCamera(m_Camera.getSpeed()); /**< 移動攝像機(jī)*/</p><p>  if(m_Keys.IsPressed(VK_DOWN) || m_Keys.IsPressed('S')) /**< 向下方向鍵或'S'鍵按下*/<

88、/p><p>  m_Camera.moveCamera(-m_Camera.getSpeed()); /**< 移動攝像機(jī)*/</p><p>  if(m_Keys.IsPressed(VK_LEFT) || m_Keys.IsPressed('A')) /**< 向左方向鍵或'A'鍵按下*/</p><p&g

89、t;  m_Camera.yawCamera(-m_Camera.getSpeed()); /**< 移動攝像機(jī)*/</p><p>  if(m_Keys.IsPressed(VK_RIGHT) || m_Keys.IsPressed('D')) /**< 向右方向鍵或'D'鍵按下*/</p><p>  m_Camera.y

90、awCamera(m_Camera.getSpeed()); /**< 移動攝像機(jī)*/</p><p><b>  }</b></p><p><b>  6 游戲場景設(shè)計(jì)</b></p><p><b>  6.1地面的構(gòu)造</b></p><p>

91、;  6.1.1 地形可視化的概念</p><p>  地形可視化是一門以研究數(shù)字地形模型(Digital Terrain Model)或數(shù)字高程域( Digital Elevation Field)的顯示、簡化、仿真等為內(nèi)容的學(xué)科,并以計(jì)算幾何作為其重要的基礎(chǔ)知識,它屬于計(jì)算機(jī)圖形學(xué)的一個(gè)分支。</p><p>  6.1.2 數(shù)據(jù)基礎(chǔ)</p><p>  未被處

92、理的用于地形三維顯示的數(shù)據(jù)稱為原始數(shù)據(jù),一般被分為矢量和柵格兩種形式。其中矢量數(shù)據(jù)包括線矢量數(shù)據(jù)、地形特征點(diǎn)數(shù)據(jù)等,柵格數(shù)據(jù)主要指數(shù)字高程模型DEM數(shù)據(jù)和紋理圖像數(shù)據(jù)。其中DEM數(shù)據(jù)是地形三維顯示中最重要的數(shù)據(jù),它的精度、質(zhì)量直接影響到后續(xù)的顯示效果。DEM 數(shù)據(jù)也可以由線矢量數(shù)據(jù)生成,初始的DEM數(shù)據(jù)由于顯示水平的不同要求,也可以用不同方法簡化或內(nèi)插為適應(yīng)新需求的數(shù)據(jù),這些數(shù)據(jù)稱為再生數(shù)據(jù)。原始數(shù)據(jù)與再生數(shù)據(jù)共同組成地形可視化的數(shù)據(jù)基

93、礎(chǔ)。</p><p>  6.1.3 顯示理論與方法</p><p>  對已知地形數(shù)據(jù)進(jìn)行三維顯示,一般要先經(jīng)過投影變換、消隱和裁剪處理、顏色與光照處理、紋理映射四個(gè)基本步驟,之后還可以根據(jù)需要在模型上疊加相應(yīng)的地物模型、矢量要素等。這些理論與方法均是計(jì)算機(jī)圖形學(xué)中真實(shí)感圖形生成算法的重要組成部分。</p><p>  6.1.4用OpenGL構(gòu)造三維地形景觀流程

94、圖</p><p>  如圖4.2.1所示:</p><p>  圖6.1 OpenGL構(gòu)造三維地形景觀基本流程圖</p><p>  6.1.5 具體實(shí)現(xiàn)</p><p> ?。?)數(shù)據(jù)準(zhǔn)備及預(yù)處理 用于構(gòu)造三維地形景觀的數(shù)據(jù)包括DEM數(shù)據(jù)和紋理數(shù)據(jù)。DEM數(shù)據(jù)的</p><p>  處理包括不同格式DEM間的轉(zhuǎn)

95、化、DEM 數(shù)據(jù)簡化、格網(wǎng)DEM 與TIN間的相互轉(zhuǎn)化等;紋理數(shù)據(jù)的處理包括圖像格式轉(zhuǎn)化、圖像裁切等。</p><p> ?。?)設(shè)置基本參數(shù) 在用OpenGL繪制三維地形模型和進(jìn)行紋理映射前,需要設(shè)置相關(guān)的景觀參數(shù)值。這些參數(shù)包括光源性質(zhì)(鏡射光、漫射光和環(huán)境光)、光源方位(距離和方向)、顏色模式(索引模式或RGBA模式)、明暗處理方式(平滑處理或平面處理)、紋理映射方式等。除此之外還需設(shè)定視點(diǎn)位置和視線

96、方向。這些參數(shù)設(shè)置都可以通過對OpenGL的相關(guān)函數(shù)的參數(shù)選擇來實(shí)現(xiàn)。</p><p> ?。?)構(gòu)造地形模型三維地形模型的基本構(gòu)造通常是以三角面為單元的。三角面的明亮程度除取決于光源和明暗處理方式外,還受到點(diǎn)與面的法向量的影響。一般點(diǎn)的法向量取值為其周圍面法向量的均值。在圖3中P點(diǎn)的法向量即可表示為與其相鄰的四個(gè)面法向量N1、N2、N3、N4的和的平均值。</p><p>  這樣三維模

97、型的構(gòu)造可由下列程序給出:</p><p>  glBegin(GL_TRIANGLES_STRIP);</p><p>  glNormal3fv(N0); //設(shè)置頂點(diǎn)法向量</p><p>  glVertex3f(v0); //設(shè)置頂點(diǎn)坐標(biāo)</p><p>  glNormal3fv(N1);</p><

98、p>  glVertex3f(v1);</p><p><b>  ……</b></p><p><b>  glEnd();</b></p><p>  構(gòu)造模型的同時(shí),還可以對模型進(jìn)行平移、旋轉(zhuǎn)和縮放等變換,以實(shí)現(xiàn)各種不同的模型造型。</p><p>  (4)投影變換 投影變換一般分

99、為透視投影變換和正射投影變換兩類。投影方式的選擇取決于顯示的內(nèi)容和用途。由于透視投影類似于人眼對客觀世界的觀察方式,因而廣泛應(yīng)用于三維地形模擬、飛行仿真、步行穿越仿真等模擬人眼視覺效果的研究領(lǐng)域。但如果需要觀察模型某一個(gè)側(cè)面不帶有形變的景觀,則更多采用正射投影方式,如制作地形暈渲圖則一般采用正射投影方式。OpenGL只繪制位于視景體內(nèi)的對象,在設(shè)置投影變換時(shí)要充分考慮模型的大小以便選擇合適的視景體范圍。</p><p

100、>  圖6.2 表示用于透視投影變換的視景體</p><p>  圖6.3 表示用于正射投影變換的視景體</p><p>  (5)視口變換 視口是指計(jì)算機(jī)屏幕中的矩形繪圖區(qū)域,它用窗口坐標(biāo)來度量,反映了屏幕上的像素位置。視口相對于窗口的左下角。視口變換的目的就是將三維空間坐標(biāo)映射為計(jì)算機(jī)屏幕上的二維平面坐標(biāo)。視口變換用函數(shù)glViewport()實(shí)現(xiàn),視口的寬高比通常等于視景體

101、的寬高比,否則視口內(nèi)顯示的圖形將會發(fā)生形變。根據(jù)視口變換后視口內(nèi)每一點(diǎn)的z坐標(biāo)值,OpenGL可以自動實(shí)現(xiàn)消隱功能,使得靠近視點(diǎn)的目標(biāo)能夠遮擋視口同一位置遠(yuǎn)離視點(diǎn)的目標(biāo)。</p><p>  (6)紋理映射 紋理映射是建立逼真三維地形景觀的重要手段,不采用紋理映射所得到的地形模</p><p>  型僅僅是具有明暗效果的光照模型,光照模型可以按照高程值進(jìn)行過渡著色或分層設(shè)色。它能夠直觀地

102、反映地表起伏狀況,但不能重現(xiàn)地表的真實(shí)面貌。</p><p>  一般紋理映射的思路是把紋理圖像“貼”到由DEM數(shù)據(jù)所構(gòu)成的三維模型上。其關(guān)鍵是實(shí)現(xiàn)影像與DEM之間的正確套合,使每個(gè)DEM格網(wǎng)點(diǎn)與其所在的圖像位置一一對應(yīng)。為提高紋理映射的運(yùn)算效率,通常采用預(yù)處理好的與DEM坐標(biāo)相對應(yīng)的圖像作為紋理以免除紋理坐標(biāo)的計(jì)算。用OpenGL函數(shù)進(jìn)行紋理映射的基本步驟為:</p><p>  紋理定

103、義:用glTexImage2D*()函數(shù)說明所映射的紋理內(nèi)容。其中包括紋理數(shù)據(jù)的指針、紋理的大小、紋理的類別(灰度或彩色)等。</p><p>  紋理控制:說明紋理以何種方式映射到三維模型表面上。OpenGL 提供了多種映射方式,其中包括紋理濾波、重復(fù)與縮限,其函數(shù)為glTexParameter*()。</p><p>  紋理的映射方式說明:在紋理映射過程中,可以用紋理來調(diào)整三維模型的

104、顏色或者將紋理與三維模型原來的顏色進(jìn)行融合,其調(diào)用函數(shù)為glTexEnv*()。</p><p>  三維模型頂點(diǎn)的紋理坐標(biāo)與幾何坐標(biāo)定義及場景繪制:幾何坐標(biāo)決定了頂點(diǎn)在屏幕上的繪制位置,調(diào)用函數(shù)為glVertex*();紋理坐標(biāo)決定紋理圖像中哪一個(gè)紋理單元賦予該頂點(diǎn),調(diào)用函數(shù)為glTexCoord*();再在glBegin()中選擇一定的繪制參數(shù)如:GL_QUAD_STRIP 或GL_TRLANGLE_STRI

105、P等,就可以實(shí)現(xiàn)帶紋理的場景繪制。</p><p><b>  6.2天空的構(gòu)造</b></p><p>  相對于構(gòu)造地面,構(gòu)造天空顯的簡單許多,本實(shí)驗(yàn)是用五張連續(xù)的天空圖片,夠成一個(gè)天空盒。并伴隨著攝像機(jī)的移動而移動,始終以攝像機(jī)為中心,這樣在玩家看起來就像是永遠(yuǎn)也走不到天邊。相對于其他的構(gòu)造天空的方法,這種方法明顯的優(yōu)勢是其計(jì)算量少,代碼自然也少了許多,有利于游

106、戲的運(yùn)行。當(dāng)然他的變化性就少了,缺乏新鮮感。</p><p>  OpenGL的坐標(biāo)系于數(shù)學(xué)里德坐標(biāo)系有一點(diǎn)區(qū)別,如圖4.2.1所示為OpenGL的坐標(biāo)系;圖4.2.2為數(shù)學(xué)里的坐標(biāo)系。</p><p>  圖6.3 OpenGL的坐標(biāo)系 圖6.4 世界坐標(biāo)系</p><p>  下圖為OpenGL天空構(gòu)造時(shí),要載

107、入的五張bmp格式的位圖所要綁定的紋理空間圖,除去地面的5張位圖。</p><p><b>  五張?zhí)炜瘴粓D為:</b></p><p>  圖6.5 背面位圖back.bmp</p><p>  圖6.6前面位圖Font.bmp</p><p>  圖6.7 左邊位圖Left.bmp</p><p&

108、gt;  圖6.8右邊位圖 Right.bmp</p><p>  圖6.9 天空紋理載入坐標(biāo)圖</p><p>  本實(shí)驗(yàn)是用CBMPLoader m_texture[5];將五張下好的天空紋理圖分別載入到如上圖所示的空間中,分別為前(front)、后(back)、左(left)、右(right)、上(top)。在每次進(jìn)行矩陣變換前都要用glPushMatrix()進(jìn)行入棧,然后用gl

109、PopMatrix()出棧,這樣操作不至于影響后面的矩陣操作。glTranslate()的作用是每一次操作都把當(dāng)前所在的位置作為原點(diǎn)。glRotatef()每一次操作都是相對于當(dāng)前原點(diǎn)的(而不是屏幕的中央)</p><p><b>  其基本步驟如下:</b></p><p>  第一步 定義數(shù)組用來保存文件名:</p><p>  char

110、*bmpName[] = { "back","front","top","left","right"};</p><p>  for(int i=0; i< 5; i++)</p><p><b>  {</b></p><p>  spr

111、intf(filename,"data/%s",bmpName[i]);</p><p>  strcat(filename,".bmp");</p><p>  第二步:生成紋理對象數(shù)組</p><p>  glGenTextures(1, &m_texture[i].ID); </p>&l

112、t;p>  第三步:通過使用glBindTexture選擇紋理對象,來完成該紋理對象的定義。</p><p>  glBindTexture(GL_TEXTURE_2D, m_texture[i].ID); </p><p>  第四步:在繪制景物之前通過glBindTexture,為該景物加載相應(yīng)的紋理。 gluBuild2DMipmaps(GL_TEXTURE_2D, GL

113、_RGB, m_texture[i].imageWidth,</p><p>  m_texture[i].imageHeight, GL_RGB, GL_UNSIGNED_BYTE,</p><p>  m_texture[i].image);</p><p>  第五步:在程序結(jié)束之前調(diào)用glDeleteTextures刪除紋理對象。</p>&l

114、t;p>  這里定義了一個(gè)析構(gòu)函數(shù):CSkyBox::~CSkyBox()來實(shí)現(xiàn)釋放所占用的內(nèi)存</p><p>  CSkyBox::~CSkyBox()</p><p><b>  {</b></p><p>  for(int i =0 ;i< 5; i++)</p><p><b>  {&

115、lt;/b></p><p>  m_texture[i].FreeImage();</p><p>  glDeleteTextures(1,&m_texture[i].ID);</p><p><b>  }</b></p><p><b>  }</b></p>&

116、lt;p>  如下是一部分核心代碼的實(shí)現(xiàn):</p><p>  glPushMatrix(); glTranslatef(m_CameraPos.x,m_CameraPos.y,m_CameraPos.z);</p><p>  glRotatef(yRot,0.0f,1.0f,0.0f);<

117、/p><p>  /** 繪制背面*/</p><p>  glBindTexture(GL_TEXTURE_2D, m_texture[0].ID);//GL_TEXTURE_2D:繪制2D紋理</p><p>  glBegin(GL_QUADS);</p><p>  /** 指定紋理坐標(biāo)和頂點(diǎn)坐標(biāo)*/</p><p

118、>  glTexCoord2f(1.0f, 0.0f); glVertex3f( width, -height, -length);</p><p>  glTexCoord2f(1.0f, 1.0f); glVertex3f( width, height, -length); </p><p>  glTexCoord2f(0.0f, 1.0f); glVertex3f( -

溫馨提示

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

最新文檔

評論

0/150

提交評論