NODEDC_BIM_VIEWER/report/251220RotateSwitchOrtoProbl...

15 KiB
Raw Blame History

25.12 Rotate / Switch Ortho Problems Report

Отчет составлен по содержимому чата и локальным изменениям кода в проекте. Цель: зафиксировать весь путь расследования проблем с вращением (ось/pivot) и прыжками камеры при переключении ортографической и перспективной проекции.


1. Подробное описание проблемы, наблюдений, логов и взаимосвязей

1.1 Контекст и среда

  • Сцены очень крупные (километры), много LAS облаков, иногда GLB модели.
  • Рабочий сценарий: уйти далеко, вернуться к объекту, переключать ortho/persp, вращать камеру.
  • Пользователь каждый тест делает с очисткой кэша браузера. Сервер не перезапускается.
  • На «свежем» состоянии проблемы часто не проявляются сразу, но появляются спустя время/навигацию.

1.2 Симптомы (что видит пользователь)

  1. Смещение оси вращения (pivot drift).

    • Вращение идет вокруг точки, которая не совпадает с курсором или целевым объектом.
    • Часто ощущается, что точка вращения «за камерой» или сильно в стороне.
    • В ortho проявляется чаще, но бывает и в perspective.
    • Иногда исчезает после переключения в perspective или после фокуса (двойной клик).
  2. Прыжки камеры при переключении ortho <-> perspective.

    • При переключении камера уезжает назад или в сторону на 50200+ метров.
    • После прыжка новая дистанция становится «новой нормой» для следующих переключений.
    • Особенно часто при переключении из ortho в perspective.
  3. Клиппинг (статические отсечки) в ortho.

    • Периодически появляется «плоскость отсечения», которая не зависит от зума.
    • Отсечка исчезает при смене ракурса/переключении проекции, но может вернуться.
  4. Нестабильный зум (скачки шага).

    • После сильного отлета зум начинает «пропускать шаги».
    • Приближение становится грубым: следующая позиция уже «за объектом».

1.3 Наблюдения (устойчивые повторения)

  • Проблемы чаще всего возникают после сильного отлета и перемещения на большое расстояние.
  • При аккуратной локальной работе (вокруг одного объекта) поведение обычно стабильнее.
  • Переключение в perspective и небольшой «полет» иногда стабилизируют pivot.
  • После double-click фокусировки проблемы временно исчезают.

1.4 Логи, которые использовались

В процессе добавлены и использовались флаги:

  • window.__dcProjDebug = true
  • window.__dcPivotDebug = true
  • window.__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 и fov
  • ortho -> 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. Что требуется для следующей итерации

  1. Свежий тест после последних правок (без длительных старых сессий).
  2. Логи:
    • window.__dcProjDebug = true
    • window.__dcPivotDebug = true
  3. Сценарий:
    • сильно отлететь,
    • вернуться к объекту,
    • вращать в ortho,
    • переключить ortho/persp.

Если вновь поймается «кривая ось» или «скачок дистанции», лог должен сопровождать момент, чтобы анализировать разницу между eyeLookDist, orthoScale, pivotDist, pickDist, rayDist.