Texture Dictionary
Текстуры в вайсе упакованы в формате движка игры - RenderWare. Формат сам по себе чанковый, и на первый взгляд немного неудобный.
Базовая структура каждого чанка:
int section - тип чанка
int size - размер чанка, включая все дочерние
int version - версия RenderWare
Корневой чанк файла -
0x0016. Первым в нём идёт чанк содержит в себе следующие данные:
chunk struct - чанк, содержащий базовую информацию об архиве текстур.
chunk[texCount] textures - чанки каждой текстуры. Описаны ниже.
chunk extension - пустой чанк, можно смело обрывать чтение файла на предыдущем пункте.
Struct-чанк, описанный выше, имеет ID
0x0001, внутри два инта:
int texCount - количество текстур.
int device - колдунственное число, обозначает DX8 или DX9, зачем - загадка.
Подчанки текстур имею заголовок
0x0015, являются контейнером для одной текстуры.
chunk struct - собственно одна текстура. Имеет самую толстую спеку из всех чанков.
chunk extension - опять же пустой чанк. В PS2-версии формата содержит какие-то данные, но в PC остаётся пустым.
Текстурный struct-чанк, так же имеет ID
0x0001, держит в себе данные и параметры текстуры:
int platform - для вайса должно быть равно 8, иначе алярм.
int addressing - оче хитро сжатая информация об сглаживании и адресации текстур. Как разжать описано ниже.
chr[32] name - имя текстуры. Null-terminated, неиспользованные байты заполнены "\0".
chr[32] mask - название маски текстуры. Я не использую, назначение сомнительное. Хранится так же, как и имя.
int raster - формат растра. Список ниже.
int alpha - аж целый инт для простого флажка, есть ли альфа или нет...
short width - ширина.
short height - высота.
byte depth - глубина цвета в битах.
byte mipcount - количество mip-уровней текстуры.
byte type - всегда равно 4.
byte compression - какое сжатие текстур использовано. 0 - никакого, 1 - DXT1, 3 - DXT3.
Дальше, если raster содержит битовый флаг
0x2000, дальше следует палитра:
int[256] palette - цвета палитры для каждого индекса в формате RGBA.
Следом, для каждого из mip-уровней повторяется следующее:
int size - размер в байтах. В зависимости от формата и фазы луны, может равняться нулю. Это необходимо проверять и пересчитывать вручную размер.
byte[size] data - данные картинки.
|
Как раскодировать сглаживание и адресацию.
Хранится всё в одном инте, но используются по сути два первых байта. Первый байт - это режим фильтрации, список режимов прилагается. Следующий байт надо разбить на два блока по 4 бита, первый блок - адресация по U, второй - по V. Типы адресации тоже прилагаются.
Типы растра:
FORMAT_DEFAULT 0x0000
FORMAT_1555 0x0100 (однобитная альфа, RGB 5 бит на канал; этот же формат используется для DXT1 с альфой)
FORMAT_565 0x0200 (5 бит красного, 6 бит зелёного, 5 бит синего; используется DXT1 без альфы)
FORMAT_4444 0x0300 (RGBA 4 бита на канал; также используется для DXT3)
FORMAT_LUM8 0x0400 (gray scale)
FORMAT_8888 0x0500 (RGBA 8 бит на канал)
FORMAT_888 0x0600 (RGB 8 бит на канал без альфы)
FORMAT_555 0x0A00 (RGB 5 бит на канал - очень редкий формат)
FORMAT_EXT_AUTO_MIPMAP 0x1000 (движок должен сгенерировать мипмапы)
FORMAT_EXT_PAL8 0x2000 (2^8 = 256 цветов в палитре)
FORMAT_EXT_PAL4 0x4000 (2^4 = 16 цветов в палитре)
FORMAT_EXT_MIPMAP 0x8000 (мипмапы прилагаются)
Типы фильтрации:
FILTER_NONE 0x00
FILTER_NEAREST 0x01
FILTER_LINEAR 0x02
FILTER_MIP_NEAREST 0x03
FILTER_MIP_LINEAR 0x04
FILTER_LINEAR_MIP_NEAREST 0x05
FILTER_LINEAR_MIP_LINEAR 0x06
Типы адресации текстурных координат:
WRAP_NONE 0x00
WRAP_WRAP 0x01
WRAP_MIRROR 0x02
WRAP_CLAMP 0x03
Как говорится, первый блин комом, поэтому первые попытки прочитать текстуры были, мягко говоря, неудачными:
Однако, спустя некоторое время я понял, что неправильно читал размер для каждого мип-уровня. Вместо int я читал short, два байта терялись и ломали остальные данные. После поправки, всё встало на свои места: