[龙之谷专题]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格式->通用模型格式:
- 点击"浏览…"按钮指定MSH文件位置.
- 点击"浏览…"按钮指定MSH对应的ANI位置.
- 点击"转换"按钮,选择所需转换格式,指定输出目录及文件名称.
- 转换完成.
通用模型格式->MSH格式:
- 点击"浏览…"按钮,指定通用模型文件位置.
- 点击"转换"按钮,选择MSH格式,指定输出目录及文件名称.
- 转换完成.
资源链接
[note]视频教程:
[妹汁谷]MSH模型格式转换工具使用说明 点击跳转
龙之谷时装补丁制作之进阶教程 经验分享 点击跳转
[/note]
[note]下载地址:
龙之谷MSH模型转换器1.2 中文版 English Version SRC
演示视频上的琪露诺冰翼 点击下载
[/note]
文件结构
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: 其他元素总数 |
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索引,从文件头开始偏移0x400(1024)字节即为骨骼数据:
单个BoneData结构示意 | |
boneName[256] | boneName: 骨骼名称 |
m1 | m1: 骨骼变换矩阵第一行数据 |
m2 | m2: 骨骼变换矩阵第二行数据 |
m3 | m3: 骨骼变换矩阵第三行数据 |
m4 | m4: 骨骼变换矩阵第四行数据 |
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: 渲染模式,取值0x100/0x101 |
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个元素 |
struct MeshInfo{
char sceneName[256];
char meshName[256];
int vertexCount;
int indexCount;
int unknown;
int renderMode;
char empty[512 - 16];
};
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部分
暂时猜测该部分数据可能用于武器的"刀锋"特效.
自定义结构
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);}
};
class Vec3F : public Vec2F{
public:
float z;
Vec3F() : Vec2F(){z = 0;}
Vec3F(KFbxVector4 &vector) : Vec2F(vector){
z = vector.GetAt(2);}
};
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.放出源代码,停止工程
暂无评论