[龍之谷專題]MSH模型轉換器開發日志<放出源代碼>

龍之谷模型轉換器開發進程表
功能 項目 讀取 寫入
多邊形 貼圖 骨骼 多邊形 貼圖 骨骼
命名 頂點 索引 法線 命名 坐標 節點 權重 命名 頂點 索引 法線 命名 坐標 節點 權重
設計/D
實現/A
測試/T
額外功能 多Mesh UI界面 材質支持 × 雜項 - 開發進度 Release
開發狀態 V1.2 下載   基本完成   遇到問題   未解決 更新日期 03.31

前言

    這個程序以及相關資信是自己興趣寫出來的,沒有任何商業利益的,本程序僅用于學習研究之用,請勿用于商業用途,由此軟件產生的商業糾紛軟件作者一概不負責任.
    發現上一篇的龍之谷修改專題日志不少人關注的說,QQ和MSN上也有問道開發情況的,看來修改龍之谷的模型還是多數CGer的共同愿望呢~于是乎有了這篇文章~嘛,我也知道等待的滋味不好受的,所以就貼一下每天的開發進度吧,稍后還會貼出相關信息~
    最后,還請各位原諒本人不才,拖慢了開發進度了orz……
    * 關于龍之谷的msh資源結構,大部分信息源于 liuliqiang 大大,特此感謝提供!

使用說明

<-Display English version of usage->

    "龍之谷MSH模型轉換器"是一款用于龍之谷模型文件(*.msh)與其他通用模型文件相互轉的便捷工具.
使用時只需指定msh文件位置,以及msh對應的動畫文件(*.ani),即可輸出通用模型格式到指定目錄.

MSH格式->通用模型格式:

  1. 點擊"瀏覽…"按鈕指定MSH文件位置.
  2. 點擊"瀏覽…"按鈕指定MSH對應的ANI位置.
  3. 點擊"轉換"按鈕,選擇所需轉換格式,指定輸出目錄及文件名稱.
  4. 轉換完成.

通用模型格式->MSH格式:

  1. 點擊"瀏覽…"按鈕,指定通用模型文件位置.
  2. 點擊"轉換"按鈕,選擇MSH格式,指定輸出目錄及文件名稱.
  3. 轉換完成.

資源鏈接

視頻教程:
[妹汁谷]MSH模型格式轉換工具使用說明 點擊跳轉
龍之谷時裝補丁制作之進階教程 經驗分享 點擊跳轉

下載地址:
龍之谷MSH模型轉換器1.2 中文版 English Version SRC
演示視頻上的琪露諾冰翼 點擊下載

文件結構

MSH文件結構示意
Header 文件頭部,用于索引各種數據
BoneData 骨骼數據部分,大小由骨骼數量決定
MeshData 模型數據部分,大小由Mesh數量決定
OtherData 其他數據部分,大小由其他元素量決定

Header部分

Header結構示意
  name: 文件頭標識
name[256] version: 文件版本
  meshCount: Mesh總數
version meshCount unknown unknown bbMax: BoundingBox最大值
bbMax   bbMin: BoundingBox最小值
bbMin boneCount unknown boneCount: 骨骼總數
otherCount   otherCount: 其他元素總數
1
2
3
4
5
6
7
8
9
10
11
12
struct Header{
    char name[256];	//Eternity Engine Mesh File 0.1
    int version;
    int meshCount;
    int unknown1;	//0x1
    int unknown2;	//0x0
    Vec3F bbMax;
    Vec3F bbMin;
    int boneCount;
    int unknown2;	//0x1或0x0
    int otherCount;
};

BoneData部分

    骨骼數據個數由Header索引,從文件頭開始偏移0×400(1024)字節即為骨骼數據:

單個BoneData結構示意
boneName[256] boneName: 骨骼名稱
m1 m1: 骨骼變換矩陣第一行數據
m2 m2: 骨骼變換矩陣第二行數據
m3 m3: 骨骼變換矩陣第三行數據
m4 m4: 骨骼變換矩陣第四行數據
1
2
3
4
struct BoneData{
	char boneName[256];			//骨骼名稱
	Vec4F transformMatrix[4];	//骨骼變換矩陣
};

