gmod-rs/docs/DIARY.md
Niko Marmeladkov 8a2eb4ef60
Some checks are pending
CI / checks (push) Waiting to run
A20/A23 первый срез: модель игрока в мире
Первый срез модели игрока, чтобы не блокировать Sandbox: рендер тот же, что у
пропов (статический меш PropMesh), скелет и анимации следующим срезом.

Движок: ModelInstance (экземпляр модели без сущности) плюс
World::spawn_model_instance (модель с диска, материалы с дедупликацией, вершины
с трансформацией, батчи) и World::move_model_instance; перезапись геометрии
вынесена в общий rewrite_instance, им пользуются и пропы.

Клиент: модель создаётся после разбора --player-pos и едет за игроком (позиция —
ступни, курс — взгляд, развёрнутый на 180°, потому что у моделей Source ось Y
смотрит влево). Включается переменной SOURCE_RS_PLAYER_MODEL: пустое значение —
models/player/police.mdl, иначе путь к модели.

Проверено кадром: модель стоит на площадке в -2438 -966 48, текстуры на месте,
вершин в мире стало 46359 против 43212 без модели. Грабли записаны в дневник:
индексы модели локальные, при вставке в общий буфер к ним прибавляется
first_vertex (без этого кадр превращался в мусор).

Заведён docs/DIARY.md — живой дневник состояния, замеров, инструментов и
грабель, чтобы уплотнение контекста ничего не теряло.
2026-10-16 23:44:39 +03:00

8.7 KiB
Raw Blame History

Дневник агента: где я и что дальше

Живой документ. Обновляю по ходу работы, чтобы после автоматического уплотнения контекста ничего не терялось. Коротко: состояние, замеры, следующий шаг, грабли.

Обновлён: 2026-10-16, вечер.


1. Что просит пользователь (приоритеты)

Ускоренный путь до Sandbox-UX (его слова): «быстрее дойти до того, как смогу спавнить через Q-меню, иметь норм модель игрока, таскать физганом, Weapon всё сделать». Поэтому очередь переставлена (docs/PARITY.md A25):

  1. A23 оружие (SWEP из Lua + вьюмодель + аттачменты) — сюда же A20 (модель игрока: один и тот же рендер моделей).
  2. A21 физика взаимодействия: физган (луч → проп → таскание, вращение, заморозка), без полной гибернации.
  3. A24 спавн: сначала консольные команды на данных из Lua (gm_spawn, gm_give, режимы gmod_tool), потом окно Q.
  4. A22 Sandbox целиком: undo/cleanup/duplicator.
  5. Визуальная точность (A10 свет на пиксель, A11–A12 вода, A16 трава/декали, A18 скайбокс) — параллельно, Sandbox не блокирует.

2. Где я сейчас (в работе)

A20/A23, первый срез сделан: модель игрока в мире. Рендер тот же, что у пропов (статический меш PropMesh), скелет и анимации — следующий срез.

Как включается и как проверять:

SOURCE_RS_PLAYER_MODEL= DISPLAY=:99 SDL_VIDEODRIVER=x11 cargo run -q -p client -- \
  map --assets ~/gmod_server/server gm_construct --hidden --frames 4 --noclip \
  --player-pos="-2438 -966 48" --flythrough /tmp/opencode/pl4 --flythrough-frames 4 \
  --route="-2438 -880 75|6 270; -2438 -1180 75|6 90"

Пустое значение — модель по умолчанию (models/player/police.mdl), иначе — путь к модели. Курс разворачивается на 180° (у моделей Source ось Y влево).

Движок: World::spawn_model_instance и World::move_model_instance, ModelInstance (экземпляр без сущности). Грабли: индексы модели локальные — при вставке в общий буфер к ним обязательно прибавляется first_vertex (без этого был мусор в кадре).

Следующее: (а) вьюмодель в первом лице и скрытие своей модели, когда камера внутри неё; (б) реестр SWEP из Lua; (в) физган; (г) скелет+анимации моделей.

3. Что уже сделано и лежит в main

