From f8db4cf73caba56bbdbe493b2fbcddada9e6209e Mon Sep 17 00:00:00 2001 From: Niko Marmeladkov Date: Sat, 17 Oct 2026 11:19:21 +0300 Subject: [PATCH] =?UTF-8?q?A26=20=D1=88=D0=B0=D0=B3=20=D0=B1:=20=D0=BA?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8=20=D0=B8=20=D0=B2=D0=B5=D1=81=D0=B0=20?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D1=88=D0=B8=D0=BD=20=D0=B2=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Model теперь несёт skins: Vec — привязку вершин к костям из VVD (до трёх костей с весами и их число), по одной записи на вершину. Индексы глобальные (после fixup VTX), считаться по ним будет матрица скиннинга вместе со скелетом Model::bones. Замер на живых моделях (лог «модель загружена»): companion_doll 1471 вершин / 1471 привязок, стол 136/136, диван 556/556 — привязка есть у всех вершин; у пропов при этом один корневой узел (bones=1). Модель игрока police.mdl — 57 костей. Все 23 сьюта зелёные; docs/PARITY.md A26 обновлён. --- crates/engine/src/model.rs | 40 ++++++++++++++++++++++++++++++++++++++ docs/PARITY.md | 11 ++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/crates/engine/src/model.rs b/crates/engine/src/model.rs index c4d7e17..faa2fef 100644 --- a/crates/engine/src/model.rs +++ b/crates/engine/src/model.rs @@ -26,6 +26,17 @@ pub enum ModelError { Geometry(String), } +/// Привязка вершины к костям (до трёх, как `mstudiovertex_t`). +/// +/// Индексы костей — **глобальные** (после fixup VTX), по ним считается +/// матрица скиннинга вместе со скелетом из `Model::bones` (A26). +#[derive(Debug, Clone, Copy, Default, PartialEq)] +pub struct VertexSkin { + pub bones: [u8; 3], + pub weights: [f32; 3], + pub num_bones: u8, +} + /// Вершина модели. #[derive(Debug, Clone, Copy, Default, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] #[repr(C)] @@ -58,6 +69,8 @@ pub struct Model { pub sequences: Vec, /// Кости скелета. pub bones: Vec, + /// Привязка вершин к костям, по одной на `vertices`. + pub skins: Vec, } /// Загружает модель по пути `models/...mdl`. @@ -98,12 +111,26 @@ pub fn load_model(vfs: &VirtualFs, name: &str, budget: &mut usize) -> Result 0 && s.weights.iter().any(|w| *w > 0.0)) + .count(); + tracing::info!( + name = %name, + vertices = model.skins.len(), + skinned, + "модель: привязка вершин к костям" + ); + } if !model.sequences.is_empty() { let sample: Vec<&str> = model .sequences @@ -205,6 +232,11 @@ pub fn load_model(vfs: &VirtualFs, name: &str, budget: &mut usize) -> Result Result` — привязку вершин +к костям из VVD (`bones[3]`, `weights[3]`, `num_bones`), по одной на вершину. +Замер на живых моделях: `companion_doll` 1471/1471, стол 136/136, диван 556/556 — +привязка есть у всех вершин; у пропов при этом один «корень» (bones=1). + +**Порядок работ:** (а) секвенции сделаны; дальше `.ani` (кадры) и слияние +включённых моделей; (б) привязка вершин сделана; (в) CPU-скиннинг в движке и +заливка на GPU; (г) проигрывание одной секвенции с циклом; (д) выбор по состоянию и блендинг. **Приёмка:** модель игрока/оружия двигается в кадре, ходьба переходит в бег и