加載模型-01.Assimp開源模型導(dǎo)入庫(kù)

我們無(wú)法像定義容器盒一樣手動(dòng)地去指定房子、貨車或人形角色這些復(fù)雜模型的頂點(diǎn)、法線和紋理坐標(biāo)。我們需要做的也是應(yīng)該要做的,是把這些模型導(dǎo)入到應(yīng)用程序中,而設(shè)計(jì)制作這些3D模型的工作應(yīng)該交給像Blender、3DS Max或者Maya這樣的工具軟件。

那些3D建模工具,可以讓美工們構(gòu)建一些復(fù)雜的形狀,并將貼圖應(yīng)用到形狀上去,即紋理映射。然后,在導(dǎo)出模型文件時(shí),建模工具會(huì)自己生成所有的頂點(diǎn)坐標(biāo)、頂點(diǎn)法線和紋理坐標(biāo)。這樣,美工們可以不用了解大量的圖像技術(shù)細(xì)節(jié),就能有大量的工具集去隨心地構(gòu)建高品質(zhì)的模型。所有的技術(shù)細(xì)節(jié)內(nèi)容都隱藏在里導(dǎo)出的模型文件里。而我們,這些圖形開發(fā)者,就必須得去關(guān)注這些技術(shù)細(xì)節(jié)了。

因此,我們的工作就是去解析這些導(dǎo)出的模型文件,并將其中的模型數(shù)據(jù)存儲(chǔ)為OpenGL能夠使用的數(shù)據(jù)。

一個(gè)常見的問題是,導(dǎo)出的模型文件通常有幾十種格式,不同的工具會(huì)根據(jù)不同的文件協(xié)議把模型數(shù)據(jù)導(dǎo)出到不同格式的模型文件中。有的模型文件格式只包含模型的靜態(tài)形狀數(shù)據(jù)和顏色、漫反射貼圖、高光貼圖這些基本的材質(zhì)信息,比如Wavefront的.obj文件。而有的模型文件則采用XML來(lái)記錄數(shù)據(jù),且包含了豐富的模型、光照、各種材質(zhì)、動(dòng)畫、攝像機(jī)信息和完整的場(chǎng)景信息等,比如Collada文件格式。Wavefront的obj格式是為了考慮到通用性而設(shè)計(jì)的一種便于解析的模型格式。建議去Wavefront的Wiki上看看obj文件格式是如何封裝的。這會(huì)給你形成一個(gè)對(duì)模型文件格式的一個(gè)基本概念和印象。

模型加載庫(kù)

現(xiàn)在市面上有一個(gè)很流行的模型加載庫(kù),叫做Assimp,全稱為Open Asset Import Library。Assimp可以導(dǎo)入幾十種不同格式的模型文件(同樣也可以導(dǎo)出部分模型格式)。只要Assimp加載完了模型文件,我們就可以從Assimp上獲取所有我們需要的模型數(shù)據(jù)。Assimp把不同的模型文件都轉(zhuǎn)換為一個(gè)統(tǒng)一的數(shù)據(jù)結(jié)構(gòu),所有無(wú)論我們導(dǎo)入何種格式的模型文件,都可以用同一個(gè)方式去訪問我們需要的模型數(shù)據(jù)。

當(dāng)導(dǎo)入一個(gè)模型文件時(shí),即Assimp加載一整個(gè)包含所有模型和場(chǎng)景數(shù)據(jù)的模型文件到一個(gè)scene對(duì)象時(shí),Assimp會(huì)為這個(gè)模型文件中的所有場(chǎng)景節(jié)點(diǎn)、模型節(jié)點(diǎn)都生成一個(gè)具有對(duì)應(yīng)關(guān)系的數(shù)據(jù)結(jié)構(gòu),且將這些場(chǎng)景中的各種元素與模型數(shù)據(jù)對(duì)應(yīng)起來(lái)。下圖展示了一個(gè)簡(jiǎn)化的Assimp生成的模型文件數(shù)據(jù)結(jié)構(gòu):

  • 所有的模型、場(chǎng)景數(shù)據(jù)都包含在Scene對(duì)象中,如所有的材質(zhì)和Mesh。同樣,場(chǎng)景的根節(jié)點(diǎn)引用也包含在這個(gè)scene對(duì)象中。
  • 場(chǎng)景的根節(jié)點(diǎn)(Root node)可能也會(huì)包含很多子節(jié)點(diǎn)和一個(gè)指向保存模型點(diǎn)云數(shù)據(jù)mMeshes[]的索引集合。根節(jié)點(diǎn)上的mMeshes[]里保存了實(shí)際了Mesh對(duì)象,而每個(gè)子節(jié)點(diǎn)上的mMesshes[]都只是指向根節(jié)點(diǎn)中的mMeshes[]的一個(gè)引用(譯者注:C/C++稱為指針,Java/C#稱為引用)。
  • 一個(gè)Mesh對(duì)象本身包含渲染所需的所有相關(guān)數(shù)據(jù),比如頂點(diǎn)位置、法線向量、紋理坐標(biāo)、面片及物體的材質(zhì)。
  • 一個(gè)Mesh會(huì)包含多個(gè)面片。一個(gè)Face(面片)表示渲染中的一個(gè)最基本的形狀單位,即圖元(基本圖元有點(diǎn)、線、三角面片、矩形面片)。一個(gè)面片記錄了一個(gè)圖元的頂點(diǎn)索引,通過(guò)這個(gè)索引,可以在mMeshes[]中尋找到對(duì)應(yīng)的頂點(diǎn)位置數(shù)據(jù)。頂點(diǎn)數(shù)據(jù)和索引分開存放,可以便于我們使用緩存(VBO、NBO、TBO、IBO)來(lái)高速渲染物體。(詳見Hello Triangle)。
  • 一個(gè)Mesh還會(huì)包含一個(gè)Material(材質(zhì))對(duì)象用于指定物體的一些材質(zhì)屬性。如顏色、紋理貼圖(漫反射貼圖、高光貼圖等)。

所以我們要做的第一件事,就是加載一個(gè)模型文件為Scene對(duì)象,然后獲取每個(gè)節(jié)點(diǎn)對(duì)應(yīng)的Mesh對(duì)象(我們需要遞歸搜索每個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)來(lái)獲取所有的節(jié)點(diǎn)),并處理每個(gè)Mesh對(duì)象對(duì)應(yīng)的頂點(diǎn)數(shù)據(jù)、索引以及它的材質(zhì)屬性。最終我們得到一個(gè)只包含我們需要的數(shù)據(jù)的Mesh集合。(在03.模型中體現(xiàn))(The result is then a collection of mesh data that we want to contain in a single Model object.)

