Преобразовать координаты экрана в координаты 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 кубиков по горизонтали на экране.