反转 2001 年的 3D 文件格式

逆向工程 二元分析 文件格式 十六进制
2021-07-08 23:24:14

这是 2001 年发布的韩国 MMORPG。游戏和公司已不复存在。一段时间以来,我一直将文件格式作为个人项目进行分析。

我已经解码了纹理和脚本文件。我只剩下 2 个文件要解码:.ani.obj. 通过扩展,我猜想.ani包含动画并.obj包含 3d 模型。正如我的问题的标题所暗示的那样。我目前正在处理该.obj文件。

我知道的

.obj文件实际上是包含一个或多个模型的档案。但是,专门的3D模型(两足动物),因为纹理与扩展另一存档文件中.t16.tex

我将以文件中的第 22 个模型def.obj为例。我也把它从存档中取出并保存为一个名为`def_022.obj 的文件。

从这里开始,我将调用第 22 个模型Armor of Eagle下一张图片是在 上Armor of Eagle找到的纹理def.t16

在此处输入图片说明

游戏中的鹰之盔甲:

在此处输入图片说明

一个def_inf.txt文件有这个相关的行:

filename    LODstep polycnt
armor_eagle 0       313     // eagle = index 22

一般而言,其结构.obj为:

06 00 00 00 03 00     // don't know what
3C 00                 // total number of models in this list
01 00 9E 00 00 00 9E 00 00 00 78 00 00 00 78 00 00 00 // the first model on the list with 0x9E polygons and 0x78 verticies
01 00 64 00 00 00 64 00 00 00 61 00 00 00 61 00 00 00 // the 2nd model
....... // continues until you reach the end of the headers
....... // then the bodies start, actual 3d data

这是标题的外观:

在此处输入图片说明

  • 青色:
    • 39 01 00 00 = 313 多边形数
    • 18 01 00 00 = 280 个顶点数
    • AD 00 6B 00 = 未知

关于 def_022.obj

人脸指数开始于0x4C [00 00 01 00...]
,从它的外观来看,结束于0x7A2 [...A2 00 A3 00]

我正在使用名为的工具,hex2obj 0.24c但在猜测顶点和 uv 列表的起点方面没有任何运气。

在此处输入图片说明

  • 黄色:在我看来,它是块标记。(因为所有文件都以它开头)
  • 浅蓝色:是一个 uint16 序列号,对于def.obj. 并且它也对应于其纹理的索引(在纹理档案中)。
  • 深绿色:是人脸指数。

问题

  • 我该如何前进?
  • 如何找到UV开始的地址?书籍?文章?资源?
  • 最后,我怎么知道顶点从哪里开始?

这都是考虑到我只是分析二进制文件而不是调试客户端本身以查看客户端如何获取数据。

更新

我注意到我正在分析的文件中有一些新内容def_022.obj一个字节数组被重复了很多次。虽然,我仍然不确定 YET 的重要性。00 00 80 3F也是每个模型开始的字节,我认为这是块标记:

在此处输入图片说明

  • 黄色:是重复字节。您还会注意到,它的前面通常是字节0x3For 0x3E,然后是0x0C0x0D,然后是0x00. 的3 个字节这种模式被重复了 185 次。
  • 青色:是包含人脸索引的区域。
  • 经过进一步研究,我发现3f80 0000 = 1还是0000 803f = 1小端。但是还是不知道意义,我要深入挖掘。

根据@RadLexus 先生提供的注释。我还能够绘制顶点并导入到搅拌机中:

在此处输入图片说明

添加了法线和 UV:

v -13.531700 37.445000 2.338600
vn -0.687800 0.725000 -0.036200
vt 0.583800 0.086300

然后我尝试添加面孔:

f 1 2 3
f 1 3 4
f 5 6 7
f 5 7 8
f 9 10 11
...

在此处输入图片说明

但仍然无法弄清楚如何应用纹理。

更新

因此,我尝试更改我的.obj文件以包含更多有关面值的信息,例如(只是将值复制为 x/x/x):

f 1/1/1 2/2/2 3/3/3
f 1/1/1 3/3/3 4/4/4
f 5/5/5 6/6/6 7/7/7

我终于得到了这个:

在此处输入图片说明

虽然它仍然是错误的,但我想我更接近一些。

最后更新

已经想通了。虽然,我仍然不知道 unknown1 和 unknown2 是什么,但它看起来已经足够了:

在此处输入图片说明


注意:我对 3D 文件格式几乎一无所知。除了 3D 对象的基本组件。

在此下载相关文件

1个回答

只是一些初步的笔记——可能会演变成一个完整的答案。


我的方法如下。显然,末尾的数字是浮点数。此外,它们并非都是浮点数;0C 00 00 00几个字节的序列不是一个合理的浮点数。计算下一个“不合理”的值(碰巧0C 00 00 00再次出现,但也有其他值)告诉我这个数据步幅28字节。(十进制是 40,但对于文档,我更喜欢十六进制。)如果您有一个功能强大的十六进制查看器,您可以调整视图宽度,如果将其视图宽度设置为 40 个字符,您会发现这是正确的。

以 40 字节的步长从末尾开始倒数,这给了我这个序列最有可能的起点。

它前面的数字显然至少是 2 字节(无符号短整型),并且从头到尾逐渐增加。由于这是一个3D模型,我便形成了强烈的预感三角形数据,那么他们至少应该包含ab以及c顶点索引,以及可能的附加属性的三角形。经过反复试验,结果并非如此。(“试错”包括将它们转储到显示程序中。因为这立即起作用,所以没有必要进行进一步的数值研究。)

由于这些信息 (1) 足以显示一个对象,并且 (2) 涵盖文件中除了开头的几个字节之外的所有数据——可以是任何字节——我继续编写一个完整的显示程序。


第一个004A字节是未知的。它们包含一些浮点数(00 00 80 3Fis 1.0,作为一个小端 4 字节浮点数),它们可以是任何东西。(很可能有规模。)

接下来的 2 个字节形成数字0016,以十进制表示22这可能是内部“对象编号”。

然后,从 开始004C113h(313,十进制)三角形定义如下。单个三角形定义由 3 个无符号短索引a, b, 组成c,指向 3 个坐标这个列表中最大的索引是0117,一个重要的数字!

紧随其后的是0118 3D 点每个 3D 点具有以下结构:

float x
float y
float z
float unknown (usually 1.0?)
unsigned int unknown
float normal_x
float normal_y
float normal_z
float u   \
float v   / correct; see bottom update

normal_*可以通过将它们的平方相加来确定这 3 个变量确实形成了一个法线;它们应该在 值附近徘徊1.0对于这些坐标中的前一百个左右,这是正确的,精度最高为 3 位小数:

1.000004
1.000080
0.999935
1.000076
0.999936
(and so on)

将所有坐标元素的大小相加得到28字节的总大小(40,十进制),并且:

  1. 文件的其余部分是这个的倍数;
  2. 将剩余部分的大小除以28结果118(280,十进制)。

因此证明了三角形列表中“最高索引”的重要性:) 它们确实是坐标索引。

其中,这些数字139h118h从何而来?它们出现在整个文件的标题部分!

这是前 3 个元素确实是xyz的证明我只绘制了xyy反转(负向屏幕底部)。您可以清楚地识别游戏中图像的“身体”部分。

线框体


并非所有坐标都完全相同。unknown_1浮点值是1.000用于第一173个坐标,然后跳转到的余数的其它值。同样,整数unknown_2从值之间悬停443这些,然后跳转到高得多的值。这需要进一步调查。


uv值可以被映射到直接在源图像。它们以浮点范围表示,0..1因此您需要将它们乘以源图像的宽度和高度。这是一张图片:

纹理坐标

图像中未使用的部分可能被其他 3D 模型使用。