Преобразовать координаты экрана в координаты OpenGL

Я создаю приложение Dice Roller для Android. Использование Kotlin, OpenGL-ES и jBullet. Я реализовал кости. Теперь мне нужно создать стены, потому что в противном случае игра в кости выкатится с экрана.

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

    gl.glViewport(0,0,width,height)    //Reset The Current Viewport
    gl.glMatrixMode(GL10.GL_PROJECTION)    //Select The Projection Matrix
    gl.glLoadIdentity()                    //Reset The Projection Matrix

    //Calculate The Aspect Ratio Of The Window
    GLU.gluPerspective(gl, 35.0f, width.toFloat() / height.toFloat(), 0.1f, 100.0f)

    GLU.gluLookAt(gl,
           0.0f, 30.0f,  0.0f, //Pos
           0.0f,  0.0f,  0.0f, //Look at
           0.0f,  0.0f,  1.0f  //Up
    );

    gl.glMatrixMode(GL10.GL_MODELVIEW)    //Select The Modelview Matrix
    gl.glLoadIdentity()                    //Reset The Modelview Matrix

    // Get matrices
    gl.glGetFloatv(GL11.GL_PROJECTION_MATRIX, glProjectionMatrix,0)
    gl.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, glModelMatrix,0)
    gl.glGetIntegerv(GL11.GL_VIEWPORT, glViewPort,0)

    // Allocate matrices
    var modelMatrix = glModelMatrix
    var projMatrix  = glProjectionMatrix
    var view = glViewPort

    // Pre allocate wall positions
    var wallDown = FloatArray(4)

    // The needed point
    var wallDownP = Vector3f(view[2].toFloat(), view[3].toFloat(), 0.2888888f)

    GLU.gluUnProject(wallDownP.x, wallDownP.y, wallDownP.z, modelMatrix, 0, projMatrix, 0, view, 0, wallDown, 0)

1 ответ

Решение

gluPerspective может быть немного неудачно в вашем случае. Это удобство от frustum операция определяется полем зрения.

Это все выполнимо из настроек, которые у вас есть в данный момент, но я рекомендую вам использовать frustum напрямую, так как будет проще вычислить:

Конус определяется параметрами границы (top, bottom, left, right), near а также far, Прямоугольник с параметрами границы с расстоянием near будет точно на весь экран. Поэтому лучше начать с самой доски. Если вы определите размер доски (viewWidth, viewHeight) и хочу поле зрения fov=35 по ширине, то расстояние d к этому объекту должно быть d*tan(35/2)=viewWidth/2 так d=viewWidth/(2*tan(35/2)) которая сейчас является относительно большой ценностью. Расстояние d теперь можно использовать как far так как я предполагаю, что вы не будете рисовать ничего за доской, а просто для уверенности, что пользователь d*2, (Увеличение far уменьшит точность буфера глубины, но не более того). Так что теперь вы можете определить near как-то так 0.1 где тогда масштаб проекции объекта scale=near/d и значения границы тогда являются исходными значениями, умноженными на масштаб:

  • left = -screenWidth/2*scale
  • right = screenWidth/2*scale
  • top = screenHeight/2*scale
  • bottom = -screenHeight/2*scale

Таким образом, имея эту настройку, вы увидите прямоугольник размера (viewWidth, viewHeight) На расстоянии d как точно на весь экран. Так вставьте d в lookAt параметры и это должно быть все. Размер игральных костей может тогда быть определен шириной экрана, таким образом, это кажется одинаковым на всех устройствах. Например, используя screenWidth/10 для размера костей вы всегда сможете разместить ровно 10 кубиков по горизонтали на экране.

Другие вопросы по тегам