OpenGL: gluUnProject возвращает неправильные координаты

Я настроил свою сцену (приложение для Android, OpenGL ES) следующим образом:

GLU.gluPerspective(gl, 60, viewRatio, 0.1f, 1000.0f);
// ...
GLU.gluLookAt(gl, cameraX, cameraY, cameraZ, cameraX, cameraY, cameraZ - 1f, 0f, 1f, 0f);
// Scene scaled down because object positions are in [-10000..10000] for x & y
gl.glScalef(0.001f, 0.001f, 1.0f);

Сцена визуализирована хорошо, она содержит квадраты с z = -10 и один гигантский фон с квадратами с z = -30. Сейчас я пытаюсь реализовать выбор лучей, как это (взято из этой ветки:

public float[] unproject(float rx, float ry, float rz) {
    float[] xyzw = {0, 0, 0, 0};
    int[] viewport = {0, 0, mDisplayWidth, mDisplayHeight};
    android.opengl.GLU.gluUnProject(rx, ry, rz, mMatrixGrabber.mModelView, 0, mMatrixGrabber.mProjection, 0, viewport, 0, xyzw, 0);
    xyzw[0] /= xyzw[3];
    xyzw[1] /= xyzw[3];
    xyzw[2] /= xyzw[3];
    xyzw[3] = 1;
    return xyzw;
}

Затем прикосновения к экрану проверяются следующим образом:

unproject(tapX, mDisplayHeight - tapY, BACKGROUND_Z);

Ожидаемое поведение: возвращенные координаты X, Y напоминают точку касания на глубине = -30 (BACKGROUND_Z)

Что он на самом деле делает: возвращает правильные координаты X, Y при нажатии в центре экрана; Но расстояние между центром экрана и точкой касания интерпретируется некорректно - кажется, что оно в какой-то мере уменьшено. Например. нажатие на центр экрана дает [0,0], нажатие на левый край экрана должно дать ~ [-3600,0], но вместо этого дает [-1.13,0]. При панорамировании вида таким образом, чтобы точка, которой ранее касались, находилась в центре экрана, получаем ~ [-3600,0], как и должно быть.

Может это из-за масштабирования сцены на 0,001? Я тестировал различные конфигурации (перемещение масштабирования перед gluLookAt или полное его удаление), но проблема не устранена :(


Пример вывода данных для касания у левого края экрана:

Точка касания передана в unproject ():

x=3, y = 554 (0,0 at bottom left; w=720, h=1280)

Матрица проекции:

[2.8482616, 0.0,       0.0,         0.0, 
 0.0,       1.7320509, 0.0,         0.0, 
 0.0,       0.0,      -1.0001999,  -1.0, 
 0.0,       0.0,      -0.20001999,  0.0]

Матрица модели:

[0.0010, 0.0,    0.0, 0.0, 
 0.0,    0.0010, 0.0, 0.0, 
 0.0,    0.0,    1.0, 0.0, 
 0.0,    0.0,    1.0, 1.0]

unproject () вывод:

[-1.1232367, -0.11801138, -1.0032262, 1.0]

Что мне здесь приходит в голову, так это то, что возвращаемое значение z кажется неправильным - значение z, переданное в unproject (), равно -30 (как упоминалось выше).


person manmal    schedule 28.03.2012    source источник
comment
Имеет ли MatrixGrabber содержать правильные матрицы? Окно просмотра правильное? Хотя это выглядит странно, что однородные координаты используются вплоть до координат модели.   -  person Stefan Hanke    schedule 28.03.2012
comment
У моего MatrixGrabber есть действующие матрицы - не знаю, в порядке ли они. Область просмотра всегда [0,0, w, h]. Вы можете дать мне совет относительно однородных - ›координат модели?   -  person manmal    schedule 28.03.2012
comment
Нет, это нормально. Проективные части берутся из матриц проекций, а все остальные аффинные матрицы строятся н.э. эти части сквозные. Я предполагаю, что в mModelView грабберов шкалы почему-то нет. Для вызовов манипулирования матрицей, приведенных в вашем примере, можете ли вы показать две матрицы захвата и результат xyzw сразу после gluUnProject?   -  person Stefan Hanke    schedule 29.03.2012
comment
обновил вопрос запрошенными вами примерами значений :)   -  person manmal    schedule 29.03.2012


Ответы (1)


Посмотрим - мне не удалось воспроизвести полученные значения, но я думаю, что это не имеет значения.

Вы не должны вызывать unproject с z-значениями за пределами [-1;+1]. Первое, что должен сделать unproject, - это отменить преобразование окон, и после этого координаты должны быть в NDC-пространстве. В OpenGL это куб [-1;+1]^3 (songho содержит красивую графику). Вызов unproject с помощью -30 означает, что точка должна была находиться перед ближней плоскостью. Вызов этого с помощью z=-1.0f приводит к ближней плоскости, а z=+1.0f - к дальней плоскости.

Как выбрать z s.t. после всех обращений матриц сохраняется z=-30 - не знаю.

person Stefan Hanke    schedule 29.03.2012
comment
чувак, ты мой герой, полностью спас мне день / неделю! установка winz в -1 дает z-значение -1,05, а winz, равное 1, дает z-значение -1001,5 (с соответствующими значениями x, y). учитывая обе точки, я могу вычислить луч и пересечь его своими квадратами. Спасибо! - person manmal; 29.03.2012
comment
Рад это слышать! Я (раньше) любил этот тип математики, даже пробирался через статьи и книги Джима Блинна. Если вы думаете, что что-то знаете, он будет крутить;) - person Stefan Hanke; 30.03.2012