2012-06-11 3 views
20

Sto costruendo un'applicazione Android che utilizza OpenGL ES 2.0 e ho eseguito un muro. Sto provando a convertire le coordinate dello schermo (dove l'utente tocca) alle coordinate del mondo. Ho provato a leggere e giocare con GLU.gluUnProject, ma o lo sto facendo male o semplicemente non lo capisco.Coordinate dello schermo Android OpenGL ES 2.0 alle coordinate mondiali

Questo è il mio tentativo ....

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]; 
} 

I numeri che sto ottenendo non mi sembra giusto, è questo il modo giusto di utilizzare questo metodo? Funziona con OpenGL ES 2.0? Dovrei rendere la matrice modello una matrice di identità prima di questi calcoli (Matrix.setIdentityM (mModelMatix, 0))?

Come seguito, se questo è corretto, come faccio a scegliere l'uscita Z? Fondamentalmente, so sempre a quale distanza voglio che siano le coordinate del mondo, ma il parametro Z in GLU.gluUnProject sembra essere una sorta di interpolazione tra il piano vicino e quello lontano. È solo un'interpolazione lineare?

Grazie in anticipo

risposta

21
/** 
    * 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;  
    } 

algoritmo è ulteriormente spiegato here.

+2

mie soluzioni sono tutti in C++. Basta scannerizzare questa risposta, mi sembra giusto. Quindi, non invierò una risposta. :] – TheBuzzSaw

1

IMHO non è necessario ri-implementare questa funzione ... Ho sperimentato la soluzione di Erol e ha funzionato, quindi grazie mille Erol. Inoltre, ho giocato con

 Matrix.orthoM(mtrxProjection, 0, left, right, bottom, top, near, far); 

e funziona benissimo pure nel mio piccolo esempio niubbo 2D OpenGL ES 2.0 progetto: