魔獸世界客戶端數(shù)據(jù)研究(一)
終于決定,還是通過wow model viewer起手,研究一下WOW的數(shù)據(jù)類型,從另一個(gè)角度,體驗(yàn)一把這個(gè)唯一讓我充過值的游戲。
這將是一系列隨筆,即在讀代碼的時(shí)候,順便記錄,以理清思路和加深映象。 其中會(huì)有很多讓人費(fèi)解的地方,如果有幸被某位兄弟看見,請勿見笑。
我們從讀取模型數(shù)據(jù)開始。。。
下面是這是頂點(diǎn)結(jié)構(gòu)體 這是wow model viewer中的定義
struct ModelVertex
{
Vec3D pos; //頂點(diǎn)位置
uint8 weights[4];//骨骼權(quán)重
uint8 bones[4];//受影響的骨骼索引
Vec3D normal;//法線
Vec2D texcoords;//紋理坐標(biāo),只有一層
int unk1, unk2; // 總是0,0 可能沒有被使用到
};
讀完頂點(diǎn)數(shù)據(jù)后,我們需要對坐標(biāo)系做一點(diǎn)修正,因?yàn)閃OW用的是Z軸向上, Y軸向里(依稀記得torque也是這樣子)
很多人用得不是太習(xí)慣
若要轉(zhuǎn)換為GL中的坐標(biāo)(Z向外),則 pos = vec3D(pos.x,pos.z,-pos.y);
若要轉(zhuǎn)換為D3D中的坐標(biāo)(Z向里),則pos = vec3D(pos.x,pos.z,pos.y);
法線轉(zhuǎn)換方式和坐標(biāo)一樣
轉(zhuǎn)換為了我們想要的坐標(biāo)數(shù)據(jù)以后。我們還要強(qiáng)制對法線進(jìn)行單位化。在這里,為了對法線進(jìn)行壓縮,其實(shí)我們可以僅存儲(chǔ)X,Y分量就可以了。
不知WOW為什么沒有這樣子。
同時(shí),在進(jìn)行模型頂點(diǎn)數(shù)據(jù)讀取的時(shí)候,由于我們本來就要進(jìn)行頂點(diǎn)數(shù)據(jù)遍歷,所以我們可以順便得出這個(gè)模型的半徑,用來做球形檢測
模型數(shù)據(jù)讀完了,緊接著是BoundingMesh(想說是包圍網(wǎng)格,又不太對,又或者,叫碰撞網(wǎng)格,這是一個(gè)簡化的網(wǎng)格,用于碰撞檢測和拾取之類的)數(shù)據(jù)
它由兩個(gè)部分組成BoundingVertices & BoundingTriangles (我又詞窮了,都懂的。)
BoundingVertices由一串float3組成,順序讀取即可,讀取完了后,如果上面的MESH做了坐標(biāo)系統(tǒng)轉(zhuǎn)換,那這里也得做。
BoundingTriangles由一串uint16索引組成,順序讀取即可。
讀取完上面的模型數(shù)據(jù)后,接下來就是紋理數(shù)據(jù)。
在WMV中的定義如下
#define TEXTURE_MAX 32 //最大紋理數(shù)
struct ModelTextureDef
{
uint32 type; //紋理類型
uint32 flags; //紋理標(biāo)記
uint32 nameLen; //名字長度
uint32 nameOfs; //名字在DBC中的偏移
};
搞笑得很啊,在結(jié)構(gòu)體定義的時(shí)候,沒有對上面字段說明,在使用的地方,卻有一段描述。不過想想也是,用的時(shí)候方便查看嘛。
/*
Texture Types
Texture type is 0 for regular textures, nonzero for skinned textures (filename not referenced in the M2 file!)
For instance, in the NightElfFemale model, her eye glow is a type 0 texture and has a file name,
the other 3 textures have types of 1, 2 and 6. The texture filenames for these come from client database files:
DBFilesClient\CharSections.dbc
DBFilesClient\CreatureDisplayInfo.dbc
DBFilesClient\ItemDisplayInfo.dbc
(possibly more)
0 Texture given in filename
1 Body + clothes 身體和布料
2 Cape 肩膀
6 Hair, beard 頭發(fā),胡子
8 Tauren fur 牛頭人的皮毛
11 Skin for creatures #1
12 Skin for creatures #2
13 Skin for creatures #3
Texture Flags
Value Meaning
1 Texture wrap X X方向環(huán)繞
2 Texture wrap Y Y方向環(huán)繞
*/
下面是我對這段說明的理解
0 表示是普通紋理 并且,可以直接獲取它的紋理名字
非0表示是皮膚 值得說明的是,紋理名字不包含在M2文件中。
比如說,在暗夜男模型中,他的眼睛發(fā)光就是一個(gè)類型為0的紋理,并且,有一個(gè)文件名(這個(gè)文件名就存在本文件中)。其它3個(gè)紋理類型是1,2和6. 紋理名字是從客戶端數(shù)據(jù)庫文件中提取。nameOfs就是表示其位置
額,寫到這里的時(shí)候,突然發(fā)現(xiàn),其實(shí)是有宏定義的
/*
Texture Types
Texture type is 0 for regular textures, nonzero for skinned textures (filename not referenced in the M2 file!) For instance, in the NightElfFemale model, her eye glow is a type 0 texture and has a file name, the other 3 textures have types of 1, 2 and 6. The texture filenames for these come from client database files:
DBFilesClient\CharSections.dbc
DBFilesClient\CreatureDisplayInfo.dbc
DBFilesClient\ItemDisplayInfo.dbc
(possibly more)
*/
enum TextureTypes
{
TEXTURE_FILENAME=0, // Texture given in filename
TEXTURE_BODY, // Body + clothes
TEXTURE_CAPE, // Item, Capes ("Item\ObjectComponents\Cape\*.blp")
TEXTURE_ITEM=TEXTURE_CAPE,
TEXTURE_ARMORREFLECT, //
TEXTURE_HAIR=6, // Hair, bear
TEXTURE_FUR=8, // Tauren fur
TEXTURE_INVENTORY_ART1, // Used on inventory art M2s (1): inventoryartgeometry.m2 and inventoryartgeometryold.m2
TEXTURE_QUILL, // Only used in quillboarpinata.m2. I can't even find something referencing that file. Oo Is it used?
TEXTURE_GAMEOBJECT1, // Skin for creatures or gameobjects #1
TEXTURE_GAMEOBJECT2, // Skin for creatures or gameobjects #2
TEXTURE_GAMEOBJECT3, // Skin for creatures or gameobjects #3
TEXTURE_INVENTORY_ART2, // Used on inventory art M2s (2): ui-buffon.m2 and forcedbackpackitem.m2 (LUA::Model:ReplaceIconTexture("texture"))
TEXTURE_15, // Patch 12857, Unknown
TEXTURE_16, //
TEXTURE_17, //
};
enum TextureFlags
{
TEXTURE_WRAPX=1,
TEXTURE_WRAPY
};
總之,就是如果遇上是0號類型,則直接讀文件名,否則就去DBC中取公共紋理數(shù)據(jù)。
比如頭發(fā)什么的,而上面牛頭人的毛發(fā)單獨(dú)定義,可能是因?yàn)槊l(fā)和一般人型生物不一樣吧。
另外,從TEXTURE_ARMORREFLECT中可以看出,WOW中的武器和盔甲是加上了反射紋理的,這樣才看起來有高光的感覺。
------------------------------------------------------------------------
------------------------------------------------------------------------
讀完模型,碰撞網(wǎng)格,紋理數(shù)據(jù),接下來,就要讀取掛接物了,最常見的掛接物,就是WOW中的肩膀,頭盔或者武器上的一些粒子效果。
WMV中,掛接物的定義如下
/*
* This block specifies a bunch of locations on the body - hands, shoulders, head, back,
* knees etc. It is used to put items on a character. This seems very likely as this block
* also contains positions for sheathed weapons, a shield, etc.
*/
struct ModelAttachmentDef
{
uint32 id; // Just an id. Is referenced in the enum POSITION_SLOTS.
uint32 bone; // Somewhere it has to be attached.
Vec3D pos; // Relative to that bone of course.
AnimationBlock unk; // (Int32) Its an integer in the data. It has been 1 on all models I saw. Whatever.
};
無非就是定義了掛接的骨骼索引,偏移位置等。 最后一個(gè)參數(shù),是動(dòng)畫塊數(shù)據(jù)。定義如下
// sub-block in block E - animation data, size 28 bytes, WotLK 20 bytes
struct AnimationBlock
{
int16 type; // 插值類型 (0=none, 1=linear, 2=hermite)
int16 seq; // 全局隊(duì)列ID,-1表示無
//下面的就是數(shù)據(jù)個(gè)數(shù)+數(shù)據(jù)在緩沖區(qū)中的偏移
#ifndef WotLK
uint32 nRanges;
uint32 ofsRanges;
#endif
uint32 nTimes; //
uint32 ofsTimes;
uint32 nKeys;
uint32 ofsKeys;
};
上面的定義可以看中,WLK版本中,BLZ對文件進(jìn)行了改動(dòng),加入了一個(gè)范圍數(shù)據(jù)。
讀取完上面的掛接頭信息以后,就可以根據(jù)這個(gè)信息,實(shí)例化一個(gè)掛接物,添加到模型身上。
下面是一個(gè)模型掛接物的信息
struct ModelAttachment
{
int id; //ID
Vec3D pos; 位置
int bone; //撞接的骨骼
Model *model; //掛接的模型
void init(MPQFile &f, ModelAttachmentDef &mad, uint32 *global);
void setup();
void setupParticle();
};
讀完上面的信息后,我發(fā)現(xiàn),還有一個(gè)詭異的attLookup數(shù)據(jù), 單看字面上意思,應(yīng)該是拿來裝一個(gè)供掛接物ID查詢的數(shù)據(jù)的。
就是ModelAttachment中的ID作為下標(biāo),進(jìn)行查詢。 目前還沒有搞明白。
本來想繼續(xù)寫下去,但發(fā)現(xiàn)寸步難行了,后面的數(shù)據(jù)都沒看明白是什么意思,只好留到下次了。
睡覺了,晚安!?。。。?/p>
posted @ 2013-04-20 00:53 麒麟子 閱讀(819) | 評論 (0) | 編輯 收藏