Java OpenGL трансформация экрана в мир с использованием gluUnProject + обсуждение дизайна - PullRequest
1 голос
/ 07 марта 2012

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

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

У меня есть класс MouseController. Всякий раз, когда вызывается событие мыши (через MouseListener свинга), я передаю 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 обнаружит его.

Вводная информация о том, как вы, ребята, справитесь, будет очень признательна!

1 Ответ

0 голосов
/ 11 марта 2012

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

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

getContentPane().getSize()

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

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

...