From 0e19660eb5122c8c52d5e909927884ad5c50b813 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Thu, 19 Feb 2026 04:46:23 +0400 Subject: Refactor documentation structure and add new specifications - Updated MSH documentation to reflect changes in material, wear, and texture specifications. - Introduced new `render.md` file detailing the render pipeline process. - Removed outdated sections from `runtime-pipeline.md` and redirected to `render.md`. - Added detailed specifications for `Texm` texture format and `WEAR` wear table. - Updated navigation in `mkdocs.yml` to align with new documentation structure. --- docs/specs/material.md | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 docs/specs/material.md (limited to 'docs/specs/material.md') diff --git a/docs/specs/material.md b/docs/specs/material.md new file mode 100644 index 0000000..cd7eea5 --- /dev/null +++ b/docs/specs/material.md @@ -0,0 +1,130 @@ +# Material (`MAT0`) + +`MAT0` описывает материал и его фазовую анимацию. + +Связанные страницы: + +- [Wear table (`WEAR`)](wear.md) +- [Texture (`Texm`)](texture.md) +- [Render pipeline](render.md) + +## 1. Контейнер + +- Тип ресурса: `0x3054414D` (`MAT0`). +- Обычно хранится в `Material.lib`. +- `attr1` используется как битовое поле runtime-флагов материала. +- `attr2` задаёт версию заголовка payload. + +## 2. Бинарный layout + +```c +struct Mat0Payload { + uint16_t phaseCount; + uint16_t animBlockCount; // должно быть < 20 + + // если attr2 >= 2 + uint8_t metaA8; + uint8_t metaB8; + // если attr2 >= 3 + uint32_t metaC32; + // если attr2 >= 4 + uint32_t metaD32; + + PhaseRecord34 phases[phaseCount]; + AnimBlockRaw anim[animBlockCount]; +}; +``` + +Если `attr2 < 2`, используются runtime-значения по умолчанию: + +- `metaA = 255` +- `metaB = 255` +- `metaC = 1.0f` +- `metaD = 0` + +## 3. Фазы материала + +```c +struct PhaseRecord34 { + uint8_t params[18]; + char textureName[16]; +}; +``` + +В рантайме запись разворачивается в структуру ~76 байт: + +- набор коэффициентов цвета/освещения/прозрачности; +- индекс слота текстуры; +- дополнительные целочисленные поля. + +`textureName`: + +- пустая строка -> фаза без текстуры (`texSlot = -1`); +- непустая строка -> загрузка текстуры по имени. + +## 4. Анимационные блоки + +```c +struct AnimBlockRaw { + uint32_t headerRaw; // mode = low 3 bits, interpMask = остальные + uint16_t keyCount; + KeyRaw keys[keyCount]; +}; + +struct KeyRaw { + uint16_t k0; + uint16_t k1; + uint16_t k2; // opaque, сохранять 1:1 +}; +``` + +`k2` нельзя удалять или нормализовать: это часть бинарного контракта. + +## 5. Выбор текущей фазы + +Материал выбирает фазу по времени и по режиму анимации блока: + +- loop; +- ping-pong; +- one-shot с clamp; +- random-offset. + +При смешивании интерполируется только часть полей, остальные копируются из активной фазы. +Для 1:1 совместимости важно сохранить эту выборочную интерполяцию. + +## 6. Загрузка и fallback + +При запросе материала по имени: + +1. Точный поиск по имени. +2. Если не найдено — fallback на `DEFAULT`. +3. Если `DEFAULT` отсутствует — используется запись с индексом `0`. + +## 7. Атрибуты и флаги + +Практически важные биты `attr1`: + +- бит загрузки текстурной фазы с расширенными флагами; +- флаги аппаратного профиля; +- 4-битный режим (`nibbleMode`); +- дополнительный флаг material-поведения. + +Неизвестные биты должны сохраняться без изменений. + +## 8. Ограничения + +- `animBlockCount < 20` +- `phaseCount` и фактический размер секции фаз должны совпадать +- `textureName` должен быть NUL-terminated и укладываться в 16 байт + +## 9. Правила writer/editor + +1. Сохранять `attr1/attr2/attr3`. +2. Не менять `metaA/B/C/D` без явного запроса. +3. Сохранять opaque-поля анимации (включая `k2`) 1:1. +4. Проверять выход за границы payload при парсинге. + +## 10. Статус валидации + +- Инварианты MAT0 зафиксированы в текущем toolchain проекта (`docs/specs` + `tools`). +- В этом окружении нет полного игрового корпуса, поэтому статистика по всем материалам не пересчитывалась. -- cgit v1.2.3