Экран Java OpenGL для преобразования мира с помощью gluUnProject + обсуждение дизайна

У меня есть 2 вопроса. Один конкретный вопрос о том, почему мой код не работает должным образом, а другой — вопрос дизайна.

1 (конкретный вопрос): я пытаюсь сопоставить координаты экрана с мировыми координатами в движке на основе 2D-тайлов (использует ось x/y, z = 0). Я использовал порт учебника Nehe о том, как добиться этого, но результаты, которые я получаю, не такие, как ожидалось.

У меня есть класс под названием MouseController. Всякий раз, когда событие мыши вызывается (через MouseListener в Swing), я передаю MouseEvent в свой MouseController.

В моей функции рисования GLCanvas я вызываю функцию MouseController.processClick(GL), чтобы иметь возможность передать текущий контекст gl в функцию processClick и получить представление модели, матрицы проекций и область просмотра.

Когда я нажимаю на отображаемый на экране блок, возвращаемые мне мировые координаты практически не имеют смысла. Во-первых, я бы ожидал, что значение z будет равно 0, но оно равно 9 (именно так высоко настроена моя камера), а мои значения x и y всегда очень близки к 0 (иногда подскакивают до 1-9 с очень небольшие движения, а затем обратно к числу, очень близкому к 0).

Кто-нибудь знает, почему это может быть так? Ниже приведена функция processClick:

    public void processClick(GL gl) {

        int x = e.getX();
        int y = e.getY();

        if(e.getButton() == MouseEvent.BUTTON1) {

            gl.glGetIntegerv(GL.GL_VIEWPORT, viewPort, 0);
            gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, mvMatrix, 0);
            gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, prMatrix, 0);

            int realy = viewPort[3] - y;

            glu.gluUnProject((double)x, (double)realy, 0, mvMatrix, 0, prMatrix, 0, viewPort, 0, wCoord, 0);

            System.out.println(x + " " + y);
            System.out.println(x + " " + realy);
            System.out.println(wCoord[0] + " " + wCoord[1] + " " + wCoord[2]);
        }

        e = null;
    }

Пример вывода, который я получаю от вышеуказанной функции, когда я нажимаю на экран, где я визуализировал квадрат с мировыми координатами (4,5,0):

  878 56
  878 636
  0.0445182388817236 0.055475957454737095 8.900000001489369

Спасибо!

РЕДАКТИРОВАТЬ: Чтение буфера глубины с помощью glReadPixels и использование его в качестве z (которое возвращает 1) дает мне правильные результаты, но они слишком велики в 20 раз.

EDIT2: Если я установлю дальнюю плоскость отсечения на то же значение, что и высота камеры, это, кажется, сработает (но это не совсем подходит).

2 (Вопрос по дизайну): мне кажется, что нет смысла обрабатывать клики в функции рисования холста OpenGL. Кажется, мне требуется, чтобы GL из этой функции мог получить матрицы, необходимые для запуска gluUnProject. Как бы вы, ребята, спроектировали это? В идеале я чувствую, что должен иметь возможность полностью отделить этот запуск от функции рисования. Сохраните ссылку на объект gl в моем MouseController и обработайте щелчок, когда MouseListener уловит его.

Мы также будем очень признательны за ваши отзывы о том, как вы, ребята, справитесь с этим!


person Mick    schedule 07.03.2012    source источник


Ответы (1)


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

Единственной «сложной» вещью была передача фактического разрешения экрана в gluOrtho2D, которое можно было получить (и сохранить) с помощью:

getContentPane().getSize()

Из JFrame, который я использовал.

Установка предпочтительного размера на панели, а затем упаковка рамы дали близкие результаты, но сама панель все еще немного отклонялась.

person Mick    schedule 11.03.2012