diff --git a/docs/DIARY.md b/docs/DIARY.md index d5bac67..e960553 100644 --- a/docs/DIARY.md +++ b/docs/DIARY.md @@ -124,6 +124,26 @@ origin. Посадка: глаз + 20 вперёд + 6 вправо − 10 вн `batch.material` с позицией материала в `world.materials` (дедупликация по имени); (3) `--only-material` фильтрует батчи, но не мешает ли ему что-то ещё. +**A26, состояние на 2026-10-17:** сделаны секвенции (с определением шага записи +по данным), кости и веса вершин, слияние включённых моделей (у игрока 465 +секвенций), чтение `.ani` (7,1 МБ, 1563 анимации, 247 блоков), декодер кадров +(`mstudioanim_t`, проверен: 280 кадров, 51 дорожка), сборка кватерниона с +нормировкой 1/32768 (выбрана замером: умножение на rot_scale давало 1,63 — +для кватерниона невозможно) и CPU-скиннинг (виден кадром). + +**Следующий шаг — проигрывание.** План, чтобы не искать заново: +1. `PropMesh` (или `ModelInstance`) должен держать **данные анимации**: + `.ani` (7 МБ) + список блоков + описания анимаций, ссылкой `Arc`, — сейчас + они читаются при загрузке модели и выбрасываются; +2. в движке `pose_model_instance(index, origin, angles, bone_quats: &[[f32;4]])`: + локальные кватернионы костей в мировые через родителей + (`world[i] = world[parent] · (T(pos_i) · R(q_i) · T(−pos_i))`), затем скиннинг + теми же весами (функция скиннинга уже есть — сейчас её ведёт синус); +3. в клиенте: выбрать секвенцию (`@idle_all_01` через последовательность + activity), взять кадр по времени (`t · fps`, циклом), собрать кватернионы + костей из дорожек и позвать `pose_model_instance`; +4. затем выбор по состоянию (`ACT_MP_*`) и блендинг, и снять синус. + **A26 «анимации» — план записан** (docs/PARITY.md A26). Ключевое открытие: в `formats` скелет и веса **уже читаются** (`mdl.bones()`, `vvd.vertices()`, `vtx.body_parts()`), не хватает разбора секвенций/`.ani`, костей в