【分析】魔兽争霸3的MPQ文件及模型格式分析

本文详细解析了魔兽争霸3中模型数据的组织方式,包括MPQ文件的读取、模型文件格式的各个组成部分,如模型属性、动作数据、材质、贴图纹理和几何数据等,并介绍了如何从MPQ文件中提取和分析这些数据。

1 魔兽争霸3的模型数据都被打包压缩在*.mpq里,可以通过SFmpq_static.lib提供的接口获取相应的数据段句柄(MPQHANDLE)。

2 读取MPQ时,首先要知道这个MPQ里有多少个被打了包的文件数目以及每个文件的名字,可以通过SFmpq_static.lib的 SFileOpenFile(LPCSTR lpFileName, MPQHANDLE *hFile)接口查找数据段标记(TAG)为(listfile)在MPQ里的位置句柄,然后继续用接口获取到数据段长度后,将这段数据Read到内存 里来,这些数据全是关于文件名及相对路径的字符串,接下来可以创建一个临时文件,把数据fwrite到这个临时文件里,这样就可以用fscan逐一读出文 件名并保存起来了(比如保存成一个table)。

3 现在有了文件的索引了,在读取模型时,还是用SFileOpenFile获取这个模型在MPQ的句柄,然后再用接口读到内存,这样就可以专门针对这段模型数据段进行分析了。

下面是魔兽3的模型文件格式:

MDLX  --  4个char,即4个字节一个DWORD的长度,这个是魔兽3模型格式的专用头标记,如果没有则表示出错

VERS  --  4个char,一个DWORD的长度,即4个字节

version data  --  DWORD类型  实际的version数据

MODL  --  4个char  这个模型的属性数据,如boundingbox

MODL size  --  DWORD  在模型数据段中的长度,一般就是372的固定长度

MODL name1  --  80个字节

MODL name2  --  260个字节

MODL unknow float  --  4个字节,float类型  功能未知

MODL boundingbox min vector  --  3个float,12个字节  boundingbox min vector

MODL boundingbox max vector  -- 3个float,12个字节

MODL unknow DWORD  --  4个字节 ( 80+260+4+12+12+4=372 )

SEQS  --  4个字节  动作数据

SEQS size  --  4个字节

SEQS data  --  上面读出来的SEQS size个字节

(  单个动作数据的struct:

struct SequenceName
{
 char mName[80];
 int  mUnk1;

 int  mUnk2;
 float mUnk3;
 int  mUnk4;
 float mUnk5;
 int  mUnk6;
 float mUnk7;

 Vec3 mMins;
 Vec3 mMaxs;
};

动作的数量:

mNumSequences = SEQS size / sizeof(SequenceName);

)

unknow TAG  --  4个字节

unknow TAG size  --  4个字节

unknow TAG data  --  unknow TAG size个字节

MTLS  --  4个字节

MTLS size  --  4个字节

MTLS data  --  MTLS size个字节

(

class mdxMaterial
{
#define MAX_LAYER 8
public:
 int    mUnk1;
 int    mUnk2;
 // 'LAYS' 
 int    mNumLayers;
 Layer1   mLayers[MAX_LAYER];

 ......
};

struct Layer1
{
 int  mLayerSize; // in Bytes
 int  mBlendMode;
 int  mUnk3;
 int  mTexture;
 int  mUnk5;
 int  mUnk6;
 float mUnk7;  // alpha ?
 BOOL mKMTA;
};

MTLS data里具体的材质数据读取是:

先读一个4个字节的单个mdxMaterial的size(layer1的数量不同导致mdxMaterial的大小不同),然后按照结构顺序填 充,碰到layer1时,用同样的方法,先读4字节Layer1的size,然后按照顺序填充layer1,总共填充mNumLayers次

)

TEXS  --  4个字节  模型使用的贴图纹理数据

TEXS size  --  4个字节 

(

struct Texture
{
 DWORD mUnk1;
 char mName[MAX_PATH]; // 260
 DWORD mUnk2;
};

由若干个Texture构成,Texture Numbers = TEXS size / sizeof(Texture)

)

TEXS data  --  TEXS size个字节  贴图纹理数据

GEOS  --  4个字节

GEOS size  --  4个字节

GEOS data  --  GEOS size个字节

(

GEOS数据段由若干个mdxGeoChunk构成

单个mdxGeoChunk具体数据分布如下:

VRTX  --  4个字节

number of vertex  --  4个字节

vertex data  --  number of vertex * 12个字节  每个顶点占用3*4个字节

NRMS  --  4个字节

number of normals  --  4个字节

normal data  --  number of normals * 12个字节  法线数据

PTYP  --  4个字节  primitives type

PTYP size  --  4个字节 

PTYP data  --  PTYP size * 4个字节

PCNT  --  4个字节  primitives count

PCNT size  --  4个字节

PCNT data  --  PCNT size * 4个字节

PVTX  --  4个字节  primitives vertices  构成IB的primitive数据

PVTX size  --  4个字节

PVTX data  --  PVTX size * 2个字节

(

struct Triangle
{
 short ind[3];
};

PVTX data里含PVTX size*2/sizeof(Triangle)个Triangle

)

GNDX  --  4个字节  vertex group indices

GNDX size  --  4个字节

GNDX data  --  GNDX size个字节

MTGC  --  4个字节  group matrix counts

MTGC size  --  4个字节

MTGC data  --  MTGC size*4个字节

MATS  --  4个字节  matrices

MATS size  --  4个字节

MATS data  --  MATS size*4个字节

unknow DWORD*4  --  4*4个unknow DWORD

chunk bounding box  --  2*3*4个字节

unknown struct number  --  4个字节

unknown struct data  --  unknown struct number*(4+12*2)个字节

UVAS  --  4个字节

UVAS size  --  4个字节

UVBS  --  4个字节

UVBS size  --  4个字节

UVBS data  --  UVBS size*8个字节

)

unknown TAG  --  4个字节

unknown TAG size  --  4个字节

unknown TAG data  --  unknown TAG size个字节

BONE  --  4个字节

BONE size  --  4个字节

BONE data  --  BONE size个字节

unknown TAG  --  4个字节

unknown TAG size  --  4个字节

unknown TAG data  --  unknown TAG size个字节

重复上面的unkown TAG读取过程5遍

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值