MeshData部分

    MeshData部分由一個或多個Mesh數據組成,具體多少個Mesh由文件頭部的meshCount決定.
每個Mesh數據由Mesh信息+Mesh數據組成,為了方便演示,示意圖將把Mesh信息部分和Mesh數據部分合并一起表示,而具體實現代碼將分成兩個結構體:

單個MeshData結構示意
sceneRoot[256] sceneRoot: Mesh所屬節點名稱
  meshName: Mesh名稱
meshName[256] vertexCount: 頂點個數
  indexCount: 頂點(三角面)索引數
vertexCount indexCount unknown renderMode renderMode: 渲染模式,取值0×100/0×101
empty[512-16] (GL_TRIANGLE_STRIP/GL_TRIANGLE)
vertexIndex vertexIndex: 頂點索引,indexCount個元素
vertexData vertexData: 頂點數據,vertexCount個元素
normalData normalData: 法線數據,vertexCount個元素
uvData uvData: UV貼圖數據,vertexCount個元素
weightIndex weightIndex: 權重索引,vertexCoun個元素
weightData weightData: 權重數據,vertexCount個元素
boneCount   boneCount: Mesh綁定骨骼個數
boneIndex boneIndex: 骨骼索引,boneCount個元素
1
2
3
4
5
6
7
8
9
struct MeshInfo{
	char sceneName[256];
	char meshName[256];
	int vertexCount;
	int indexCount;
	int unknown;
	int renderMode;
	char empty[512 - 16];
};
1
2
3
4
5
6
7
8
9
10
struct MeshDataPointer{//數據指針
    char* pFaceIndex;	//0x2(unsigned short) * indexCount
    char* pVertexData;	//0x4(float) * 3 * vertexCount
    char* pNormalData;	//0x4(float) * 3 * vertexCount
    char* pUVData;	//0x4(float) * 2 * vertexCount
    char* pBoneIndex;	//0x2(unsigned short) * 4 vertexCount
    char* pBoneWeight;	//0x4(float) * 4 * vertexCount
    int*  pBoneCount;	//Mesh綁定的Bone數
    char* pBoneName;	//0x100(char [256]) * boneCount
};

    現在說一下MeshData里面各個元素的組成,雖然說規范和DirectX差不多,不過當時對DirectX的3D編程完全沒有了解的我,可被這個搞得一頭冒水呢……
    MSH文件在保存浮點型數據時均使用單精度型(float)浮點數保存數據.

VertexData元素
    VertexData,即頂點數據,是頂點在三維空間的x,y,z坐標數據.每個元素使用Vec3F結構保存數據.

VertexIndex元素
    VertexIndex,即頂點索引,是程序畫面的順序數據,索引的是頂點數據.每個元素使用unsign short類型保存數據.

NormalData元素
    NormalData,即法線數據,是每個頂點的法向數據,以三維空間坐標x,y,z表示.每個元素使用Vec3F結構保存數據.

UVData元素
    UVData,即UV貼圖數據,是每個頂點在二維貼圖空間映射的u,v坐標.每個元素使用Vec2F結構保存數據.

WeightIndex元素
    WeightIndex,即權重索引,是每個頂點的權重索引,每個頂點最多可以索引4個骨骼.每個元素使用4個unsign short類型保存數據.

WeightData
    WeightData,即權重數據,是每個頂點的權重數據,每個頂點最多可以擁有4個骨骼權重.每個元素使用Vec4F結構保存數據.

BoneIndex
    BoneIndex,即骨骼索引,用以給骨骼編序,只保存骨骼名稱.每個元素使用char [256]字符型數組保存數據.

OtherData部分

    暫時猜測該部分數據可能用于武器的"刀鋒"特效.

自定義結構

1
2
3
4
5
6
7
8
9
10
11
12
class Vec2F{
	public:
	float x;
	float y;
	Vec2F(){x = 0; y = 0;}
	Vec2F(KFbxVector2 &vector){
		x = vector.GetAt(0);
		y = vector.GetAt(1);}
	Vec2F(KFbxVector4 &vector){
		x = vector.GetAt(0);
		y = vector.GetAt(1);}
};
1
2
3
4
5
6
7
class Vec3F : public Vec2F{
	public:
	float z;
	Vec3F() : Vec2F(){z = 0;}
	Vec3F(KFbxVector4 &vector) : Vec2F(vector){
		z = vector.GetAt(2);}
};
1
2
3
4
5
6
7
class Vec4F : public Vec3F{
	public:
	float w;
	Vec4F() : Vec3F(){w = 0;}
	Vec4F(KFbxVector4 &vector) : Vec3F(vector){
		w = vector.GetAt(3);}
};

