- 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.
131 lines
4.3 KiB
Markdown
131 lines
4.3 KiB
Markdown
# 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`).
|
||
- В этом окружении нет полного игрового корпуса, поэтому статистика по всем материалам не пересчитывалась.
|