- 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.
4.2 KiB
4.2 KiB
MSH animation
MSH animation описывает связку Res8 + Res19 и runtime-правила сэмплирования/смешивания поз.
Связанные страницы:
1. Ресурсы анимации
1.1. Res8 (пул ключей)
struct AnimKey24 {
float pos_x;
float pos_y;
float pos_z;
float time;
int16_t qx;
int16_t qy;
int16_t qz;
int16_t qw;
};
Декодирование quaternion-компонент: q = s16 / 32767.0.
1.2. Res19 (карта кадров)
uint16_t map_words[]; // size/2 элементов
Res19.attr2 хранит глобальную длину таймлайна (число кадров).
1.3. Связь с Res1
Для каждого узла:
anim_map_start(hdr2) — начало блока вRes19или0xFFFF.fallback_key(hdr3) — индекс fallback-ключа вRes8.
2. Сэмплирование узла
Вход: время t, текущий узел.
Выход: quat(w,x,y,z) и pos(x,y,z).
2.1. Индекс кадра
Движок использует x87-совместимое округление для выражения t - 0.5.
Для 1:1 повторения нужно сохранить ту же политику плавающей точки.
2.2. Выбор key index
- Если кадр вне диапазона
frame_count->fallback_key. - Если
anim_map_start == 0xFFFF->fallback_key. - Иначе берётся
map_words[anim_map_start + frame]:- если значение
>= fallback_key, тоже используетсяfallback_key; - иначе используется значение из map.
- если значение
2.3. Интерполяция
Если выбран fallback, возвращается ровно этот ключ без интерполяции.
Иначе:
- Берутся соседние ключи
k0иk1. - Если
tточно равенk0.timeилиk1.time, возвращается соответствующий ключ. - Иначе:
alpha = (t - k0.time) / (k1.time - k0.time)pos = lerp(k0.pos, k1.pos, alpha)quat = slerp_like(k0.quat, k1.quat, alpha)
Кватернион в runtime хранится в порядке [w, x, y, z].
3. Смешивание двух сэмплов
При blending между позами A и B:
- Выбираются валидные стороны по
blendи валидности времени. - Если активна одна сторона, берётся она.
- Если активны обе:
- применяется shortest-path flip для
qB; - выполняется quaternion blend;
- позиция смешивается линейно.
- применяется shortest-path flip для
Матрица строится из quaternion, а translation подставляется отдельным шагом.
4. Каноника writer
Рекомендуемые правила:
- Ключи узлов писать подряд в
Res8в порядке узлов. fallback_keyузла указывает на последний ключ его трека.- Для узлов с map выделять блок длины
frame_countвRes19. - Для статических узлов:
anim_map_start = 0xFFFF, один ключ сtime=0. Res8.attr1 = key_count,Res8.attr3 = 4.Res19.attr1 = map_word_count,Res19.attr2 = frame_count,Res19.attr3 = 2.
5. Валидация перед сохранением
Res8.size % 24 == 0Res19.size % 2 == 0- каждый
fallback_key < key_count - для узла с map:
anim_map_start + frame_count <= map_word_count - внутри трека времена ключей строго возрастают
6. Статус валидации
- Форматные проверки включены в
tools/msh_doc_validator.py. - В текущем окружении полный игровой корпус MSH не подключен в
testdata, поэтому массовый прогон здесь не выполнялся.