Change Log

11.18 
A03:解決建立三角面時順序錯誤的問題.
T02:頂點信息建立測試通過.
T03:三角面建立測試通過.
T04:頂點法線建立測試通過.
11.19
A06:完成了對貼圖UV的讀取.
T02/T04/T06:發現浮點數的精度取值問題.
11.20
A01/A05:完成對模型名稱,貼圖名稱讀取.
T01/T05:模型名稱,貼圖名稱讀取通過測試. 
11.21
重新理解MSH格式結構.
重寫了一下讀取函數,優化讀取速度,整理了程序結構.
A03:修復了奇偶面數讀取錯誤問題.
T03:奇偶面數讀取測試通過.
11.23
模塊化功能函數.
A07:實現骨骼結點名稱的讀取.
T07:骨骼結點名稱讀取測試通過.
D08:讀取骨骼變換矩陣遇到問題.
11.26
T03:發現在讀取非閉合多邊形出現三角面混亂問題.
D08:完成對骨骼數據的讀取設計.
A08:考慮綁定骨骼綁定問題.
11.27
發現不同版本的MSH在建立多邊形時采用GL_TRIANGLE_STRIP 或 GL_TRIANGLE 模式
T03:解決讀取頂點索引錯亂問題.
A11:寫入MSH頂點索引可能要使用GL_TRIANGLE模式
11.28
A08:完成對骨骼與模型的綁定已經蒙皮權重的添加.
A08:遇到綁定骨骼后模型扭曲的問題.
11.29
MSH文件不足以提供完整骨骼信息,決定追加ANI文件輔佐.
12.05
A08:完成對骨骼父子節點的添加,修正世界坐標和本地坐標的轉換問題.
D08:修正骨骼與模型綁定后扭曲問題.
T08:骨骼綁定測試通過.
O01:完成對多Mesh讀取
12.09
D11:決定使用GL_TRIANGLE模式寫入三角形索引.
A15:實現對骨骼名稱及骨骼變換矩陣的寫入.
T15:發現寫入的變換矩陣與原數據有些差異.
12.10
D09/D10/D11/D12:實現對Mesh名稱,三角面索引,頂點數據,法線信息的讀取和寫入.
D13/D14:實現對貼圖坐標名稱的讀取和寫入.
D16:實現對骨骼權重的讀取和寫入.
T15:仍未解決骨骼矩陣信息與原信息差異問題,但測試中未發現有什么問題.
T09/T10/T11/T12/T13/T14/T16:測試通過,但是無法保證BoundingBox信息正確.
"今天只有早上一節物理課,于是果斷花了一整天把這個程序的大部分功能實現了.畢竟這周學校要忙的事特多,搞到周一到周四基本上不能碰程序了…果然有了讀取的經驗和知識,寫入的編程設計進度一天就完成了…激動~~"
12.11
A03:優化了GL_TRIANGLE_STRIP讀取多邊形算法
T03:發現某系模型轉換成FBX格式導入到Maya后再導出FBX會導致Maya崩潰的問題.
12.13
T15:解決骨骼世界變換矩陣數據的出現差異的問題,發現原來是編寫時忽略了骨骼根節點.
12.14
發布1.0b,公測開始……
2010.12.17 – V1.0.1b
1.修復了UV貼圖錯誤問題.
2.解決骨骼名稱特殊字符過濾問題
2011.1.16 – V1.1
1.界面支持視覺風格
2.更詳細錯誤提示信息
3.可選額外骨骼信息(ANI文件需求)
4.增加對新版FBX格式的兼容性
2011.3.31 – V1.2
1.修正界面刷新異常
2.UNICODE工程
3.支持非英文目錄
2012.9.22 – V1.2
1.放出源代碼,停止工程

  1. 暫無評論

  1. 暫無 Trackback

?

return top

皇家彩世界快乐飞艇官网