image

Еще одна статья о разборе форматов, для летнего воскресного вечера, небольшая и развлекательная. На этот раз речь пойдёт о 3d-моделях. Принципы хранения данных для любых моделей одинаковы, но форматы файлов весьма разнообразны. Даже в условиях одного и того же движка разработчики норовят всё модифицировать и впихнуть что-нибудь своё, ведь в коммерческих версиях у них есть возможность менять код движка, и они ей обычно пользуются.

Основной объём любого файла с моделью составляют несколько больших таблиц с данными о вершинах, о том, как они соединяются и как на них натягиваются текстуры. Начнём с вершин. Простой список с координатами x,y,z может выглядеть например так:



Так как чаще всего координаты лежат в виде 32-битных плавающих чисел, их легко распознать внутри файла по повторяющимся через 4 байта цифрам в диапазоне 40-45, или для отрицательных чисел C0-C5. Конечно встречаются и другие байты, но эти чаще всего. Так происходит потому, что диапазон координат 3d-модели небольшой с точки зрения порядка, а порядок как раз хранится в старшем байте.

Далее, нужна таблица, где указано, в каком порядке вершины соединяются в треугольники. Чаще всего она выглядит так:



Это 16-битные номера вершин, группами по три. Так как в моделях обычно не более нескольких сотен вершин, числа эти маленькие, и такую таблицу тоже легко видно визуально. В данном примере выделен один из треугольников, состоящий из вершин с номерами 50,51 и 52.

И третья — таблица текстурных координат, чтобы привязать вершины к плоской текстуре, которую нужно на них натянуть.



Координаты x и y в пределах текстуры приводятся к диапазону от 0 до 1, и если текстура имеет размер 2048x2048 или 4096x4096, нет смысла в высокой точности. Поэтому они чаще всего хранятся как плавающие числа с половинной точностью, 16 битные. Старший байт у них получается чуть больше 0x30, изредка доходя до 0x40 или чуть больше. Здесь красным и оранжевым выделены текстурные координаты, зеленым и светло-зеленым — координаты на карте освещения.

После того, как найдены эти таблицы, можно посчитать количество элементов, найти, где это количество хранится и как описывается вся структура. Но кроме этих таблиц в файле обязательно найдутся много мелких непонятных чисел, которые неизвестно к чему относятся и что означают. Вот например, в середине файла с моделью человека имеются три плавающих единицы (выделены зеленым):



Как узнать, что они обозначают? Да просто поменять их и посмотреть, что получится. Запишем вместо них 1,5 и запустим игру



Ну конечно, это масштаб. Интересный эффект получается от того, что анимация записана в других файлах отдельно, и она завязана на координаты в моделях, поэтому возникают такие причудливые уродцы. У мужчины на площади на плечах сидит ребенок. Теперь он оказался у него внутри грудной клетки. Человек перед шлагбаумом, совершающий непонятные движения, на самом деле аплодирует.

Теперь попробуем определить, где здесь ширина, а где высота. Изменим только одно число, первое: уменьшим его в 10 раз.



Таким образом, экспериментируя, можно определить значение оставшихся чисел. Если же при изменении каких-то из них ничего не происходит, просто оставим их в покое. Может быть мы никогда не узнаем, зачем они нужны. А если вдруг однажды они дадут о себе знать — тогда и будем разбираться.

Вот один из примеров, когда разобрать формат файла аналитически бывает легче и быстрее, чем изучать exe-шник, где можно заблудиться в дебрях кода, скармливающего всю эту информацию видеоподсистеме.

Комментарии (12)


  1. AllexIn
    19.07.2015 21:38

    Аналогичным образом в свое время разобрал формат карт для Периметра.
    Но все гораздо хуже в проектах, которые следят за целостностью файлов или как-то пакуют данные.
    Правда последнее время большинство разработчиков этого не делают, потому что аппаратные ресурсы практически безграничные, а шифроваться нет смысла, т.к. модо-творчество — путь к второй жизни игры.


    1. ID_Daemon Автор
      19.07.2015 21:43
      +2

      Упаковка сейчас очень широко используется. Пример был в прошлой статье: habrahabr.ru/post/261561


      1. AllexIn
        19.07.2015 21:45

        Мне кажется это скорее исключение.
        Я на своей практике встречал игру в которой данные не просто паковались, а еще и шифровались… Но это тоже скорее исключение. :)
        Как правило данные лежат в виде максимально комфортном для быстрой загрузки, что существенно упрощает их обработку.


        1. ID_Daemon Автор
          19.07.2015 21:55
          +1

          По моему опыту, наоборот. Большинство «больших» игр пакует либо все ресурсы, либо за исключением видео и звука, которые всё равно сильно не сжимаются.


          1. beeruser
            20.07.2015 01:03
            +1

            >> либо за исключением видео и звука, которые всё равно сильно не сжимаются
            Они _уже_ пожаты. Кто-то хранит голый wave, или видео в виде последовательности .tga? =)


            1. ID_Daemon Автор
              20.07.2015 13:48

              Речь не о том, «пожаты» они сами по себе или нет. Я просто сказал, что есть игры, которые пакуют всё. Для примера возьмем такую известную серию как Doom/Quake. Все ресурсы, включая звук, одной кучей упакованы в zip-архив.


        1. Leopotam
          19.07.2015 23:17

          Внешняя память всегда самая медленная — практически всегда быстрее прочитать небольшой блок упакованных данных одним куском и потом распаковать его в значительно больший объем данных для использования в оперативной памяти.


  1. saboteur_kiev
    19.07.2015 23:16

    Реверс-инженеринг 3д форматов впервые делал в Elite для ZX-Spectrum. Там 3д модели кораблей были простые, разобраться было несложно. Наделал кучку совершенно других моделей, было весело.
    Сейчас реверс-инженеринг с последующим ковырянием модели в hex-едиторе выглядит как-то по-детски. Гораздо проще выдрать модель целиком и отредактировать ее в соответствующем редакторе.
    Тем более, что на самом деле гораздо удобнее взять редактор моделей, который подходит для определенного движка, и модели поправить в нем.
    Также можно создать в нем простейшие модели каких-либо фигур, и реверсить на них, а не на таких сложных моделях как фигура человека со всеми его формами.


    1. AllexIn
      19.07.2015 23:23
      +1

      Никто не говорит о редактировании модели в HEX редакторе.
      Речь о том, чтобы разобрать формат и потом сделать импортер/экспортер, например.


      1. Mrrl
        20.07.2015 02:34

        Импортёр — ладно. Но для экспортёра понадобится знать, что прописывать в те самые магические числа, смысла которых понять не удалось. Если новая модель будет хотя бы иногда показывать что-то правдоподобное — то уже повезло. Но скорее всего, при небольшом изменении топологии или числа вершин/треугольников всё сломается так, что не разберёшь.


    1. ID_Daemon Автор
      19.07.2015 23:30
      +3

      Я потому и написал в самом начале, что разработчики модифицируют движки. Ни один редактор обычно не подходит.


  1. SHVV
    20.07.2015 10:00
    +1

    Что-то маловато написали.
    Думаю, стоит упомянуть ещё несколько таблиц, которые тоже бывают: нормали (возможно со знаком бинормали в третьем компоненте), веса костей для скелетной анимации. Ещё текстурных координат может быть два набора (для стационарной геометрии).

    Таблицы могут записываться как отдельно, так и вперемешку (то есть все компоненты вершины описывается одной записью), так как во втором случае производительность несколько выше.

    Ещё могут быть лоды, описания габартных контейнеров, сам скелет с иерархией костей и т.д.