Движок: геометрия модели вынесена в append_model_geometry (меш, материалы, вершины с трансформацией, батчи со смещением индексов на вершины экземпляра). Поверх неё World::spawn_prop — то же, что делает Q-меню GMod: геометрия, сущность класса prop_physics (её видят Lua и физика), тело в мире физики по габаритам меша, экземпляр пропа для move_prop. Клиент: клавиша G — спавн пропа по взгляду (модель из SOURCE_RS_SPAWN_MODEL, по умолчанию models/props_junk/watermelon01.mdl), и аргумент --spawn <модель> для отладки и скриптов. Проп сразу попадает в габариты коллизии игрока — их клиент пересобирает каждый кадр. Проверено кадром: арбуз заспавнен в 96 юнитах по взгляду и отрисован (--player-pos="-2438 -966 48", камера у "-2500 -1050 60|5 0"). Грабли записаны в дневник: буферы рендера собраны на сборке мира, поэтому после спавна рендерер пересобирается целиком — позже заменим до-аллокацией вершин.
9.6 KiB
Дневник агента: где я и что дальше
Живой документ. Обновляю по ходу работы, чтобы после автоматического уплотнения контекста ничего не терялось. Коротко: состояние, замеры, следующий шаг, грабли.
Обновлён: 2026-10-16, вечер.
1. Что просит пользователь (приоритеты)
Ускоренный путь до Sandbox-UX (его слова): «быстрее дойти до того, как смогу спавнить через Q-меню, иметь норм модель игрока, таскать физганом, Weapon всё сделать». Поэтому очередь переставлена (docs/PARITY.md A25):
- A23 оружие (SWEP из Lua + вьюмодель + аттачменты) — сюда же A20 (модель игрока: один и тот же рендер моделей).
- A21 физика взаимодействия: физган (луч → проп → таскание, вращение, заморозка), без полной гибернации.
- A24 спавн: сначала консольные команды на данных из Lua (
gm_spawn,gm_give, режимыgmod_tool), потом окно Q. - A22 Sandbox целиком: undo/cleanup/duplicator.
- Визуальная точность (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
(без этого был мусор в кадре).
Спавн пропа из игры сделан (ядро A24). World::spawn_prop (геометрия из
append_model_geometry, сущность prop_physics, тело в физике, экземпляр
пропа) + в клиенте клавиша G (спавн по взгляду) и аргумент
--spawn <модель> (отладка и скрипты). Проверено кадром: арбуз заспавнен и
отрисован (--spawn models/props_junk/watermelon01.mdl, камера у
-2500 -1050 60|5 0).
Грабли: буферы рендера созданы на сборке мира — после спавна рендерер пересобирается целиком (медленно, но работает); позже нужна до-аллокация вершин под спавн.
Следующее: (а) до-аллокация вершин под спавн вместо пересборки рендерера; (б) реестр SWEP из Lua и вьюмодель; (в) физган (луч → проп → таскание); (г) скрытие своей модели, когда камера внутри неё; (д) скелет+анимации.
3. Что уже сделано и лежит в main
Последние коммиты (свежие сверху):
4ad0405очередь: A23 оружие, A24 Q-меню, A25 ускоренный порядок;7a8a750очередь: A20 модель игрока, A21 полная физика, A22 Sandbox через GLua;257ac07,d35efefA13 туман сделан целиком (чтение + шейдер);72bad60A19: подшаг не гасит скорость о склон (35°: 65 → 147);5bdbdbf,e638607A19: замер по углам + найден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_normal0,7 (45,6°),DIST_EPSILON1/32,sv_stepsize18, воздушный потолок желаемой скорости 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+ картовые тесты.