Files
fparkan/docs/specs/msh-notes.md

119 lines
4.8 KiB
Markdown
Raw Permalink Normal View History

# 3D implementation notes
Контрольная страница с практическими правилами реализации 3D-пайплайна и с перечнем незакрытых зон.
Документ intentionally high-level: без ссылок на внутренние функции/адреса.
Связанные страницы:
- [MSH core](msh-core.md)
- [MSH animation](msh-animation.md)
- [Material (`MAT0`)](material.md)
- [Texture (`Texm`)](texture.md)
- [FXID](fxid.md)
- [Render pipeline](render.md)
## 1. Базовые двоичные правила
1. Все форматы в этой подсистеме little-endian.
2. Внутри NRes данные ресурсов выравниваются по 8 байт.
3. Внутри payload таблиц padding между записями обычно отсутствует: записи идут подряд по stride.
## 2. Быстрая карта stride'ов
| Ресурс | Запись | Stride |
|---|---|---:|
| Res1 | Node | 38 |
| Res2 | Slot | 68 (после header `0x8C`) |
| Res3 | Position | 12 |
| Res4 | Normal | 4 |
| Res5 | UV0 | 4 |
| Res6 | Index | 2 |
| Res7 | Tri descriptor | 16 |
| Res8 | Animation key | 24 |
| Res13 | Batch | 20 |
| Res19 | Animation map | 2 |
## 3. Декодирование ключевых потоков
## 3.1. Позиции (Res3)
`float3`, stride `12`.
## 3.2. Нормали (Res4)
`int8[4]`, используются первые 3 компоненты:
```text
n = clamp(s8 / 127.0, -1..1)
```
## 3.3. UV (Res5)
`int16[2]`:
```text
u = s16 / 1024.0
v = s16 / 1024.0
```
## 3.4. Animation key (Res8)
`pos(float3) + time(float) + quat(int16x4)`:
```text
q = s16 / 32767.0
```
## 4. Практический reader-контракт
Для runtime-совместимого чтения модели:
1. Найти нужные ресурсы по `type_id` в NRes.
2. Проверить `size/stride`-инварианты.
3. Проверить диапазоны ссылок:
- slot -> batch/triangles;
- batch -> indices;
- indices -> vertices;
- anim_map -> anim_keys.
4. Неизвестные поля и неизвестные ресурсы сохранять через copy-through.
## 5. Практический writer-контракт
1. Пересчитывать только явно вычислимые поля.
2. Не нормализовать opaque-данные без уверенной спецификации.
3. При roundtrip неизмененных данных требовать byte-identical результат.
4. Для новых ассетов фиксировать отдельную политику «генерация vs preserve».
## 6. Runtime-связка материалов и текстур
Канонический путь резолва:
1. Модель -> wear-таблица (`*.wea`).
2. Wear-слот -> material name.
3. Material -> текущая фаза -> `textureName`.
4. `Texm` ищется в `Textures.lib` (или lightmap-библиотеке для lightmap-ветки).
Fallback:
- материал: `DEFAULT`, затем индекс `0`;
- текстура/lightmap: fallback-слот движка.
## 7. Что уже закрыто для 1:1
1. Бинарный контракт базовых MSH таблиц.
2. Контракт animation sampling (`Res8 + Res19`).
3. Контракт MAT0/WEAR/Texm на уровне чтения и применения в кадре.
4. Формат FXID-контейнера, командный поток и fixed command sizes.
5. Валидация на retail-корпусе через `tools/msh_doc_validator.py` (0 ошибок/предупреждений).
## 8. Статус покрытия и что осталось до 100%
1. Полная field-level семантика части служебных полей:
- `Batch20` opaque-поля;
- хвостовые служебные поля slot-записей;
- часть флагов узлов/групп.
2. Полный writer-путь для авторинга новых анимированных ассетов (не только roundtrip существующих).
3. Полная формализация семантики FX payload полей по каждому opcode для генерации новых эффектов, а не только для корректного чтения/исполнения.
4. Полный канонический writer `Texm` для всех редких форматов и edge-case комбинаций служебных флагов.
5. Сквозной «импорт внешнего ассета -> игровой пакет» с формальной спецификацией sidecar-метаданных (материал/эффект/анимация).