2012-06-11 13 views
20

Ich baue eine Android-Anwendung, die OpenGL ES 2.0 verwendet und ich habe in eine Wand gerannt. Ich versuche, Bildschirmkoordinaten (wo der Benutzer berührt) zu Weltkoordinaten zu konvertieren. Ich habe versucht, mit GLU.gluUnProject zu lesen und zu spielen, aber ich mache es entweder falsch oder verstehe es einfach nicht.Android OpenGL ES 2.0 Bildschirmkoordinaten zu Weltkoordinaten

Dies ist mein Versuch ....

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

Die Zahlen, die ich bin immer noch nicht richtig sein, dann ist dies der richtige Weg, diese Methode zu nutzen? Funktioniert es für OpenGL ES 2.0? Soll ich die Modellmatrix vor diesen Berechnungen zu einer Identitätsmatrix machen (Matrix.setIdentityM (mModelMatix, 0))?

Als Follow up, wenn das korrekt ist, wie wähle ich den Ausgang Z? Grundsätzlich weiß ich immer, in welcher Entfernung die Weltkoordinaten liegen sollen, aber der Z-Parameter in GLU.gluUnProject scheint eine Art Interpolation zwischen der nahen und der fernen Ebene zu sein. Ist es nur eine lineare Interpolation?

Vielen Dank im Voraus

Antwort

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

Algorithmus wird weiter here.

+2

Meine Lösungen alle in C++. Wenn ich nur über diese Antwort scanne, sieht es für mich richtig aus. Also werde ich keine Antwort posten. :] – TheBuzzSaw

1

IMHO muss man diese Funktion nicht neu implementieren ... Ich experimentierte mit Erols Lösung und es funktionierte, also vielen Dank dafür Erol. Außerdem spielte ich mit

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

und es funktioniert gut, wie auch in meinem kleinen Noob Beispiel 2D OpenGL ES 2.0-Projekt: