将屏幕坐标转换为OpenGL坐标

我正在为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) 

gluPerspective可能在你的情况有点不幸。 这是由视野定义的frustum操作的便利。

这一切都可以从目前的设置,但我建议你直接使用视frustum ,因为它会更容易计算:

平截头体由边界参数( topbottomleftright ), nearfar 。 具有近距离边界参数的矩形将完全全屏。 所以最好从董事会本身开始。 如果你定义板子的尺寸(viewWidth, viewHeight)并且需要宽度为(viewWidth, viewHeight) fov=35的视场,那么到这个物体的距离d应该是d*tan(35/2)=viewWidth/2 so d=viewWidth/(2*tan(35/2)) ,这是一个相对较大的值。 距离d现在可以使用, far我假设你将不会在板子后面画任何东西,但只是为了确保用户d*2 。 (增加far会降低深度缓冲的精度,但没有别的)。 所以现在你可以定义near 0.1东西,那么物体投影的scale=near/dscale=near/d ,然后边界值是原始值乘以比例:

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

所以有了这个设置,你将会在距离d处选择大小的矩形(viewWidth, viewHeight) ,就像完整的全屏幕一样。 因此,将d插入到lookAt参数中,应该是全部。 骰子的大小可以由屏幕宽度来定义,因此它在所有设备上看起来相似。 例如,使用screenWidth/10作为骰子尺寸,您将始终能够在屏幕上水平放置10个骰子。