gluProject преобразование 3D-координат в 2D-координаты не преобразует 2D-координату Y правильно

после двух часов погуглить (здесь, здесь, здесь, здесь и здесь и тонна других, которые я не удосужился найти), я думал, что наконец узнал теорию поворота 3D-координат в 2D-координаты. Но это не работает. Идея в том, чтобы перевести 3D координаты корабля в 2D координаты на экране, чтобы отобразить имя игрока, управляющего этим кораблем.

текст оказывается в неправильном месте: enter image description here

текст "Test || 2DXCoordinate / / 2DZCoordinate".

вот мой getScreenCoords() - который преобразует 3D координаты в 2D.

public static int[] getScreenCoords(double x, double y, double z) {
    FloatBuffer screenCoords = BufferUtils.createFloatBuffer(4);
    IntBuffer viewport = BufferUtils.createIntBuffer(16);
    FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
    FloatBuffer projection = BufferUtils.createFloatBuffer(16);
    GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
    GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
    GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
    boolean result = GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
    if (result) {
        return new int[] { (int) screenCoords.get(0), (int) screenCoords.get(1) };
    }
    return null;
}

screenCoords.get (0) возвращает идеальную координату X. Однако, screenCoords.get (1) идет выше или ниже в зависимости от того, насколько далеко я от корабля. После многих часов отладки я сузил его до этой строки неверно:

GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);

однако я понятия не имею, что случилось. Координата X корабля в порядке.... Почему не Y?

согласно ответу BDL, я поставляю "неправильную матрицу" в gluProject(). Но я не вижу, как это возможно, поскольку я вызываю метод сразу после рендеринга моего корабля (который, очевидно, находится в любой матрице, которая рисует корабль).

Я просто не могу понять, что случилось.

Примечание: ответ BDL совершенно адекватен за исключением это не объясняет, почему координаты Y неверны.

Примечание: этот вопрос был намного длиннее и гораздо более расплывчатым. Я опубликовал свой суженный вопрос выше после нескольких часов отладки.

2 ответов


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

Общая теория о системах координат в OpenGL

в большинстве случаев геометрия модели в вашей сцене (например, корабль) задается в модель-система координат. Это пространство, где ваша вершина координаты существуют. При размещении модели в вашей сцене мы применяем модель-матрицу к каждой вершине, чтобы получить координаты корабля в сцене. Эта система координат называется мировое пространство. При просмотре сцены с заданной точки зрения и направления просмотра снова требуется преобразование, которое преобразует сцену так, что точка зрения находится в начале координат (0,0,0), а направление просмотра-вдоль отрицательной оси Z. Это посмотреть координаты система. Последний шаг-преобразование координат вида в ndc, которое выполняется с помощью проекционной матрицы.

в общей сложности мы получаем преобразование вершины на экране, например:

 v_screen = Projection * View * Model * v_model

в Древнем OpenGL (как вы его используете) представление и модель хранятся вместе в матрице ModelView.

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

ваш проблема

у вас уже есть позиция в мировом пространстве (x,y,z) вашего корабля. Таким образом, трансформация с моделью уже произошла. То, что осталось

v_screen = Projection * View * v_worldspace

для этого мы видим, что в нашем случае матрица ModelView, которая вводится в gluProject, должна быть именно матрицей представления.

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


Я нашел ответ на мой вопрос!

Я

font.drawString(drawx - offset, drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);

когда это должно было быть

font.drawString(drawx - offset, Display.getHeight() - drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);