如何读取这些UV坐标?

逆向工程 二元分析
2021-06-17 00:17:47

我正在尝试对 1997 年的赛车游戏(试驾 4)中的3D 模型(汽车)进行逆向工程我能够提取 3D 网格和纹理,但无法弄清楚 UV 映射是如何工作的。

每辆车只有一个文件,其中包含所有内容(3D 模型、纹理、仪表板、调整等)。3D 模型部分包含一个顶点列表和多边形列表。单个多边形如下所示:

Triangle
{
    ulong       beg = 0xffff0000
    ushort      texture     // 0 = car bottom, 3 = body
    ubyte[6]    unknown     // UV mapping???
    ulong[3]    vertices    // Indices
    ulong       end = 0x00000000
}

我发现 6 字节unknown部分包含 UV 数据,因为当我修改这些值时,游戏中有明显的不同。它有 6 个字节长,因此它可以为 3 个顶点中的每一个保存一个 U 和 V 值。但是,我完全不知道如何解释这些数字。我尝试将它们作为字节读取并除以 255 以将它们转换为从 0 到 1 的浮点数,但没有成功。它们可能是 8 位浮点数吗?(我不明白这些是如何工作的,所以不能确定。)

下面是 80 个多边形的十六进制转储(每行一个)。

FF FF 00 00 03 00 7B 7B 7D AD BE AD 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00
FF FF 00 00 03 00 7B 7D 7D BE BE AD 01 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00
FF FF 00 00 03 00 3E 1C 3E BE BE C9 04 00 00 00 05 00 00 00 06 00 00 00 00 00 00 00
FF FF 00 00 03 00 1C 1C 3E BE CB C9 05 00 00 00 07 00 00 00 06 00 00 00 00 00 00 00
FF FF 00 00 03 00 7B 7B 7D AD BE AD 08 00 00 00 09 00 00 00 0A 00 00 00 00 00 00 00
FF FF 00 00 03 00 7B 7D 7D BE BE AD 09 00 00 00 0B 00 00 00 0A 00 00 00 00 00 00 00
FF FF 00 00 03 00 09 09 02 AC 9E AC 0C 00 00 00 0D 00 00 00 0E 00 00 00 00 00 00 00
FF FF 00 00 03 00 09 00 02 9E 9E AC 0D 00 00 00 0F 00 00 00 0E 00 00 00 00 00 00 00
FF FF 00 00 00 00 A0 A7 A0 1D 1D 00 10 00 00 00 11 00 00 00 12 00 00 00 00 00 00 00
FF FF 00 00 00 00 A7 A7 A0 1D 00 00 11 00 00 00 13 00 00 00 12 00 00 00 00 00 00 00
FF FF 00 00 03 00 45 45 67 3F 48 3F 14 00 00 00 15 00 00 00 01 00 00 00 00 00 00 00
FF FF 00 00 03 00 44 44 46 5B 5B 48 16 00 00 00 17 00 00 00 18 00 00 00 00 00 00 00
FF FF 00 00 03 00 44 47 46 5B 49 48 17 00 00 00 19 00 00 00 18 00 00 00 00 00 00 00
FF FF 00 00 00 00 92 97 98 1D 1D 1A 1A 00 00 00 17 00 00 00 16 00 00 00 00 00 00 00
FF FF 00 00 03 00 00 19 19 7B 7E 60 1B 00 00 00 00 00 00 00 1C 00 00 00 00 00 00 00
FF FF 00 00 03 00 46 44 29 47 5B 4A 19 00 00 00 17 00 00 00 1D 00 00 00 00 00 00 00
FF FF 00 00 03 00 44 2B 29 5B 5C 4A 17 00 00 00 1A 00 00 00 1D 00 00 00 00 00 00 00
FF FF 00 00 00 00 98 97 92 03 00 00 1E 00 00 00 1F 00 00 00 20 00 00 00 00 00 00 00
FF FF 00 00 03 00 3E 3E 2D BE BB BE 14 00 00 00 1B 00 00 00 21 00 00 00 00 00 00 00
FF FF 00 00 03 00 3E 2D 2D BB BC BE 1B 00 00 00 22 00 00 00 21 00 00 00 00 00 00 00
FF FF 00 00 03 00 2D 2D 1C 90 81 90 23 00 00 00 24 00 00 00 25 00 00 00 00 00 00 00
FF FF 00 00 03 00 2D 1C 1C 81 81 90 24 00 00 00 26 00 00 00 25 00 00 00 00 00 00 00
FF FF 00 00 03 00 2D 2D 18 BE BC BE 21 00 00 00 22 00 00 00 27 00 00 00 00 00 00 00
FF FF 00 00 03 00 2D 18 18 BC BB BE 22 00 00 00 28 00 00 00 27 00 00 00 00 00 00 00
FF FF 00 00 03 00 1C 1C 09 90 81 90 25 00 00 00 26 00 00 00 29 00 00 00 00 00 00 00
FF FF 00 00 03 00 1C 12 09 81 82 90 26 00 00 00 2A 00 00 00 29 00 00 00 00 00 00 00
FF FF 00 00 00 00 92 92 91 07 00 00 2B 00 00 00 20 00 00 00 2C 00 00 00 00 00 00 00
FF FF 00 00 03 00 18 18 11 BD BB BD 27 00 00 00 28 00 00 00 2D 00 00 00 00 00 00 00
FF FF 00 00 03 00 18 11 11 BB BB BD 28 00 00 00 2E 00 00 00 2D 00 00 00 00 00 00 00
FF FF 00 00 03 00 03 0B 0C 86 8E 7F 2F 00 00 00 29 00 00 00 30 00 00 00 00 00 00 00
FF FF 00 00 03 00 0B 13 0C 8E 81 7F 29 00 00 00 2A 00 00 00 30 00 00 00 00 00 00 00
FF FF 00 00 03 00 0D 0C 00 4D 57 57 31 00 00 00 32 00 00 00 33 00 00 00 00 00 00 00
FF FF 00 00 00 00 83 81 87 03 07 01 34 00 00 00 35 00 00 00 36 00 00 00 00 00 00 00
FF FF 00 00 00 00 81 87 87 07 07 01 35 00 00 00 37 00 00 00 36 00 00 00 00 00 00 00
FF FF 00 00 03 00 5D 5E 3F BD AD BD 38 00 00 00 39 00 00 00 03 00 00 00 00 00 00 00
FF FF 00 00 03 00 5E 3F 3F AD AD BD 39 00 00 00 02 00 00 00 03 00 00 00 00 00 00 00
FF FF 00 00 03 00 7C 5E 7C AD AD BD 3A 00 00 00 39 00 00 00 3B 00 00 00 00 00 00 00
FF FF 00 00 03 00 5E 5D 7C AD BD BD 39 00 00 00 38 00 00 00 3B 00 00 00 00 00 00 00
FF FF 00 00 00 00 AA AA AB 16 1D 1E 3C 00 00 00 3D 00 00 00 3E 00 00 00 00 00 00 00
FF FF 00 00 00 00 BC BA B5 06 01 08 3F 00 00 00 40 00 00 00 41 00 00 00 00 00 00 00
FF FF 00 00 00 00 BA B5 B5 01 00 08 40 00 00 00 42 00 00 00 41 00 00 00 00 00 00 00
FF FF 00 00 03 00 5D 5D 43 0C 1B 0C 43 00 00 00 44 00 00 00 45 00 00 00 00 00 00 00
FF FF 00 00 03 00 5D 48 43 1B 1B 0C 44 00 00 00 46 00 00 00 45 00 00 00 00 00 00 00
FF FF 00 00 03 00 7B 59 7B BF BF C9 3B 00 00 00 05 00 00 00 3A 00 00 00 00 00 00 00
FF FF 00 00 03 00 59 5A 7B BF C9 C9 05 00 00 00 47 00 00 00 3A 00 00 00 00 00 00 00
FF FF 00 00 03 00 00 00 1C DC F7 CB 48 00 00 00 40 00 00 00 07 00 00 00 00 00 00 00
FF FF 00 00 03 00 00 1C 1C F7 F3 CB 40 00 00 00 3F 00 00 00 07 00 00 00 00 00 00 00
FF FF 00 00 03 00 5F 3F 1C F2 EB F2 49 00 00 00 4A 00 00 00 3F 00 00 00 00 00 00 00
FF FF 00 00 03 00 7D 7D 60 DC C3 CE 43 00 00 00 4B 00 00 00 4C 00 00 00 00 00 00 00
FF FF 00 00 03 00 7D 5F 60 C3 BE CE 4B 00 00 00 4D 00 00 00 4C 00 00 00 00 00 00 00
FF FF 00 00 03 00 04 0C 0B B7 BE AF 4E 00 00 00 2D 00 00 00 0C 00 00 00 00 00 00 00
FF FF 00 00 03 00 0C 13 0B BE BC AF 2D 00 00 00 2E 00 00 00 0C 00 00 00 00 00 00 00
FF FF 00 00 03 00 7D 62 73 00 00 13 2F 00 00 00 33 00 00 00 4F 00 00 00 00 00 00 00
FF FF 00 00 03 00 62 5F 73 00 13 13 33 00 00 00 50 00 00 00 4F 00 00 00 00 00 00 00
FF FF 00 00 03 00 73 5E 73 1F 1F 2B 0F 00 00 00 51 00 00 00 0E 00 00 00 00 00 00 00
FF FF 00 00 03 00 5E 5F 73 1F 2B 2B 51 00 00 00 35 00 00 00 0E 00 00 00 00 00 00 00
FF FF 00 00 03 00 5E 5D 3F AD BD AD 52 00 00 00 53 00 00 00 08 00 00 00 00 00 00 00
FF FF 00 00 03 00 5D 3F 3F BD BD AD 53 00 00 00 09 00 00 00 08 00 00 00 00 00 00 00
FF FF 00 00 00 00 A7 AA AA 1D 1D 16 11 00 00 00 3D 00 00 00 3C 00 00 00 00 00 00 00
FF FF 00 00 00 00 B5 B5 B4 08 00 00 41 00 00 00 42 00 00 00 54 00 00 00 00 00 00 00
FF FF 00 00 03 00 43 48 5D 0C 1B 0C 54 00 00 00 42 00 00 00 48 00 00 00 00 00 00 00
FF FF 00 00 03 00 48 5D 5D 1B 1B 0C 42 00 00 00 40 00 00 00 48 00 00 00 00 00 00 00
FF FF 00 00 03 00 7C 5D 7C BD BD AD 4B 00 00 00 53 00 00 00 55 00 00 00 00 00 00 00
FF FF 00 00 03 00 5D 5E 7C BD AD AD 53 00 00 00 52 00 00 00 55 00 00 00 00 00 00 00
FF FF 00 00 03 00 19 18 2D 7F 82 7F 56 00 00 00 26 00 00 00 57 00 00 00 00 00 00 00
FF FF 00 00 03 00 18 2D 2D 82 82 7F 26 00 00 00 24 00 00 00 57 00 00 00 00 00 00 00
FF FF 00 00 03 00 10 12 19 7F 82 7F 30 00 00 00 2A 00 00 00 56 00 00 00 00 00 00 00
FF FF 00 00 03 00 12 18 19 82 82 7F 2A 00 00 00 26 00 00 00 56 00 00 00 00 00 00 00
FF FF 00 00 00 00 87 87 87 16 1C 1C 58 00 00 00 32 00 00 00 31 00 00 00 00 00 00 00
FF FF 00 00 03 00 06 07 1E 32 0B 3B 59 00 00 00 5A 00 00 00 5B 00 00 00 00 00 00 00
FF FF 00 00 03 00 07 1E 1E 0B 04 3B 5A 00 00 00 1C 00 00 00 5B 00 00 00 00 00 00 00
FF FF 00 00 03 00 1C 1C 2D AC BB AC 5C 00 00 00 28 00 00 00 5D 00 00 00 00 00 00 00
FF FF 00 00 03 00 1C 2D 2D BB BC AC 28 00 00 00 22 00 00 00 5D 00 00 00 00 00 00 00
FF FF 00 00 03 00 09 12 1C AC BB AC 0C 00 00 00 2E 00 00 00 5C 00 00 00 00 00 00 00
FF FF 00 00 03 00 12 1C 1C BB BB AC 2E 00 00 00 28 00 00 00 5C 00 00 00 00 00 00 00
FF FF 00 00 03 00 1C 1C 09 9E 90 9E 5E 00 00 00 25 00 00 00 0D 00 00 00 00 00 00 00
FF FF 00 00 03 00 1C 09 09 90 90 9E 25 00 00 00 29 00 00 00 0D 00 00 00 00 00 00 00
FF FF 00 00 03 00 2D 2D 1C 9E 90 9E 5F 00 00 00 23 00 00 00 5E 00 00 00 00 00 00 00
FF FF 00 00 03 00 2D 1C 1C 90 90 9E 23 00 00 00 25 00 00 00 5E 00 00 00 00 00 00 00
FF FF 00 00 03 00 3D 2D 2D 90 90 9E 59 00 00 00 23 00 00 00 5F 00 00 00 00 00 00 00

