簡(jiǎn)介
在前面的幾篇博客中,我們主要是使用正方體來(lái)做相關(guān)內(nèi)容介紹.但是在日常的圖形程序中,我們通常都會(huì)使用非常復(fù)雜且好玩的模型,它們比正方體要好看多了。然而,和正方體對(duì)象不同,我們不太能夠?qū)ο袷欠孔印⑵?chē)或者人形角色這樣的復(fù)雜形狀手工定義所有的頂點(diǎn)、法線和紋理坐標(biāo)。我們想要的是將這些模型(Model)導(dǎo)入(Import)到程序當(dāng)中。模型通常都由3D藝術(shù)家在Blender、3DS Max或者Maya這樣的工具中精心制作。
這些所謂的3D建模工具(3D Modeling Tool)可以讓藝術(shù)家創(chuàng)建復(fù)雜的形狀,并使用一種叫做UV映射的手段來(lái)應(yīng)用貼圖。這些工具將會(huì)在導(dǎo)出到模型文件的時(shí)候自動(dòng)生成所有的頂點(diǎn)坐標(biāo)、頂點(diǎn)法線以及紋理坐標(biāo)。這樣子藝術(shù)家們即使不了解圖形技術(shù)細(xì)節(jié)的情況下,也能擁有一套強(qiáng)大的工具來(lái)構(gòu)建高品質(zhì)的模型了。所有的技術(shù)細(xì)節(jié)都隱藏在了導(dǎo)出的模型文件中。但是,作為圖形開(kāi)發(fā)者,我們就必須要了解這些技術(shù)細(xì)節(jié)了。
所以,我們的工作就是解析這些導(dǎo)出的模型文件以及提取所有有用的信息,將它們儲(chǔ)存為OpenGL能夠理解的格式。一個(gè)很常見(jiàn)的問(wèn)題是,模型的文件格式有很多種,每一種都會(huì)以它們自己的方式來(lái)導(dǎo)出模型數(shù)據(jù)。像結(jié)尾是.obj模型格式,只包含了模型數(shù)據(jù)以及材質(zhì)信息,還有模型顏色和漫反射/鏡面光貼圖。而以XML為基礎(chǔ)的Collada文件格式則非常的豐富,包含模型、光照、多種材質(zhì)、動(dòng)畫(huà)數(shù)據(jù)、攝像機(jī)、完整的場(chǎng)景信息等等。結(jié)尾是.obj格式通常被認(rèn)為是一個(gè)易于解析的模型格式。
總而言之,不同種類(lèi)的文件格式有很多,它們之間通常并沒(méi)有一個(gè)通用的結(jié)構(gòu)。所以如果我們想從這些文件格式中導(dǎo)入模型的話,我們必須要去自己對(duì)每一種需要導(dǎo)入的文件格式寫(xiě)一個(gè)導(dǎo)入器。很幸運(yùn)的是,正好有一個(gè)庫(kù)專(zhuān)門(mén)處理這個(gè)問(wèn)題。
模型加載庫(kù)
一個(gè)非常流行的模型導(dǎo)入庫(kù)是Assimp,它是Open Asset Import Library(開(kāi)放的資產(chǎn)導(dǎo)入庫(kù))的縮寫(xiě)。Assimp能夠?qū)牒芏喾N不同的模型文件格式(并也能夠?qū)С霾糠值母袷剑?,它?huì)將所有的模型數(shù)據(jù)加載至Assimp的通用數(shù)據(jù)結(jié)構(gòu)中。當(dāng)Assimp加載完模型之后,我們就能夠從Assimp的數(shù)據(jù)結(jié)構(gòu)中提取我們所需的所有數(shù)據(jù)了。由于Assimp的數(shù)據(jù)結(jié)構(gòu)保持不變,不論導(dǎo)入的是什么種類(lèi)的文件格式,它都能夠?qū)⑽覀儚倪@些不同的文件格式中抽象出來(lái),用同一種方式訪問(wèn)我們需要的數(shù)據(jù)。
當(dāng)使用Assimp導(dǎo)入一個(gè)模型的時(shí)候,它通常會(huì)將整個(gè)模型加載進(jìn)一個(gè)場(chǎng)景(Scene)對(duì)象,它會(huì)包含導(dǎo)入的模型/場(chǎng)景中的所有數(shù)據(jù)。Assimp會(huì)將場(chǎng)景載入為一系列的節(jié)點(diǎn)(Node),每個(gè)節(jié)點(diǎn)包含了場(chǎng)景對(duì)象中所儲(chǔ)存數(shù)據(jù)的索引,每個(gè)節(jié)點(diǎn)都可以有任意數(shù)量的子節(jié)點(diǎn)。Assimp數(shù)據(jù)結(jié)構(gòu)的(簡(jiǎn)化)模型如下:

- 和材質(zhì)和網(wǎng)格(Mesh)一樣,所有的場(chǎng)景/模型數(shù)據(jù)都包含在
Scene對(duì)象中。Scene對(duì)象也包含了場(chǎng)景根節(jié)點(diǎn)的引用。 - 場(chǎng)景的
Root node(根節(jié)點(diǎn))可能包含子節(jié)點(diǎn)(和其它的節(jié)點(diǎn)一樣),它會(huì)有一系列指向場(chǎng)景對(duì)象中mMeshes數(shù)組中儲(chǔ)存的網(wǎng)格數(shù)據(jù)的索引。Scene下的mMeshes數(shù)組儲(chǔ)存了真正的Mesh對(duì)象,節(jié)點(diǎn)中的mMeshes數(shù)組保存的只是場(chǎng)景中網(wǎng)格數(shù)組的索引。 - 一個(gè)
Mesh對(duì)象本身包含了渲染所需要的所有相關(guān)數(shù)據(jù),像是頂點(diǎn)位置、法向量、紋理坐標(biāo)、面(Face)和物體的材質(zhì)。 - 一個(gè)網(wǎng)格包含了多個(gè)面。
Face代表的是物體的渲染圖元(Primitive)(三角形、方形、點(diǎn))。一個(gè)面包含了組成圖元的頂點(diǎn)的索引。由于頂點(diǎn)和索引是分開(kāi)的,使用一個(gè)索引緩沖來(lái)渲染是非常簡(jiǎn)單的。 - 最后,一個(gè)網(wǎng)格也包含了一個(gè)
Material對(duì)象,它包含了一些函數(shù)能讓我們獲取物體的材質(zhì)屬性,比如說(shuō)顏色和紋理貼圖(比如漫反射和鏡面光貼圖)。
所以,我們需要做的第一件事是將一個(gè)物體加載到Scene對(duì)象中,遍歷節(jié)點(diǎn),獲取對(duì)應(yīng)的Mesh對(duì)象(我們需要遞歸搜索每個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)),并處理每個(gè)Mesh對(duì)象來(lái)獲取頂點(diǎn)數(shù)據(jù)、索引以及它的材質(zhì)屬性。最終的結(jié)果是一系列的網(wǎng)格數(shù)據(jù),我們會(huì)將它們包含在一個(gè)Model對(duì)象中。
網(wǎng)格
當(dāng)使用建模工具對(duì)物體建模的時(shí)候,藝術(shù)家通常不會(huì)用單個(gè)形狀創(chuàng)建出整個(gè)模型。通常每個(gè)模型都由幾個(gè)子模型/形狀組合而成。組合模型的每個(gè)單獨(dú)的形狀就叫做一個(gè)網(wǎng)格(Mesh)。比如說(shuō)有一個(gè)人形的角色:藝術(shù)家通常會(huì)將頭部、四肢、衣服、武器建模為分開(kāi)的組件,并將這些網(wǎng)格組合而成的結(jié)果表現(xiàn)為最終的模型。一個(gè)網(wǎng)格是我們?cè)贠penGL中繪制物體所需的最小單位(頂點(diǎn)數(shù)據(jù)、索引和材質(zhì)屬性)。一個(gè)模型(通常)會(huì)包括多個(gè)網(wǎng)格。
下一篇研究如何編譯assimp 模型庫(kù)并導(dǎo)入到ios 工程中去