1
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-12-11 04:51:21 +04:00
Files
parkan-playground/ParkanPlayground/MSH_FORMAT.md
bird_egop a8536f938d fxid
2025-12-09 02:32:32 +03:00

16 KiB
Raw Permalink Blame History

Документация формата MSH

Формат .msh используется игрой Parkan: Железная стратегия (1998) для хранения 3D-мешей. MSH файлы — это NRes архивы, содержащие несколько типизированных компонентов.

Обзор

Существует два варианта формата MSH:

Вариант Применение Ключевые компоненты Хранение треугольников
Модель Роботы, здания, объекты 06, 0D, 07 Индексированные треугольники
Ландшафт Террейн 0B, 15 Прямые треугольники

Автоопределение типа

Модель:    Есть компонент 06 (индексы) И 0D (батчи)
Ландшафт:  Есть компонент 0B (материалы) И НЕТ компонента 06

Сводка компонентов

Тип Название Размер элемента Описание
01 Pieces 38 (0x26) Части меша / тайлы с LOD-ссылками
02 Submeshes 68 (0x44) LOD части с баундинг-боксами
03 Vertices 12 (0x0C) Позиции вершин (Vector3)
04 неизвестно 4 (неизвестно)
05 неизвестно 4 (неизвестно)
06 Indices 2 Индексы вершин треугольников (только Модель)
07 неизвестно 16 (только Модель)
08 Animations 4 Кейфреймы анимации меша
0A ExternalRefs переменный Внешние ссылки на меши (строки)
0B неизвестно 4 неизвестно (только Ландшафт)
0D неизвестно 20 (0x14) неизвестно (только Модель)
0E неизвестно 4 неизвестно (только Ландшафт)
12 MicrotextureMap 4 неизвестно
13 ShortAnims 2 Короткие индексы анимаций
15 неизвестно 28 (0x1C) неизвестно

Поток данных

Модель (роботы, здания)

Компонент 01 (Pieces - части)
    │
    └─► Lod[n] ──► Компонент 02 (индекс сабмеша)
                        │
                        ├─► StartIndexIn07 ──► Компонент 07 (данные на треугольник)
                        │
                        └─► StartOffsetIn0d:ByteLengthIn0D ──► Компонент 0D (батчи)
                                                                    │
                                                                    ├─► IndexInto06:CountOf06 ──► Компонент 06 (индексы)
                                                                    │                                   │
                                                                    │                                   └─► Компонент 03 (вершины)
                                                                    │
                                                                    └─► IndexInto03 (базовое смещение вершины)

Ландшафт (террейн)

Компонент 01 (Тайлы, обычно 16×16 = 256)
    │
    └─► Lod[n] ──► Компонент 02 (индекс сабмеша)
                        │
                        └─► StartIndexIn07:CountIn07 ──► Компонент 15 (треугольники)
                                                              │
                                                              └─► Vertex1/2/3Index ──► Компонент 03 (вершины)
                                                         
                        └─► StartIndexIn07:CountIn07 ──► Компонент 0B (материалы, параллельно 15)

Важно: В ландшафтных мешах поля StartIndexIn07 и CountIn07 в Компоненте 02 используются для индексации в Компонент 15 (треугольники), а не в Компонент 07.


Структуры компонентов

Компонент 01 - Pieces (0x26 = 38 байт)

Определяет части меша (для моделей) или тайлы террейна (для ландшафтов).

Смещение Размер Тип Поле Описание
0x00 1 byte Type1 Флаги типа части
0x01 1 byte Type2 Дополнительные флаги
0x02 2 int16 ParentIndex Индекс родителя (-1 = корень)
0x04 2 int16 OffsetIntoFile13 Смещение в короткие анимации
0x06 2 int16 IndexInFile08 Индекс в анимации
0x08 30 ushort[15] Lod Индексы сабмешей по LOD-уровням (0xFFFF = не используется)

Ландшафт: 256 тайлов в сетке 16×16. Каждый тайл имеет 2 LOD (индексы 0-255 и 256-511).