如果需要,我可以发布完整的文件结构。提前致谢!

编辑:

Vertex3D
{
    float x, y, z
}
Vector3D
{
    float x, y, z
}

Vertex
{
    Vertex3D    vertex
    Vector3D    normal  // Sum = 1.0
    ulong       unknown
    ubyte[12]   padding = 0
}
Triangle
{
    ulong       beg = 0xffff0000
    ushort      texture     // 0 = car bottom, 3 = body
    ubyte[6]    unknown     // UV mapping???
    ulong[3]    vertices    // Indices
    ulong       end = 0x00000000
}

Model3D
{
    char[8]     identifier = "PCMODL01"
    ulong       unknown = 0x00000000
    ulong       offset1 = 44    // Vertices start offset
    ulong       offset2         // Polygons start offset

    ubyte[16]   stuff

    ulong                   n_polygons
    ulong                   n_vertices
    Vertex[n_vertices]      vertices
    Triangle[n_polygons]    polygons
}

Main
{
    // Header
    ulong   n_blocks = 7

    ulong   offset1 = 60
    ulong   length1     // Model

    ulong   offset2
    ulong   length2     // Dash lo res (320x80) RGB565

    ulong   offset3
    ulong   length3     // Dash hi res (640x160) RGB565

    ulong   offset4
    ulong   length4     // Steering wheel (256x256) RGB565

    ulong   offset5
    ulong   length5     // Car textures (128x256) RGB565

    ulong   offset6
    ulong   length6     // Tuning

    ulong   offset7
    ulong   length7     // Menu picture (400x400) Indexed color

    // offset1 onwards
    Model3D         model

    // offset2 onwards
    blob[25600]     dash_lo

    // offset3 onwards
    blob[102400]    dash_hi

    // offset4 onwards
    blob[65536]     steer_whl

    // offset5 onwards
    blob[32768]     textures

    // offset6 onwards
    blob[300]       tuning

    // offset7 onwards
    ubyte[12]       unknown1
    ubyte           menu_position
    char[3]         basename        // CAM, JAG, VET, etc.
    ulong           padding = 0x00000000
    ulong           unknown2
    blob[160000][5] menu_screens    // 5 images, one per language
}
1个回答

问题解决了!

我发现这些unknown值实际上是纹理贴图上的像素坐标(正整数)。汽车纹理的大小为 128 x 256,因此通过将每个 U 或 V 坐标除以该方向的最大值,我们就有了正确的浮点转换:

vertex1.u = unknown[0] / 127.f;
vertex2.u = unknown[1] / 127.f;
vertex3.u = unknown[2] / 127.f;

vertex1.v = -unknown[3] / 255.f;
vertex2.v = -unknown[4] / 255.f;
vertex3.v = -unknown[5] / 255.f;

此外,我的转换器中有一些错误阻止了它的工作......