Mesh(網(wǎng)格,或被譯為“模型點(diǎn)云”)
用建模工具構(gòu)建物體時(shí),美工通常不會(huì)直接使用單個(gè)形狀來(lái)構(gòu)建一個(gè)完整的模型。一般來(lái)說(shuō),一個(gè)模型會(huì)由幾個(gè)子模型/形狀組合拼接而成。而模型中的那些子模型/形狀就是我們所說(shuō)的一個(gè)Mesh。例如一個(gè)人形模型,美工通常會(huì)把頭、四肢、衣服、武器這些組件都分別構(gòu)建出來(lái),然后在把所有的組件拼合在一起,形成最終的完整模型。一個(gè)Mesh(包含頂點(diǎn)、索引和材質(zhì)屬性)是我們?cè)贠penGL中繪制物體的最小單位。一個(gè)模型通常有多個(gè)Mesh組成。

下一節(jié)教程中,我們將用上述描述的數(shù)據(jù)結(jié)構(gòu)來(lái)創(chuàng)建我們自己的Model類和Mesh類,用于加載和保存那些導(dǎo)入的模型。如果我們想要繪制一個(gè)模型,我們不會(huì)去渲染整個(gè)模型,而是去渲染這個(gè)模型所包含的所有獨(dú)立的Mesh。

在開始導(dǎo)入模型之前,我們需要先把Assimp包含到我們的工程中。

構(gòu)建Assimp

你可以在Assimp的下載頁(yè)面選擇一個(gè)想要的版本去下載Assimp庫(kù)。到目前為止,Assimp可用的最新版本是3.1.1。我們建議你自己編譯Assimp庫(kù),因?yàn)锳ssimp官方的已編譯庫(kù)不能很好地覆蓋在所有平臺(tái)上運(yùn)行。如果你忘記怎樣使用CMake編譯一個(gè)庫(kù),請(qǐng)?jiān)斠?a target="_blank" rel="nofollow">Creating a window(創(chuàng)建一個(gè)窗口)教程。

這里我們列出一些編譯Assimp時(shí)可能遇到的問題,以便大家參考和排除:

  • CMake在讀取配置列表時(shí),報(bào)出與DirectX庫(kù)丟失相關(guān)的一些錯(cuò)誤。報(bào)錯(cuò)如下:
    Could not locate DirectXCMake Error at cmake-modules/FindPkgMacros.cmake:110 (message):Required library DirectX not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.
    這個(gè)問題的解決方案:如果你之前沒有安裝過(guò)DirectX SDK,那么請(qǐng)安裝。下載地址:DirectX SDK
  • 安裝DirectX SDK時(shí),可以遇到一個(gè)錯(cuò)誤碼為S1023的錯(cuò)誤。遇到這個(gè)問題,請(qǐng)?jiān)诎惭bDirectX SDK前,先安裝C++ Redistributable package(s)。 問題解釋::已知問題:DirectX SDK (June 2010) 安裝及S1023錯(cuò)誤
  • 一旦配置完成,你就可以生成解決方案文件了,打開解決方案文件并編譯Assimp庫(kù)(編譯為Debug版本還是Release版本,根據(jù)你的需要和心情來(lái)定吧)
  • 使用默認(rèn)配置構(gòu)建的Assimp是一個(gè)動(dòng)態(tài)庫(kù),所以我們需要把編譯出來(lái)的assimp.dll文件拷貝到我們自己程序的可執(zhí)行文件的同一目錄里(I:\vs\OpenGL\Debug)
  • 編譯出來(lái)的Assimp的LIB文件和DLL文件可以在code/Debug或者code/Release里找到
  • 把編譯好的LIB文件和DLL文件拷貝到工程的相應(yīng)目錄下,并鏈接到你的解決方案中。同時(shí)還好記得把Assimp的頭文件也拷貝到工程里去(Assimp的頭文件可以在include目錄里找到)

如果你想要讓Assimp使用多線程支持來(lái)提高性能,你可以使用Boost庫(kù)來(lái)編譯 Assimp。在Boost安裝頁(yè)面,你能找到關(guān)于Boost的完整安裝介紹。

現(xiàn)在,你應(yīng)該已經(jīng)能夠編譯Assimp庫(kù),并鏈接Assimp到你的工程里去了。下一節(jié)內(nèi)容:導(dǎo)入完美的3D物件!


拓展閱讀:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容