2026-02-11 21:12:05 +00:00
|
|
|
|
# 3D implementation notes
|
|
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
Контрольная страница с практическими правилами реализации 3D-пайплайна и с перечнем незакрытых зон.
|
|
|
|
|
|
Документ intentionally high-level: без ссылок на внутренние функции/адреса.
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
Связанные страницы:
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
- [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)
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 1. Базовые двоичные правила
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
1. Все форматы в этой подсистеме little-endian.
|
|
|
|
|
|
2. Внутри NRes данные ресурсов выравниваются по 8 байт.
|
|
|
|
|
|
3. Внутри payload таблиц padding между записями обычно отсутствует: записи идут подряд по stride.
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 2. Быстрая карта stride'ов
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
| Ресурс | Запись | 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 |
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 3. Декодирование ключевых потоков
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 3.1. Позиции (Res3)
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
`float3`, stride `12`.
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 3.2. Нормали (Res4)
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
`int8[4]`, используются первые 3 компоненты:
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
```text
|
|
|
|
|
|
n = clamp(s8 / 127.0, -1..1)
|
2026-02-11 21:12:05 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 3.3. UV (Res5)
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
`int16[2]`:
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
```text
|
|
|
|
|
|
u = s16 / 1024.0
|
|
|
|
|
|
v = s16 / 1024.0
|
2026-02-11 21:12:05 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 3.4. Animation key (Res8)
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
`pos(float3) + time(float) + quat(int16x4)`:
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
```text
|
|
|
|
|
|
q = s16 / 32767.0
|
2026-02-11 21:12:05 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 4. Практический reader-контракт
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
Для runtime-совместимого чтения модели:
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
1. Найти нужные ресурсы по `type_id` в NRes.
|
|
|
|
|
|
2. Проверить `size/stride`-инварианты.
|
|
|
|
|
|
3. Проверить диапазоны ссылок:
|
|
|
|
|
|
- slot -> batch/triangles;
|
|
|
|
|
|
- batch -> indices;
|
|
|
|
|
|
- indices -> vertices;
|
|
|
|
|
|
- anim_map -> anim_keys.
|
|
|
|
|
|
4. Неизвестные поля и неизвестные ресурсы сохранять через copy-through.
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 5. Практический writer-контракт
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
1. Пересчитывать только явно вычислимые поля.
|
|
|
|
|
|
2. Не нормализовать opaque-данные без уверенной спецификации.
|
|
|
|
|
|
3. При roundtrip неизмененных данных требовать byte-identical результат.
|
|
|
|
|
|
4. Для новых ассетов фиксировать отдельную политику «генерация vs preserve».
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 6. Runtime-связка материалов и текстур
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
Канонический путь резолва:
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
1. Модель -> wear-таблица (`*.wea`).
|
|
|
|
|
|
2. Wear-слот -> material name.
|
|
|
|
|
|
3. Material -> текущая фаза -> `textureName`.
|
|
|
|
|
|
4. `Texm` ищется в `Textures.lib` (или lightmap-библиотеке для lightmap-ветки).
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
Fallback:
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
- материал: `DEFAULT`, затем индекс `0`;
|
|
|
|
|
|
- текстура/lightmap: fallback-слот движка.
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 7. Что уже закрыто для 1:1
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
1. Бинарный контракт базовых MSH таблиц.
|
|
|
|
|
|
2. Контракт animation sampling (`Res8 + Res19`).
|
|
|
|
|
|
3. Контракт MAT0/WEAR/Texm на уровне чтения и применения в кадре.
|
|
|
|
|
|
4. Формат FXID-контейнера, командный поток и fixed command sizes.
|
|
|
|
|
|
5. Валидация на retail-корпусе через `tools/msh_doc_validator.py` (0 ошибок/предупреждений).
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
## 8. Статус покрытия и что осталось до 100%
|
2026-02-11 21:12:05 +00:00
|
|
|
|
|
2026-02-19 11:07:04 +04:00
|
|
|
|
1. Полная field-level семантика части служебных полей:
|
|
|
|
|
|
- `Batch20` opaque-поля;
|
|
|
|
|
|
- хвостовые служебные поля slot-записей;
|
|
|
|
|
|
- часть флагов узлов/групп.
|
|
|
|
|
|
2. Полный writer-путь для авторинга новых анимированных ассетов (не только roundtrip существующих).
|
|
|
|
|
|
3. Полная формализация семантики FX payload полей по каждому opcode для генерации новых эффектов, а не только для корректного чтения/исполнения.
|
|
|
|
|
|
4. Полный канонический writer `Texm` для всех редких форматов и edge-case комбинаций служебных флагов.
|
|
|
|
|
|
5. Сквозной «импорт внешнего ассета -> игровой пакет» с формальной спецификацией sidecar-метаданных (материал/эффект/анимация).
|