diff options
| author | Valentin Popov <valentin@popov.link> | 2026-06-22 00:58:51 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-06-22 00:58:51 +0300 |
| commit | 78fc5f1debf1395d5df0bab7cc0dde54351205cb (patch) | |
| tree | ef8f7c72a183723fcbea0b2d1fefd7c28ca7bc18 /docs/specs/msh-animation.md | |
| parent | 50c2cf4686b53ebd2b76318223096660e92305a4 (diff) | |
| download | fparkan-78fc5f1debf1395d5df0bab7cc0dde54351205cb.tar.xz fparkan-78fc5f1debf1395d5df0bab7cc0dde54351205cb.zip | |
docs: rewrite MkDocs documentation
Diffstat (limited to 'docs/specs/msh-animation.md')
| -rw-r--r-- | docs/specs/msh-animation.md | 126 |
1 files changed, 0 insertions, 126 deletions
diff --git a/docs/specs/msh-animation.md b/docs/specs/msh-animation.md deleted file mode 100644 index 1c0807a..0000000 --- a/docs/specs/msh-animation.md +++ /dev/null @@ -1,126 +0,0 @@ -# MSH animation - -`MSH animation` описывает связку `Res8 + Res19` и runtime-правила сэмплирования/смешивания поз. - -Связанные страницы: - -- [MSH core](msh-core.md) -- [Render pipeline](render.md) - -## 1. Ресурсы анимации - -### 1.1. `Res8` (пул ключей) - -```c -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` (карта кадров) - -```c -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 - -1. Если кадр вне диапазона `frame_count` -> `fallback_key`. -2. Если `anim_map_start == 0xFFFF` -> `fallback_key`. -3. Иначе берётся `map_words[anim_map_start + frame]`: - - если значение `>= fallback_key`, тоже используется `fallback_key`; - - иначе используется значение из map. - -### 2.3. Интерполяция - -Если выбран fallback, возвращается ровно этот ключ без интерполяции. - -Иначе: - -1. Берутся соседние ключи `k0` и `k1`. -2. Если `t` точно равен `k0.time` или `k1.time`, возвращается соответствующий ключ. -3. Иначе: - - `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: - -1. Выбираются валидные стороны по `blend` и валидности времени. -2. Если активна одна сторона, берётся она. -3. Если активны обе: - - применяется shortest-path flip для `qB`; - - выполняется quaternion blend; - - позиция смешивается линейно. - -Матрица строится из quaternion, а translation подставляется отдельным шагом. - -## 4. Каноника writer - -Рекомендуемые правила: - -1. Ключи узлов писать подряд в `Res8` в порядке узлов. -2. `fallback_key` узла указывает на последний ключ его трека. -3. Для узлов с map выделять блок длины `frame_count` в `Res19`. -4. Для статических узлов: `anim_map_start = 0xFFFF`, один ключ с `time=0`. -5. `Res8.attr1 = key_count`, `Res8.attr3 = 4`. -6. `Res19.attr1 = map_word_count`, `Res19.attr2 = frame_count`, `Res19.attr3 = 2`. - -## 5. Валидация перед сохранением - -- `Res8.size % 24 == 0` -- `Res19.size % 2 == 0` -- каждый `fallback_key < key_count` -- для узла с map: `anim_map_start + frame_count <= map_word_count` -- внутри трека времена ключей строго возрастают - -## 6. Статус валидации - -- Форматные проверки были покрыты legacy-валидатором. -- Корпусная валидация анимационных инвариантов выполнена на полном retail-наборе. - -## 7. Статус покрытия и что осталось до 100% - -Закрыто: - -1. Контракт `Res8 + Res19` и fallback-логика выбора ключа. -2. Базовая интерполяция поз и blending двух сэмплов. -3. Канонические инварианты writer path для существующих ассетов. - -Осталось: - -1. Полная фиксация численного поведения на всех FP-edge-case (включая платформенные различия округления). -2. Полный writer-профиль для авторинга новых анимаций без опоры на reference copy-through. -3. Набор runtime parity-тестов «frame-by-frame pose equivalence» на длинных анимациях. |
