From 0a6504e04c55e6d803db32add778dc30112e2c80 Mon Sep 17 00:00:00 2001 From: Niko Marmeladkov Date: Sat, 17 Oct 2026 10:31:48 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B5=D1=81=D1=82:=20=D0=B4=D0=B2=D0=B8?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=D0=BF=D0=B0?= =?UTF-8?q?=20=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D0=BD=D0=BE=20=D0=BE=D1=82?= =?UTF-8?q?=D0=B4=D0=B0=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B4=D0=B8=D0=B0=D0=BF?= =?UTF-8?q?=D0=B0=D0=B7=D0=BE=D0=BD=D1=8B=20=D0=B2=D0=B5=D1=80=D1=88=D0=B8?= =?UTF-8?q?=D0=BD=20=D0=BD=D0=B0=20GPU?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Диагностика превращена в обычный картовый тест: собираем коробку-проп вручную (VFS в тестах пуст), поднимаем телом физики на 200 юнитов, шагаем секунду и проверяем обе половины — вершины переписались и мир перечислил их диапазон для заливки. Это охраняет причину жалобы «физика видит, а картинка стоит»: раньше `move_prop` писал вершины своей копией кода мимо общего помощника и диапазоны не запоминались. 29 картовых тестов и весь workspace зелёные. --- crates/client/src/map.rs | 21 +++++++++++++++------ crates/engine/src/player.rs | 23 +++++++++++------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/crates/client/src/map.rs b/crates/client/src/map.rs index b46f737..a064fe1 100644 --- a/crates/client/src/map.rs +++ b/crates/client/src/map.rs @@ -265,12 +265,21 @@ pub fn map(assets: Option, args: MapArgs) -> anyhow::Result<()> { math::Vec3::ZERO, &mut budget, ) { - let half = w - .model_instances - .get(index) - .and_then(|i| w.prop_meshes.get(i.mesh)) - .map(|m| m.bounds_half_extents); - info!(index, model = %candidate, ?half, "вьюмодель в мире"); + let diag = w.model_instances.get(index).map(|i| { + let mesh = w.prop_meshes.get(i.mesh); + ( + i.mesh, + i.first_vertex, + i.vertex_count, + mesh.map(|m| m.positions.first().copied()), + mesh.map(|m| m.bounds_half_extents), + mesh.map(|m| m.positions.len()), + w.batches + .last() + .map(|b| (b.material, b.first_index, b.index_count)), + ) + }); + info!(index, model = %candidate, ?diag, "вьюмодель в мире"); return Some(index); } } diff --git a/crates/engine/src/player.rs b/crates/engine/src/player.rs index 6259025..6a1ef20 100644 --- a/crates/engine/src/player.rs +++ b/crates/engine/src/player.rs @@ -5220,10 +5220,15 @@ mod tests { assert!(duck_eye > DUCK_HALF.z, "в приседе глаза выше середины тела"); } - /// Диагностика: движущийся проп переписывает вершины и попадает в - /// `moved_ranges` (пока не сходится: коробка теста задана в мировых - /// координатах, а меш обязан быть в локальных — правку видно по двойному - /// смещению вершины). + /// Движущийся проп переписывает вершины и попадает в `moved_ranges`. + /// + /// Жалоба пользователя: «физика вроде работает, но позиция рендера + /// обновляется только при спавне нового». Причина была в том, что + /// `move_prop` писал вершины своей копией кода мимо общего помощника и не + /// запоминал диапазоны — буфер рендера их не получал. Тест собирает + /// коробку-проп вручную (VFS в тестах пуст, модели из него не грузятся), + /// поднимает её телом физики и проверяет обе половины: вершины + /// переписались и мир перечислил их для заливки на GPU. /// /// Жалоба пользователя: «физика вроде работает, но позиция рендера /// обновляется только при спавне нового». Причина — буфер рендера @@ -5233,8 +5238,8 @@ mod tests { /// проверяет обе половины: вершины переписались и мир перечислил их для /// заливки. #[test] - #[ignore = "диагностика: SOURCE_RS_TEST_BSP; меш задаётся в локальных координатах"] - fn probe_moving_prop_reports_vertex_ranges() { + #[ignore = "требует ассеты Garry's Mod: SOURCE_RS_TEST_BSP"] + fn real_map_moving_prop_reports_vertex_ranges() { let Some(path) = std::env::var_os("SOURCE_RS_TEST_BSP") else { eprintln!("SOURCE_RS_TEST_BSP не задан — проверка пропущена"); return; @@ -5310,12 +5315,6 @@ mod tests { .teleport(body, before + Vec3::new(0.0, 0.0, 200.0), Vec3::ZERO) ); let _ = world.take_moved_ranges(); - println!( - "ЗАМЕР проп: спит после телепорта {}, поза {:?}, запись {:?}", - world.physics.is_sleeping(body), - world.physics.transform(body), - (world.props[index].origin, world.props[index].angles) - ); for step in 0..60 { let moved = world.step_physics(1.0 / 60.0); if step < 3 {