Компонент 02 - Submeshes (Заголовок: 0x8C = 140 байт, Элемент: 0x44 = 68 байт)

Заголовок (140 байт)

Смещение Размер Тип Поле Описание
0x00 96 Vector3[8] BoundingBox 8-точечный баундинг-бокс
0x60 12 Vector3 Center Центральная точка
0x6C 4 float CenterW W-компонента
0x70 12 Vector3 Bottom Нижняя точка
0x7C 12 Vector3 Top Верхняя точка
0x88 4 float XYRadius Радиус в плоскости XY

Элемент (68 байт)

Смещение Размер Тип Поле Описание
0x00 2 ushort StartIndexIn07 Модель: Начальный индекс в Компоненте 07
Ландшафт: Начальный индекс треугольника в Компоненте 15
0x02 2 ushort CountIn07 Модель: Количество в Компоненте 07
Ландшафт: Количество треугольников
0x04 2 ushort StartOffsetIn0d Начальное смещение в Компоненте 0D (только Модель)
0x06 2 ushort ByteLengthIn0D Количество батчей в Компоненте 0D (только Модель)
0x08 12 Vector3 LocalMinimum Минимум локального баундинг-бокса
0x14 12 Vector3 LocalMaximum Максимум локального баундинг-бокса
0x20 12 Vector3 Center Центр сабмеша
0x2C 12 Vector3 Vector4 Неизвестно
0x38 12 Vector3 Vector5 Неизвестно

Компонент 03 - Vertices (0x0C = 12 байт)

Смещение Размер Тип Поле Описание
0x00 4 float X Координата X
0x04 4 float Y Координата Y
0x08 4 float Z Координата Z

Компонент 06 - Indices (2 байта) - Только Модель

Массив ushort значений — индексы вершин треугольников. Используются группами по 3 для каждого треугольника. Ссылки через батчи Компонента 0D.


Компонент 07 - Triangle Data (0x10 = 16 байт) - Только Модель

Данные рендеринга на каждый треугольник.

Смещение Размер Тип Поле Описание
0x00 2 ushort Flags Флаги рендера
0x02 2 ushort Magic02 Неизвестно
0x04 2 ushort Magic04 Неизвестно
0x06 2 ushort Magic06 Неизвестно
0x08 2 int16 OffsetX Нормализованный X (÷32767 для -1..1)
0x0A 2 int16 OffsetY Нормализованный Y (÷32767 для -1..1)
0x0C 2 int16 OffsetZ Нормализованный Z (÷32767 для -1..1)
0x0E 2 ushort Magic14 Неизвестно

Компонент 0B - Material Data (4 байта) - Только Ландшафт

Информация о материале/текстуре на каждый треугольник. Параллельный массив к Компоненту 15.

Смещение Размер Тип Поле Описание
0x00 2 ushort HighWord Индекс материала/текстуры
0x02 2 ushort LowWord Индекс треугольника (последовательный)

Компонент 0D - Draw Batches (0x14 = 20 байт) - Только Модель

Определяет батчи вызовов отрисовки.

Смещение Размер Тип Поле Описание
0x00 2 ushort Flags Флаги батча
0x02 2 - Padding -
0x04 1 byte Magic04 Неизвестно
0x05 1 byte Magic05 Неизвестно
0x06 2 ushort Magic06 Неизвестно
0x08 2 ushort CountOf06 Количество индексов для отрисовки
0x0A 4 int32 IndexInto06 Начальный индекс в Компоненте 06
0x0E 2 ushort CountOf03 Количество вершин
0x10 4 int32 IndexInto03 Базовое смещение вершины в Компоненте 03

Компонент 15 - Triangles (0x1C = 28 байт)

Прямые определения треугольников. Используется и Моделью и Ландшафтом, но только Ландшафт использует их напрямую для рендеринга.

