15 KiB
25.12 Rotate / Switch Ortho Problems Report
Отчет составлен по содержимому чата и локальным изменениям кода в проекте. Цель: зафиксировать весь путь расследования проблем с вращением (ось/pivot) и прыжками камеры при переключении ортографической и перспективной проекции.
1. Подробное описание проблемы, наблюдений, логов и взаимосвязей
1.1 Контекст и среда
- Сцены очень крупные (километры), много LAS облаков, иногда GLB модели.
- Рабочий сценарий: уйти далеко, вернуться к объекту, переключать ortho/persp, вращать камеру.
- Пользователь каждый тест делает с очисткой кэша браузера. Сервер не перезапускается.
- На «свежем» состоянии проблемы часто не проявляются сразу, но появляются спустя время/навигацию.
1.2 Симптомы (что видит пользователь)
-
Смещение оси вращения (pivot drift).
- Вращение идет вокруг точки, которая не совпадает с курсором или целевым объектом.
- Часто ощущается, что точка вращения «за камерой» или сильно в стороне.
- В ortho проявляется чаще, но бывает и в perspective.
- Иногда исчезает после переключения в perspective или после фокуса (двойной клик).
-
Прыжки камеры при переключении ortho <-> perspective.
- При переключении камера уезжает назад или в сторону на 50–200+ метров.
- После прыжка новая дистанция становится «новой нормой» для следующих переключений.
- Особенно часто при переключении из ortho в perspective.
-
Клиппинг (статические отсечки) в ortho.
- Периодически появляется «плоскость отсечения», которая не зависит от зума.
- Отсечка исчезает при смене ракурса/переключении проекции, но может вернуться.
-
Нестабильный зум (скачки шага).
- После сильного отлета зум начинает «пропускать шаги».
- Приближение становится грубым: следующая позиция уже «за объектом».
1.3 Наблюдения (устойчивые повторения)
- Проблемы чаще всего возникают после сильного отлета и перемещения на большое расстояние.
- При аккуратной локальной работе (вокруг одного объекта) поведение обычно стабильнее.
- Переключение в perspective и небольшой «полет» иногда стабилизируют pivot.
- После double-click фокусировки проблемы временно исчезают.
1.4 Логи, которые использовались
В процессе добавлены и использовались флаги:
window.__dcProjDebug = truewindow.__dcPivotDebug = truewindow.__dcAllowOffsetEye = true(опционально, для диагностики)
Типовые лог-сообщения:
- Проекции:
[dc-proj] persp->ortho,[dc-proj] ortho->persp,proj-switch(before/after) - Пивот:
[dc-pivot] start,[dc-pivot] start-clamp,[dc-pivot] ortho-pivot,[dc-pivot] persp-pick,[dc-pivot] ortho-eye-normalize
Что замечено по логам:
- В ortho часто фиксируется несоответствие между eyeLookDist и orthoScale (orthoScale намного больше).
- В некоторых логах
pickDist/rayDistсильно отличаются отeyeLookDist. - Были ситуации, когда
pivotPos == look, но ощущение вращения все равно «кривое», значит проблема не только в выборе pivot, а в состоянии камеры (eye/scale).
1.5 Взаимосвязи и гипотезы
Основные гипотезы, подтвержденные частично логами и наблюдениями:
- Проблемы накопительные: чем больше дальних перемещений и масштаба, тем выше шанс сломаться.
- Пивот в ortho при выборе через pick/ray нестабилен в больших сценах.
- Сильные отлеты приводят к разрыву между
orthoScaleиeyeLookDist, что искажает ось вращения. - Переключение проекций использует параметры, которые не всегда согласованы с текущим состоянием камеры.
2. Подробное описание всех попыток исправления
Ниже приведены все попытки с указанием: где делали, что меняли, зачем, ожидаемый результат и фактический результат.
Попытка 1. Настройки клиппинга в UI (viewport)
Где: UI блок Viewport (инспектор).
Что сделали: добавили поля для клиппинга (perspective/ortho), позже min/max.
Зачем: пользователь видел слишком ранние отсечки и хотел управлять дистанцией.
Ожидание: контроль near/far клиппинга решит отсечки и приблизит камеру.
Факт: в perspective стало предсказуемее, в ortho появились «статические» отсечки,
которые не всегда зависели от камеры. Проблема клиппинга осталась.
Попытка 2. Принудительный near/far (0.01 / 1e9)
Где: параметры камеры.
Зачем: исключить влияние near/far.
Ожидание: клиппинг исчезнет.
Факт: не помогло, отсечки остались.
Попытка 3. Включение логов и сбор метрик
Где: консольный дебаг, далее встроенные логи.
Что: добавлены [dc-proj] и [dc-pivot] логи.
Зачем: видеть dist, orthoScale, pickDist, rayDist.
Ожидание: найти связь между параметрами и рывками/пивотом.
Факт: выявлены несоответствия scale/dist и роль сильных отлетов, но без прямого фикса.
Попытка 4. Форк core-камеры в локальный файл
Где: frontend/lib/dc-camera-context.es.js
Что: из minified xeokit сделали локальную «контекстную» версию для правок.
Зачем: исправлять первоисточник, а не обертки.
Ожидание: полный контроль над Camera/Ortho/Perspective.
Факт: сначала ошибки сборки (duplicate identifier, lookAtMat4v undefined),
после коррекции файл заработал и стал основным местом правок.
Попытка 5. Удаление обертки проекций
Где: frontend/dcViewer.js
Что: удален projectionSync (обертка синхронизации проекций).
Зачем: убрать внешние корректировки, которые могут конфликтовать.
Ожидание: меньше неожиданных прыжков.
Факт: источник конфликтов убран, но прыжки и pivot drift остались.
Попытка 6. Пересчет ortho/persp в Camera.projection
Где: frontend/lib/dc-camera-context.es.js (Camera.projection setter)
Что:\n
persp -> ortho: масштаб берется изdistиfovortho -> persp: дистанция берется изorthoScaleиfov- убраны расчеты на основе
rayDist
Зачем: сделать переключение более детерминированным.
Ожидание: стабильная дистанция при переключениях.
Факт: иногда лучше, но рывки оставались, особенно после большого зума.
Попытка 7. Отключение offsetEyeFromLook
Где: frontend/lib/dc-camera-context.es.js
Что: offsetEyeFromLook теперь false по умолчанию, включается через флаг __dcAllowOffsetEye.
Зачем: offset подозревался как источник смещения оси вращения.
Ожидание: pivot станет стабильнее.
Факт: стало немного стабильнее, но проблема не исчезла.
Попытка 8. Clamp pivot по dot/ratio
Где: PivotController.startPivot
Что: если pivotDist/eyeLookDist слишком большой или направление не совпадает,
pivot принудительно сбрасывается на look.
Зачем: исключить pivot за камерой.
Ожидание: уменьшение случаев «кривой» оси.
Факт: часть экстремальных случаев ушла, но проблема оставалась.
Попытка 9. Эвристики ortho pick pivot
Где: обработчик mouse/touch для pivot в dc-camera-context.es.js
Что: pick pivot принимается только при нормальных dot/ratio и пределах rayDist.
Зачем: в ortho pick часто уводил pivot в неверное место.
Ожидание: меньше смещений оси.
Факт: поведение было нестабильным, в некоторых случаях хуже.
Попытка 10. Ortho eye normalize
Где: PivotController.startPivot
Что: если orthoScale >> eyeLookDist, camera.eye отодвигается вдоль вида
на max(eyeLookDist, orthoScale).
Зачем: уменьшить расхождение между масштабом и дистанцией камеры.
Ожидание: стабилизация оси вращения в ortho после сильного зума.
Факт: результаты неоднозначные, иногда хуже.
Попытка 11. Полное отключение pick pivot в ortho (последняя правка)
Где: mouse/touch обработчики pivot в dc-camera-context.es.js
Что: при ortho pivot всегда camera.look, pick/ray не используются.
Зачем: убрать нестабильность pick pivot.
Ожидание: стабильная ось вращения в ortho.
Факт: требуется повторный тест после этой правки.
Попытка 12. Жесткая фиксация look и движение eye вдоль направления
Где: Camera.projection setter
Что: при переключении проекций look фиксируется,
eye пересчитывается только по направлению вида (без боковых смещений).
Зачем: убрать скачки в сторону/назад при ortho <-> persp.
Ожидание: переключение без прыжков по позиции.
Факт: требуется повторный тест после этой правки.
Попытка 13. Расширенные логи
Где: dc-camera-context.es.js
Что: добавлены детальные логи [dc-proj] и [dc-pivot].
Зачем: фиксировать реальные параметры во время рывков.
Ожидание: получить воспроизводимые метрики для анализа.
Факт: помогло подтвердить связь с сильным зумом, но без полного решения.
3. Итоговое состояние на момент отчета
Актуальные изменения в форке:
frontend/lib/dc-camera-context.es.js:- упрощен пересчет ortho/persp;
offsetEyeFromLookпо умолчанию false;- pivot clamp при подозрительном pivot;
ortho-eye-normalize(эксперимент);- в ortho pivot всегда
look, pick/ray игнорируется (последняя правка); - логи
__dcProjDebugи__dcPivotDebug.
frontend/dcViewer.js:- удалена обертка
projectionSync.
- удалена обертка
Состояние проблемы:
- после ряда правок поведение часто становится лучше на короткой дистанции, но при сильных отлетах проблема возвращается.
- основной подозреваемый: накопление состояния в камере
- разрыв между
orthoScaleиeyeLookDist - нежелательные pivot‑решения в ortho.
- разрыв между
4. Что требуется для следующей итерации
- Свежий тест после последних правок (без длительных старых сессий).
- Логи:
window.__dcProjDebug = truewindow.__dcPivotDebug = true
- Сценарий:
- сильно отлететь,
- вернуться к объекту,
- вращать в ortho,
- переключить ortho/persp.
Если вновь поймается «кривая ось» или «скачок дистанции»,
лог должен сопровождать момент, чтобы анализировать разницу
между eyeLookDist, orthoScale, pivotDist, pickDist, rayDist.