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遍