Смещение Размер Тип Поле Описание
0x00 4 uint32 Flags Флаги треугольника (0x20000 = коллизия)
0x04 4 uint32 MaterialData Данные материала (см. ниже)
0x08 2 ushort Vertex1Index Индекс первой вершины
0x0A 2 ushort Vertex2Index Индекс второй вершины
0x0C 2 ushort Vertex3Index Индекс третьей вершины
0x0E 4 uint32 Magic0E Неизвестно
0x12 4 uint32 Magic12 Неизвестно
0x16 4 uint32 Magic16 Неизвестно
0x1A 2 ushort Magic1A Неизвестно

MaterialData (0x04) - Структура материала

MaterialData = 0xFFFF_SSPP
                    │  │└─ PP: Основной материал (byte 0)
                    │  └─── SS: Вторичный материал для блендинга (byte 1)
                    └────── Всегда 0xFFFF (байты 2-3)
Значение SS Описание
0xFF Сплошной материал (без блендинга)
0x01-0xFE Индекс вторичного материала для блендинга

Примеры:

  • 0xFFFFFF01 = Сплошной материал 1
  • 0xFFFF0203 = Материал 3 с блендингом в материал 2

Компонент 0A - External References (переменный размер)

Таблица строк для внешних ссылок на части меша. Формат:

[4 байта: длина] [байты строки] [null-терминатор]
...повтор...

Длина 0 означает пустую запись. Строки типа "central" имеют особое значение (flag |= 1).


Пример: Ландшафт SC_1

Land.msh (SC_1):
├── 01: 256 тайлов (сетка 16×16)
├── 02: 512 сабмешей (256 LOD0 + 256 LOD1)
├── 03: 10 530 вершин
├── 04: 10 530 данных на вершину
├── 05: 10 530 данных на вершину
├── 0B: 7 882 записи материалов
├── 0E: 10 530 данных на вершину
├── 12: 10 530 микротекстурный маппинг
└── 15: 7 882 треугольника
        ├── LOD 0: 4 993 треугольника (тайлы 0-255 → сабмеши 0-255)
        └── LOD 1: 2 889 треугольников (тайлы 0-255 → сабмеши 256-511)

Использование

var converter = new MshConverter();

// Автоопределение типа и конвертация в OBJ
converter.Convert("Land.msh", "terrain.obj", lodLevel: 0);
converter.Convert("robot.msh", "robot.obj", lodLevel: 0);

// Ручное определение типа
var archive = NResParser.ReadFile("mesh.msh").Archive;
var type = MshConverter.DetectMeshType(archive);
// Возвращает: MshType.Model или MshType.Landscape

Формат WEA - Файлы материалов ландшафта

Файлы .wea — текстовые файлы, определяющие таблицу материалов для ландшафта.

Формат

{count}
{index} {material_name}
{index} {material_name}
...

Связь с Land.msh

Каждая карта имеет два файла материалов:

Файл Используется для Треугольники в Comp15
Land1.wea LOD0 (высокая детализация) Первые N (сумма CountIn07 для LOD0)
Land2.wea LOD1 (низкая детализация) Остальные

Пример (SC_1)

Land1.wea:

4
0 B_S0
1 L04
2 L02
3 L00

Land2.wea:

4
0 DEFAULT
1 L05
2 L03
3 L01

Маппинг материалов

Индекс материала в Comp15.MaterialData & 0xFF → строка в .wea файле.

Треугольник с MaterialData = 0xFFFF0102
  └─ Основной материал = 02 → Land1.wea[2] = "L02"
  └─ Блендинг с материалом = 01 → Land1.wea[1] = "L04"

Типичные имена материалов

Префикс Назначение
L00-L05 Текстуры ландшафта (grass, dirt, etc.)
B_S0 Базовая текстура
DEFAULT Фолбэк для LOD1
WATER Вода (поверхность)
WATER_BOT Вода (дно)
WATER_M Вода LOD1

Источники

  • Реверс-инжиниринг Terrain.dll (класс CLandscape)
  • Декомпиляция Ghidra: CLandscape::ctor и IMesh2_of_CLandscape::Render