Как настроить GLCamera для отображения всего GLScene

У меня есть объект GLScene разного (но известного) размера. Он полностью окружен TGLDummyCube.

Я хочу расположить GLCamera (с CameraStyle: glPerspective) так, чтобы объект был полностью виден на экране. У меня это работает в основном - объект виден, но расстояние иногда слишком большое, или объект больше экрана и обрезан.

Как я могу это сделать? Я предполагаю, что это можно сделать с помощью умного сочетания расстояния камеры и фокусного расстояния, но пока мне это не удалось.

Это кажется другим в GLScene по сравнению с OpenGL. Я использую GLScene и Delphi 2007.


person Andreas    schedule 25.07.2009    source источник
comment
Если вы не получаете удовольствия, спрашивая таким образом, вы можете рассмотреть возможность удаления тега Delphi и просто спросить о GLScene, заявив, что любая логика будет оценена, включая псевдокод, и что вы планируете адаптироваться к Delphi. Язык, который вы используете, на самом деле не важен, вам нужна логика/математика.   -  person Argalatyr    schedule 25.07.2009
comment
Argalatyr, спасибо, но я не уверен насчет объекта GLCamera — это просто инкапсуляция стандартной OpenGL-камеры или он добавляет дополнительные возможности?   -  person Andreas    schedule 27.07.2009
comment
По своей сути это классическая камера OpenGL, есть дополнительные функции, но они не меняют основную математику.   -  person Eric Grange    schedule 03.02.2012


Ответы (2)


Хотя изменение расстояния до камеры и фокусного расстояния изменит визуальный размер объекта, у него есть недостаток, заключающийся в изменении перспективы, что приводит к несколько искаженному изображению. Вместо этого я предлагаю использовать свойство камеры SceneScale.

Увы, у меня нет действительных шагов для расчета правильного значения для этого. В моем случае я должен масштабировать до куба с переменным размером, в то время как размер окна просмотра является постоянным. Поэтому я поместил два фиктивных куба в положение целевого куба, размер каждого из которых соответствовал ширине или высоте наблюдателя с соответствующими значениями для SceneScale, расстояния до камеры и FocalLength. Во время выполнения я рассчитываю новое SceneScale по отношению размера целевого куба к размерам фиктивного куба. Это работает очень хорошо в моем случае.

Изменить: вот код, который я делаю для вычислений.

  • ZoomRefX и ZoomRefY это DummyCubes
  • TargetDimX и TargetDimY дают размер текущего объекта
  • DesignWidth и DesignHeight - это размер MyGLView во время разработки
  • DesignSceneScale — это SceneScale камеры во время разработки.

Код расчета:

ScaleX := (ZoomRefX.CubeSize*MyGLView.Width)/(DesignWidth*TargetDimX);
ScaleY := (ZoomRefY.CubeSize*MyGLView.Height)/(DesignHeight*TargetDimY);
NewSceneScale := Min(ScaleX, ScaleY)*DesignSceneScale;

DummyCubes ZoomRefX и ZoomRefY имеют такие размеры, что у них есть небольшой запас по левому и правому или верхнему и нижнему краям окна просмотра. Оба расположены так, чтобы передние грани совпадали. Кроме того, целевой объект позиционируется таким образом, чтобы его лицевая сторона совпадала с лицевой стороной этих DummyCubes.

Приведенные выше формулы позволяют изменять размер окна во время разработки, но на самом деле я не проверял эту функцию.

person Uwe Raabe    schedule 25.07.2009
comment
Спасибо за подсказку — я тоже играл со SceneScale, используя его в своем обработчике событий OnMouseWheel. Правильно ли я понимаю, что вы устанавливаете эти dummycubes во время разработки и соответственно подгоняете куб во время выполнения? Звучит как хитрый трюк. Меняйте объект, а не камеру. - person Andreas; 27.07.2009
comment
Я установил dummycubes во время разработки на размер, соответствующий размеру окна средства просмотра. Два куба, потому что экран не квадратный, а кубы-пустышки. Теперь, когда мой реальный объект, скажем, удвоил размер dummycube, я знаю, что мне нужно вдвое уменьшить SceneScale, чтобы сделать его видимый размер таким же, как у dummycube во время разработки. Выполняя эти вычисления отдельно для ширины и высоты, я могу рассчитать масштаб сцены, благодаря которому целевой объект помещается в окно. Это работает только потому, что размер окна фиксирован. И я не меняю объект — я меняю только SceneScale камеры. - person Uwe Raabe; 27.07.2009

@Andreas, если вы играли со SceneScale (как вы упомянули в комментариях), это означает, что вы ищете правильный способ разместить объект в поле зрения камеры, либо изменив расстояние камеры / фокусное расстояние, либо изменив размер объекта. Если это так, самый простой способ изменить размер отдельного объекта, чтобы он поместился на экране, — использовать его свойство BoundingSphereRadius следующим образом:

ResizeMultiplier := 2; //play with it, it depends on your camera params
GLFreeForm1.Scale.Scale(ResizeMultiplier / GLFreeForm1.BoundingSphereRadius);

Вы можете добавить GLDummyCube в качестве корневого объекта для всех других объектов сцены, а затем изменить размер GLDummyCube методом, упомянутым выше.

person Kainax    schedule 09.06.2015