Последние коммиты (свежие сверху):

  • 4ad0405 очередь: A23 оружие, A24 Q-меню, A25 ускоренный порядок;
  • 7a8a750 очередь: A20 модель игрока, A21 полная физика, A22 Sandbox через GLua;
  • 257ac07, d35efef A13 туман сделан целиком (чтение + шейдер);
  • 72bad60 A19: подшаг не гасит скорость о склон (35°: 65 → 147);
  • 5bdbdbf, e638607 A19: замер по углам + найден flRedirectCoeff в движке;
  • 3bfd078, d88988f рельеф: треугольники отсекают шаг, нормаль наружу (стены по рёбрам полигонов ушли);
  • b74824b склон: догон земли трассировкой (рампы 242–250 вместо 197,8);
  • 23c5034 присед: 250/150/520/216,7 по спеке, камера 46 → 28 (была выше хитбокса);
  • aa11713, d220b5a рампы и стыки: отсечение по последней входной грани, касание ребром не преграда;
  • 86a6cb6, 5380184 инструменты: слой коллизий, дамп кирпича, обход карты.

Все 23 сьюта и 28 картовых тестов зелёные.

4. Замеры, которые нельзя потерять

  • A19 (скорость на склоне): замер probe_slope_angles (синтетический клин). Было: 5° 239, 10° 232, 15° 196, 20° 152, 25° 116, 30° 88, 35° 65, 40° 49, 44° 39. Стало: 239 / 233 / 226 / 214 / 195 / 175 / 147 / 132 / 107. Цель — 250 до 44°. Остаток теряется на прямом (скользящем) пути: иногда он выигрывает выбор у подшага. Инструмент: SOURCE_RS_TRACE_STEP=1 печатает, какой путь победил (step_move).
  • Механизм движка для скорости на склоне: gamemovement.cpp, ClipVelocity (строка ~3144) — блок flRedirectCoeff: out *= (len + |v·n|·coeff)/len. Наивный перенос копит бонус за кадр (15° → 442 юнита/с) — откачен.
  • Туман карты gm_construct: цвет (0,557 0,643 0,698), start 1024, end 250000, max_density 1,0, farz −1 (дальний, на ближних дистанциях нейтрален).
  • Габариты/линейки Source: тело 72/36 (стоя/присед), глаза 64/28 (VEC_VIEW/VEC_DUCK_VIEW), sv_walkable_normal 0,7 (45,6°), DIST_EPSILON 1/32, sv_stepsize 18, воздушный потолок желаемой скорости 30.
  • Коллизия gm_construct: 2118 кирпичей; 140 за габаритами карты (3D-скайбокс, часть с несогласованными плоскостями — см. E19.2); 11776 треугольника рельефа, у всех намотка «гео внутрь» (нормаль разворачиваем в clip_triangle).
  • Присед: обрезка HandleDuckingSpeedCrop = 0.33333333 только в приседе и на земле, желаемая скорость 450 (бег 650), максимум 250 / 520.

5. Инструменты диагностики (не переизобретать)

  • SOURCE_RS_DEBUG_COLLISION=<радиус> — слой коллизий: красные рёбра кирпичей, жёлтые габариты, голубой рельеф, зелёное тело.
  • probe_brush_dump (SOURCE_RS_TEST_BSP_AT="x,y,z,радиус") — полный дамп кирпича: содержимое с расшифровкой, владелец-сущность, каждая грань с текстурой, габарит, попадание в коллизию.
  • probe_ramp_movement — движение из точки: 8 направлений, рывки, залипания, кто мешает (кирпич + текстуры).
  • probe_slanted_surface — лучи по наклонным кирпичам против настоящей формы.
  • probe_slope_angles — таблица скорости по углам (приёмка A19).
  • probe_phantom_walls_scan, probe_collision_contents — обход карты и состав коллизии.
  • real_map_* — 28 картовых тестов, требуют SOURCE_RS_TEST_BSP.
  • Запуск клиента: DISPLAY=:99 SDL_VIDEODRIVER=x11 cargo run -q -p client -- map --assets ~/gmod_server/server gm_construct ..., для кадров нужен --flythrough <dir>.

6. Грабли (уже наступал)

  • Vec3 без Index: писать покомпонентно.
  • %[fx:mean*255] в ImageMagick без имени канала врёт — считать mean.r/g/b.
  • Тесты с картой имеют свой VirtualFs::new() (189 материалов) — индексы материалов не как в рантайме (54).
  • Правки кода делать edit, не sed/python, кроме больших перестановок блоков — и после каждой проверять cargo clippy и тесты.
  • Перед коммитом всегда: cargo fmt --all && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace + картовые тесты.