Android OpenGL ES 2,0 coordenadas de la pantalla a las coordenadas del mundo
Estoy construyendo una aplicación para Android que usa OpenGL ES 2.0 y me he encontrado con una pared. Estoy tratando de convertir coordenadas de pantalla (donde el usuario toca) a las coordenadas del mundo. He intentado leer y jugar con GLU.gluUnProject, pero lo estoy haciendo mal o simplemente no lo entiendo.
Este es mi intento ….
- Compartir el contexto EGL2.0 entre 2 GLSurfaceViews causó EGL_BAD_ACCESS en las tabletas Android
- ¿Hay alguna forma de comprobar si el dispositivo Android es compatible con openGL ES 2.0?
- Android OpenGL ES 2, Dibujo de cuadrados
- Modificación de la salida de la cámara con SurfaceTexture y OpenGL
- Pasando varias texturas a shader en LibGDX
public void getWorldFromScreen(float x, float y) { int viewport[] = { 0, 0, width , height}; float startY = ((float) (height) - y); float[] near = { 0.0f, 0.0f, 0.0f, 0.0f }; float[] far = { 0.0f, 0.0f, 0.0f, 0.0f }; float[] mv = new float[16]; Matrix.multiplyMM(mv, 0, mViewMatrix, 0, mModelMatrix, 0); GLU.gluUnProject(x, startY, 0, mv, 0, mProjectionMatrix, 0, viewport, 0, near, 0); GLU.gluUnProject(x, startY, 1, mv, 0, mProjectionMatrix, 0, viewport, 0, far, 0); float nearX = near[0] / near[3]; float nearY = near[1] / near[3]; float nearZ = near[2] / near[3]; float farX = far[0] / far[3]; float farY = far[1] / far[3]; float farZ = far[2] / far[3]; }
Los números que estoy recibiendo no parecen correctos, ¿es esta la forma correcta de utilizar este método? ¿Funciona para OpenGL ES 2.0? ¿Debería hacer que la matriz de modelos una matriz de identidad antes de estos cálculos (Matrix.setIdentityM (mModelMatix, 0))?
Como un seguimiento, si esto es correcto, ¿cómo elegir la salida Z? Básicamente, siempre sé a qué distancia quiero que las coordenadas del mundo estén, pero el parámetro Z en GLU.gluUnProject parece ser algún tipo de interpolación entre el plano cercano y el plano lejano. ¿Es sólo una interpolación lineal?
Gracias por adelantado
- ¿Cuál es el parámetro "offset" en GLES20.glVertexAttribPointer / glDrawElements, y de dónde proviene ptr / indices?
- referencia indefinida glBindVertexArrayOES en eclipse
- Cómo compartir una asignación Renderscript con OpenGL en Android
- Actualización de la textura con glTexImage2D (..) en OpenglES2
- Android y OpenGL dan marco negro en el inicio
- OpenGL ES 2.0 - Texturas siempre negras
- Cómo cargar y mostrar el archivo .obj en Android con OpenGL-ES 2
- GlDepthMask (GL_FALSE) trashes el búfer de cuadros en algunas GPUs
/** * Calculates the transform from screen coordinate * system to world coordinate system coordinates * for a specific point, given a camera position. * * @param touch Vec2 point of screen touch, the actual position on physical screen (ej: 160, 240) * @param cam camera object with x,y,z of the camera and screenWidth and screenHeight of the device. * @return position in WCS. */ public Vec2 GetWorldCoords( Vec2 touch, Camera cam) { // Initialize auxiliary variables. Vec2 worldPos = new Vec2(); // SCREEN height & width (ej: 320 x 480) float screenW = cam.GetScreenWidth(); float screenH = cam.GetScreenHeight(); // Auxiliary matrix and vectors // to deal with ogl. float[] invertedMatrix, transformMatrix, normalizedInPoint, outPoint; invertedMatrix = new float[16]; transformMatrix = new float[16]; normalizedInPoint = new float[4]; outPoint = new float[4]; // Invert y coordinate, as android uses // top-left, and ogl bottom-left. int oglTouchY = (int) (screenH - touch.Y()); /* Transform the screen point to clip space in ogl (-1,1) */ normalizedInPoint[0] = (float) ((touch.X()) * 2.0f / screenW - 1.0); normalizedInPoint[1] = (float) ((oglTouchY) * 2.0f / screenH - 1.0); normalizedInPoint[2] = - 1.0f; normalizedInPoint[3] = 1.0f; /* Obtain the transform matrix and then the inverse. */ Print("Proj", getCurrentProjection(gl)); Print("Model", getCurrentModelView(gl)); Matrix.multiplyMM( transformMatrix, 0, getCurrentProjection(gl), 0, getCurrentModelView(gl), 0); Matrix.invertM(invertedMatrix, 0, transformMatrix, 0); /* Apply the inverse to the point in clip space */ Matrix.multiplyMV( outPoint, 0, invertedMatrix, 0, normalizedInPoint, 0); if (outPoint[3] == 0.0) { // Avoid /0 error. Log.e("World coords", "ERROR!"); return worldPos; } // Divide by the 3rd component to find // out the real position. worldPos.Set( outPoint[0] / outPoint[3], outPoint[1] / outPoint[3]); return worldPos; }
El algoritmo es explicado aquí.
Espero que mi pregunta (y respuesta) le ayude:
Cómo encontrar la posición absoluta del clic mientras ampliado
No sólo tiene el código, sino también diagramas y diagramas y diagramas que lo explican 🙂 Tomó años para entenderlo también.
IMHO uno no necesita volver a implementar esta función … Experimenté con la solución de Erol y funcionó, así que muchas gracias por Erol. Además, jugué con
Matrix.orthoM(mtrxProjection, 0, left, right, bottom, top, near, far);
Y funciona bien también en mi pequeño ejemplo de noob 2D OpenGL ES 2.0 proyecto:
- Public void onSurfaceChanged (GL10 no utilizado, int width, int height) {…
- URLConnection con Cookies?
- El adaptador de RecyclerView notifyDataSetChanged detiene la animación de fantasía