Мне нужно рассчитать края видимого пространства из текущего состояния OpenGL - PullRequest
2 голосов
/ 23 июня 2009

В OpenGL в Delphi я пытаюсь вычислить, какая часть сцены видима, находя левый, правый, верхний и нижний экстенты области просмотра в ортогональной проекции. Это приведет к тому, что некоторые взаимодействия с мышью будут казаться 1-к-1. У меня нет большого доступа к коду, который устанавливает матрицу ортографической проекции, но я знаю, что он вызывает glOrtho (...) для установки матрицы проекции.

Мне нужно иметь возможность взять декартову плоскость (не визуализированную многоугольную плоскость), а затем вычислить левый, правый, верхний и нижний края области просмотра из любой информации, которую может предоставить opengl (меня не волнует передние и задние плоскости отсечения). У меня нет доступа к коду, который устанавливает объем просмотра (используя библиотеку glScene для Delphi), поэтому единственная информация, которую я могу использовать, чтобы найти эту информацию (насколько мне известно), это

glGet(GL_PROJECTION_MATRIX, @projectionMatrix);

Основываясь на документации в http://www.talisman.org/opengl-1.1/Reference/glOrtho.html, Я решил, что могу сделать некоторую математику, чтобы вычислить, каковы были левый, правый, верхний и нижний экстенты для ближней плоскости (чего в орто-режиме достаточно) (см. Мой код ниже). Однако, когда я на самом деле смотрю на значения, которые я извлекаю из glGet, я вижу матрицу со значениями, которые не соответствуют описанию в приведенной выше ссылке на документацию (см. Данные матрицы ниже). С такими разочаровывающими числами у меня есть сомнения относительно того, правильно ли я использую glGet, и могу ли я действительно полагаться на эти числа, чтобы дать мне левый / правый / верхний / нижний экстенты видимого тома. Полагаю, я тоже мог совершить ошибку в Delphi, но я не знаю, что это будет.

В этом конкретном случае плоскость ориентирована так, чтобы смотреть прямо в камеру, а камера имеет ортогональную проекцию. Я не полностью контролирую настройку матрицы проекции, поэтому я надеялся, что смогу вычислить левый край как

 left = 2 / (A * (tx - 1)/(tx+1) - 1)

Где A и tx извлекаются из матрицы проекции, как показано в http://www.talisman.org/opengl-1.1/Reference/glOrtho.html (я не показываю, как я вывел формулу выше, поэтому она может быть неверной - сейчас она дает ответ - INF). Код, который я использовал для получения значений матрицы проекции, выглядит следующим образом:

var
  projectionMatrix: TMatrix;
  Left, Right, Top, Bottom: Single;
  A, B, C, tx, ty, tz: Single;
begin
  A := projectionMatrix[0][0];
  B := projectionMatrix[1][1];
  C := projectionMatrix[2][2];
  tx := projectionMatrix[0][3];
  ty := projectionMatrix[1][3];
  tz := projectionMatrix[2][3];

  Left := 2 / (A * ((tx - 1) / (tx + 1) - 1));
  ShowMessage(FloatToStr(A));
  //etc...

Значения матрицы, которые я вижу, примерно такие:

[0] (0, 1.7436188636e-39, 6.4310754487e+37, 1.3822464104e-39)
[1] (3.8535707769e-43, 1.4012984643e-45, 0, 2.8086960027e+32)
[2] (-4.20345941e+17, 0, 1.7437029415e-39, 2.8086960027e+32)
[3] (1.7437645986e-39, 6.4311900443e+37, +NAN, 1.7437645986e-39)

[Изменить] glScene имеет следующие объявления:

TMatrix = THomogeneousFltMatrix; 
THomogeneousFltMatrix = TMatrix4f; 
TMatrix4f = array[0..3] of TVector4f; 
TVector4f = array[0..3] of single; 

[Изменить] Если я изменю матрицу проекции на массив из 16 значений, вот что произойдет:

var      
  projectionMatrix, modelviewMatrix: array[0..16] of single;
begin
  ...
  glGetFloatv(GL_PROJECTION_MATRIX, @projectionMatrix);
  ...

результирующий массив - это элементы с 0 по 16, которые по-прежнему выглядят неправильно.

projectionMatrix (5.9208279286e-39, -1536643072, 1,2429653406, -1.2128044229e-11, 2,8763115406, 0, 4,728515625, 1.7430022923e-39, 6.5138089186e + 37, 30 + -3.7955583126e, -2,4000201225, -3.7955583126e + 30, 2,4000201225, -1.2128044229e-11, 2,6263115406, -1,2128044229e-11, -2,6263115406) ​​

1 Ответ

1 голос
/ 21 июля 2009

Вы похоже используете glScene. Почему бы не использовать TGLSceneBuffer.ScreenVectorIntersectWithPlane () ?

Вы получаете 4 мировых вектора из 4 экранных координат и имеете прямоугольник, площадь которого вы можете легко вычислить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...