魔兽世界客户端数据研究(三)
終于決定,還是通過wow model viewer起手,研究一下WOW的數據類型,從另一個角度,體驗一把這個唯一讓我充過值的游戲。
這將是一系列隨筆,即在讀代碼的時候,順便記錄,以理清思路和加深映象。 其中會有很多讓人費解的地方,如果有幸被某位兄弟看見
,請勿見笑。
?
今天來說一下M2中的LOD的數據
WOW中,為了降低遠處模型的渲染開銷,為模型做了LOD,即遠處的模型,使用更少的頂點,更粗略的材質。 比如遠處的模型在渲染的時
候,面片數量減少,關閉光照,不渲染掛接的特效等等。
因此,不用證明也知道,M2中,材質是存在每一個LOD信息中的。
哎,也就寫這幾句的時候順手些,其實不用分析,也是這個結果。因為我們自己的引擎就是這樣做的,何況是WOW這種大師級的作品呢。
從WMV的解析代碼下手,看看它是如何解析的吧。
首先,它使用了這樣一行代碼
int16 *transLookup = (int16*)(f.getBuffer() + header.ofsTransparencyLookup);
讀取了一串用于透明值的查找數組。 不過暫時沒有使用,后面材質構建的地方才會用到。
接下來,就是讀取相關數據了。 在WLK以后,所有的這些數據,被分離到了.skin文件里面,不知道是咱想的,以后再來作討論。 但是在
WLK之前,這個數據還是被放在了一起的。
通過模型的名字我們組合上.skin,就是當前所要的渲染數據了。
這個組合是這樣的。
假如我們一個模型是 humanmale.m2
那么它的四個LOD數據分別就是 humanmale01.skin humanmale02.skin humanmale03.skin humanmale04.skin
當我們得到了這個數據后,就可以通過MPQFile加載想要的數據了。
OK,假設上面的過程,我們已經完全搞定了,此時,我們就得到了一個skin的數據。有了這個數據,我們就可以為所欲為了,嘿嘿。有點
夸張了。 在這個數據的最前面,肯定是數據頭了。 數據頭在WMV中本來一直是以xxxxHeader來定義的,不過在這里,它一改風格,定義
了一個叫ModelView的東西。
我們來看看這貨的定義
struct ModelView
{
#ifdef WotLK
??? char id[4]; //巫妖王版本新增的一個標記位,必須是 'S' 'K' 'I' 'N'
#endif
??? uint32 nIndex; //這個表示此LOD有多少個INDEX
??? uint32 ofsIndex; //這個表示此LOD的INDEX從模型的哪里開始數
??? uint32 nTris; //這個表示此LOD有多少個構建成三角形的索引
??? uint32 ofsTris;???? //三角形個數
??? uint32 nProps; //額外的頂點屬性
??? uint32 ofsProps; //頂點屬性讀取
??? uint32 nSub; //有多少個子部件 后面定義的ModelGeoset表示一個子部件,其包括了MESH數據,材質,渲染狀態等內容
??? uint32 ofsSub;???? //
??? uint32 nTex;? //紋理
??? uint32 ofsTex;???? // ModelTexUnit, material properties/textures
??? int32 lod;???????????????? // LOD bias?? WMV作者也打了問號。
};
有了這個數據頭以后,我們就可以無腦的先讀取上面的數據,然后再進行構建。
索引數據
uint16 *indexLookup = (uint16*)(g.getBuffer() + view->ofsIndex);
構成三角形的頂點索引序列
uint16 *triangles = (uint16*)(g.getBuffer() + view->ofsTris);
當前模型在渲染時候的索引數目
nIndices = view->nTris;
重新分配索引
wxDELETEA(indices);
indices = new uint16[nIndices];
將本地索引轉換成全局索引
for (size_t i = 0; i<nIndices; i++)
{
??????? indices[i] = indexLookup[triangles[i]];
}
索引數據總算是完了,下面就得準備子模型和材質相關的事情。
大家都知道,在渲染管線中,一次渲染提交只能提交具有相同渲染狀態和紋理的模型。 于是,我們的模型如果具有不同的材質,就需要
先做分割處理。 這是所有WOW這樣的3D MMORPG引擎都需要處理的問題。
在WMV中,模型渲染狀態相關的數據,使用了ModelGeoset來表示,紋理相關的,使用了ModelTexUnit來表示
先看看ModelGeoset的定義
/// Lod part, One material + render operation
struct ModelGeoset
{
??? uint32 id;??????? // mesh part id?
??? uint16 vstart;??? // first vertex, Starting vertex number.
??? uint16 vcount;??? // num vertices, Number of vertices.
??? uint16 istart;??? // first index, Starting triangle index (that's 3* the number of triangles drawn so far).
??? uint16 icount;??? // num indices, Number of triangle indices.
??? uint16 nSkinnedBones;??? // number of bone indices, Number of elements in the bone lookup table.
??? uint16 StartBones;??????? // ? always 1 to 4, Starting index in the bone lookup table.
??? uint16 rootBone;??????? // root bone?
??? uint16 nBones;??????? //
??? Vec3D BoundingBox[2];
??? float radius;
};
由上可知,它定義了渲染相關的頂點,以及骨骼,和包圍盒信息,最后一個是作為構建包圍球用的。
/// Lod part, A texture unit (sub of material)
struct ModelTexUnit
{
??? // probably the texture units
??? // size always >=number of materials it seems
??? uint16 flags;??????? // Usually 16 for static textures, and 0 for animated textures.
??? uint16 shading;??????? // If set to 0x8000: shaders. Used in skyboxes to ditch the need for depth buffering.
See below.
??? uint16 op;??????????? // Material this texture is part of (index into mat)
??? uint16 op2;??????????? // Always same as above?
??? int16 colorIndex;??? // A Color out of the Colors-Block or -1 if none.
??? uint16 flagsIndex;??? // RenderFlags (index into render flags, TexFlags)
??? uint16 texunit;??????? // Index into the texture unit lookup table.
??? uint16 mode;??????? // See below.
??? uint16 textureid;??? // Index into Texture lookup table
??? uint16 texunit2;??? // copy of texture unit value?
??? uint16 transid;??????? // Index into transparency lookup table.
??? uint16 texanimid;??? // Index into uvanimation lookup table.
};
而上面這個結構,是紋理相關的信息。
上面的信息,都是一些索引和ID值,真正的數據是放在全局信息中的。
讀取完上面的數據后,LOD信息基本上就大功造成了。 而這些索引是如何使用的,只有下一次再研究了。今天又很晚了。
由此可知,WOW中的數據組織和一般的引擎沒有太多區別。 即HEADER信息用于分割數據區域。
整個模型要使用的數據,放在了最上層,然后,不同的LOD和子MESH要使用數據的時候,只需要保存一些索引值,再到全局數據里去查詢就可以了。
暫時到此吧,下次繼續。。。。
轉載于:https://www.cnblogs.com/qilinzi/archive/2013/04/26/3043890.html
總結
以上是生活随笔為你收集整理的魔兽世界客户端数据研究(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ansible入门及组件介绍
- 下一篇: 多个页面同时跳转到一个页面,然后返回到上