5.2 地圖編輯系統
5.2.3 製作地表
製作好地形高度圖的「.raw」檔之後,由 cMAP 類別下的 Loadmap() 函式呼叫 LoadRawFile()後,LoadRawFile()會將 raw 檔案中的資料 讀入記憶體,並且回傳陣列給 Loadmap()。Loadmap()將陣列的內容 做分析後,將檔案中每一個對應點的明亮度數值讀出來,經由簡短的 程式碼將數值放大十倍後存入陣列 m_TexturePool 中。
圖 5-4 讀入 raw 檔的步驟
讀入所有的座標高度之後,再利用 OpenGL 的繪圖功能,把整個 地圖的骨架建構起來。首先是原本已經存好的平面座標(X,Y),之後 再把剛剛完成的高度座標(Z)跟平面座標,合成一個點的完整立體 座標(X,Y,Z)。程式中所有的面都是由三角型組合而成,也就是三個 點的座標會先構成最基本的面,之後再由許多的三角形面組成不同的 地形。如圖 5-5、5-6。
簡易3D多人線上遊戲系統
圖 5-5 由三角形構成的地表
圖 5-6 由三角形構成的地表
另外 OpenGL 之中有一個很重要的功能,可以在繪製平面三角形 的時候大量減少記憶體的使用。一般陣列的儲存方法,是將每個點的 座標一一存起來,然後每讀出三個點的座標之後再組合成一個三角 形。但這種方法其實浪費掉許多不必要的記憶體空間,因為每一個三 角形的三個點座標是跟前一個三角形的座標重複的,沒有必要再把它 當作另一組數據存起來。在 OpenGL 中,只要按照特定的步驟把點的 座標按順序存入陣列中,那麼在繪圖的時後,程式會自動判斷座標間 的關係,把新讀入的一組座標,跟前兩組座標合成一組新的平面。這 樣不只能夠更快的繪出圖形,更有效的節省了將近 2/3 的記憶體資 源。
圖 5-7 中,實心的圓點代表最近一次讀入的點座標,空心的圓點 代表已經讀完的資料。由上圖可知ㄧ般的方式儲存資料,畫出三個完 整的三角形,需要用到 9 個單位的繪圖時間以及 27 個記憶體位置,
而且其中有大半的資料是重複的。這麼做不僅沒有節省記憶體空間,
而且沒有辦法加速 3D 繪圖的速度,後者更是製作遊戲時最忌諱的情 況之一。
圖 5-7 一般程式的陣列讀取法
簡易3D多人線上遊戲系統
角 型 加 速 繪 圖 法 , 就 是 節 省 記 憶 體 並 加 速 繪 圖 的 函 式 之 ㄧ 。 m_TexturePool 陣列會將內部的資料處理過後,縮減記憶體的使用 量,把重複的點座標資料清除。如此一來就可以照著 OpenGL 的演算 法直接讀入下一個點的座標後,跟仍然保留在記憶體內的前兩組資料 運算,直接在螢幕上畫出下一個三角形。圖 5-8 為 OpenGL 的陣列讀 取方法。
由圖 5-8 可以發現,同樣是畫出三個三角形,OpenGL 的陣列讀 取方法只需要 5 個單位的繪圖時間以及 12 個記憶體位置,而且越往 後畫下去差距會越來越大,到達一般陣列讀取方式的 1/3 左右。這樣 一來不但可以讓遊戲進行的更順暢,還可以減少相當大的記憶體空 間,對一個遊戲程式來講,實在是不可多得的一個優點。
圖 5-8 OpenGL 的陣列讀取法
二、地表貼圖
當畫面上所有的三角形都畫完了之後,算是完成了地形的基本骨 架。如圖 5-9 所示,大致上可以看出整個地形的高低起伏,還可以看
到許許多多的三角形是如何把地形拼湊起來的。但是這樣當然根本不 能算是完成,除了把每一個面畫出來之外,還要把所需要的圖片貼上 去才行。
圖 5-9 部分地圖的透明骨架
在貼圖系統中,我們採用了雙重貼圖的技術。所謂雙重貼圖,就 是視我們的需求,把貼圖拆成幾個層次來個別動作。而在我們地表貼 圖的系統中,把整個貼圖的工作拆為兩個層次:「地面色彩分佈圖」
跟「地面材質貼圖」。
¾ 地面色彩分佈圖
就是指地面所要呈現的顏色。首先參考劇情之後畫出一張符
簡易3D多人線上遊戲系統
¾ 地面材質貼圖
地面除了要有顏色之外,還需要有一張材質貼圖。材質貼圖 可以表現出地表細部的質感,並且做出模擬實物效果的畫面(例 如:岩石、草地、及石磚路面等)。
圖 5-10 地面色彩分佈圖
由圖 5-10 可以很清楚的看出地形上大致的分佈,還有道路的部 份也用灰色表現的很明顯,可以帶領玩家前往會發生劇情事件的關鍵 地點。不過如果地面只有這樣單以顏色來表現的話,會顯的過於單 調。整張圖看起來的感覺雖然還好,但是真的進行遊戲時由於畫面會 放的很大,地面會看起來只有一大塊一樣的顏色,如圖 5-11。
圖 5-11 只用一張地面色彩分布圖時,地面的效果
因此為了刻畫細部的地表,我們使用了另一張材質貼圖,如圖 5-12。將兩張圖重疊,貼在剛剛製作好的地形骨架上,就可以展現出 很棒的地面效果。如圖 5-13。
圖 5-12 地表材質貼圖
簡易3D多人線上遊戲系統
兩種材質不同的是,色彩分佈圖是一整張圖剛好貼滿整個地圖骨 架;而材質貼圖是以小範圍重複貼圖,利用不斷貼上一樣的材質貼圖 而佈滿整張地圖。因為不是放大之後再貼,所以材質貼圖可以展現出 很細微的地面特徵,如此一來整張地圖就能夠非常的完整展現出來。
圖 5-13 貼上材質之後的地面效果
如此一來,地表的製作算是完成了。下一步要在地面上安插原本 預定的 3D 物件,如此一來就可以塑造更完美的地圖。
5.2.4 3D 物件製作 一、3D 物件繪製
使用 SketchUp 軟體編輯。此軟體多半是運用在建物方面,因為 它用來編輯建築物之類的 3D 物件時,非常方便。而這也是我們選擇 使用 SketchUp 而不是使用知名的 3D 編輯軟體(如 3D studio Max、
Strata、及 Maya 等)的原因。相較起來,SketchUp 的編輯程序實在 簡便許多,省下了學習軟體所花費的時間以及編輯 3D 物件的時間。
但由於 SketchUp 軟體比較不常見,以下便介紹編輯 3D 物件的流程、
常遇到的問題、以及解決方法。
根據先前列出的 3D 物件列表,決定出要製作的 3D 物件。決定好 之後先以手工繪出物件的初步模型,不必在意畫的詳不詳細,重點著 重於整體的架構表現,以便於實際製作的時候,能夠很清楚的知道整 個物件的結構,不僅在製作的過程中能夠得心應手,也會節省不少製 作的時間。如圖 5-14 的神廟初步模型草稿圖,所代表的便是我們遊 戲世界中會出現的 3D 物件之一。
簡易3D多人線上遊戲系統
圖 5-14 3D 物件的手繪草稿(神廟-1)
完成草稿圖後,下一步就是依照比例設定出物件的大小(高度座 標不用考慮,我們所要決定的大小是在於物件的平面面積佔了幾 格)。由於之後要設定可走不可走的座標,因此物件的大小要盡量跟 標準格子對齊,如圖 5-15,此舉除了可走不可走的座標好設之外,
也方便地圖的編排。
圖 5-15 正確的 3D 物件大小 圖 5-16 錯誤的 3D 物件大小
圖 5-17 整個物件 圖 5-18 各個元件的分解圖
另外還要注意的是,SketchUp 軟體製作出來的 3ds 檔,有一項 很麻煩的限制,那就是單一物件中各個元件只能貼一種圖,且只要是 觸碰在一起的不同元件就會被判斷成是單一元件。
因此解決方法就是,如果我們要在同樣一個物件中貼上不同材質 的貼圖,就必須讓各個元件很靠近,但是絕對不能夠碰在一起。如下 圖 5-19、5-20,製作的要訣就是讓各元件之間保持著 1 個單位像素 的距離,這麼一來才可以在地圖上顯示出我們想要的效果。這一個步 驟雖然讓我們在編輯的時候大傷腦筋,但是比起前面所說過的其它軟
簡易3D多人線上遊戲系統
圖 5-19 物件外觀 圖 5-20 元件之間間隔的特寫
製作完成的 3D 物件,利用 SketchUp 的 Import 功能,把原本的
「.skp」檔(SketchUp 專屬檔案格式)輸出成「.3ds」檔,然後利 用系統中 cLoad3ds 類別中的函式多次分析,解讀成 OpenGL 能夠顯示 的格式,再顯示在地圖上。
為什麼要特地將.skp 檔案輸出成.3ds 檔之後才進行解析呢? 理 由是因為.3ds 檔是目前市面上最廣為接受的 3D 物件檔案格式,並且 相容於多種不同的 3D 編輯軟體。而且其檔案架構的特性簡潔明瞭,
捨去許多不必要的繁雜屬性資料,簡單的紀錄不同的點、線、面、及 貼圖的關係,除去了 3D 物件檔案最大的缺點之一,也就是檔案格是 太過龐大的問題;再者,這樣一來也使的我們的系統有更好的擴充 性,不只是能夠解讀 SketchUp 所製作出來的 3D 物件.skp 檔,而是 能夠處理幾乎所有 3D 編輯軟體都能夠輸出的.3ds 檔。
由圖 5-21 及圖 5-22 可發現,一個 skp 檔轉成 3ds 檔的格式之後,
大小相差了幾乎 20 倍,但是解出來的資料仍然可以繪出很完整的 3D 模型。這就是 3ds 檔這麼受歡迎的原因:結構簡潔及檔案小。
圖 5-21 skp 檔案的大小 圖 5-22 3ds 檔案的大小
二、OpenGL 讀 3ds 檔原理
完成一個 3ds 檔之後,我們製作 3D 物件最後的工作,就是要利 用程式把它顯示在遊戲畫面上。由於 OpenGL(其實 DirectX 也是)
之中並沒有直接讀取 3ds 檔案的功能,因此我們要先自己理解 3ds 檔 案的內部架構後,再設計出一套函式把 3ds 檔轉換成 OpenGL 可以讀 取的型態。
這實在是一件大工程,首先先使用 UltraEdit 文件編輯程式打開 一個 3ds 檔,如圖 5-23,這樣我們就可以仔細研究檔案的內部結構。
簡易3D多人線上遊戲系統
圖 5-23 3ds 檔的內容
3ds 檔案內最主要是用所謂的「chunk(典譯通譯:區塊)」來儲 存每一筆資料。在整個 chunk 的最開頭顯示這一個 chunk 的屬性,一 共有以下幾種:
¾ vertices─頂點,也就是代表 3ds 檔案中分佈的線條,由這 些線條的資料才能夠繪出所有的平面。
¾ Face─平面,表示各個由線條組成的三角形平面,由許多的 平面才能夠組合成立體的 3d 物件。(但是檔案中並沒有所謂
「立體物件」的 chunk 類型,因為其實立體物件就是由平面 集合而成的;但是平面在繪圖的觀點來看並不是用線條組成
「立體物件」的 chunk 類型,因為其實立體物件就是由平面 集合而成的;但是平面在繪圖的觀點來看並不是用線條組成