2012-06-11 2 views
20

Я создаю приложение для Android, которое использует OpenGL ES 2.0, и я столкнулся с стеной. Я пытаюсь преобразовать координаты экрана (где пользователь прикасается) к мировым координатам. Я пробовал читать и играть с GLU.gluUnProject, но я либо делаю это неправильно, либо просто не понимаю.Координаты экрана Android OpenGL ES 2.0 с мировыми координатами

Это моя попытка ....

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

Числа я получаю не кажется правильным, это правильный способ использовать этот метод? Он работает для OpenGL ES 2.0? Должен ли я сделать модельную матрицу единичной матрицей перед этими вычислениями (Matrix.setIdentityM (mModelMatix, 0))?

В качестве продолжения, если это правильно, как я могу выбрать выход Z? В принципе, я всегда знаю, на каком расстоянии я хочу, чтобы координаты мира были, но параметр Z в GLU.gluUnProject кажется некоторой интерполяцией между ближней и дальней плоскостью. Это просто линейная интерполяция?

Заранее спасибо

ответ

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

Алгоритм далее объясняется here.

+2

Мои решения находятся в C++. Просто просматривая этот ответ, он выглядит правильно для меня. Поэтому я не буду публиковать ответ. :] – TheBuzzSaw

1

Надеется, что мой вопрос (и ответ) должен помочь вам:

How to find absolute position of click while zoomed in

Он имеет не только код но и диаграммы, диаграммы и диаграммы, объясняющие это :) Принял меня, чтобы понять это.

1

IMHO один не нуждается в повторной реализации этой функции ... Я экспериментировал с решением Erol и работал, поэтому большое спасибо за это Erol. Кроме того, я играл с

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

и она отлично работает, а в моем крошечном примере нуб 2D OpenGL ES проект 2.0:

 Смежные вопросы

  • Нет связанных вопросов^_^