无法使gluUnProject()在Android OpenGL ES 2.0中运行

时间:2014-05-23 06:37:28

标签: android opengl-es opengl-es-2.0 transformation

我没有从gluUnProject函数得到预期的坐标值。

我先放一些代码。这是在触摸事件上调用的函数

public float[] getWorldSpaceFromMouseCoordinates(float mouseX, float mouseY)
{
    float[] finalCoord = { 0.0f, 0.0f, 0.0f, 0.0f };

    // mouse Y needs to be inverted
    mouseY = (float)_viewport[3] - mouseY;
    float[] mouseZ = new float[1];

    FloatBuffer fb = FloatBuffer.allocate(1);

    GLES20.glReadPixels((int)mouseX, (int)mouseY, 1, 1, GLES20.GL_DEPTH_COMPONENT, GLES20.GL_FLOAT, fb);

    int result = GLU.gluUnProject(mouseX, mouseY, fb.get(0), mViewMatrix, 0, mProjectionMatrix, 0, _viewport, 0, finalCoord, 0);

    float[] temp2 = new float[4];
    Matrix.multiplyMV(temp2, 0, mViewMatrix, 0, finalCoord, 0);
    if(result == GL10.GL_TRUE){
        finalCoord[0] = temp2[0] / temp2[3];
        finalCoord[1] = temp2[1] / temp2[3];
        finalCoord[2] = temp2[2] / temp2[3];

    }

    Log.d("Coordinate:", "" + temp2[0] + "," + temp2[1] + "," + temp2[2]);
    return finalCoord;
}

这里是设置矩阵

@Override
public void onSurfaceChanged(GL10 unused, int width, int height)
{
    // Adjust the viewport based on geometry changes,
    // such as screen rotation
    GLES20.glViewport(0, 0, width, height);
    _viewport = new int[] { 0, 0, width, height };

    float ratio = (float) width / height;

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 2, 7);
}

设置模型视图矩阵(注意模型矩阵只是一个标识。)

    // Set the camera position (View matrix)
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

根据我的理解,我对这个功能的期望是它会给我世界坐标w.r.t原点,这是没有发生的。我正在创建一个具有以下坐标

的正方形
       _vertices = new float [] { -0.5f, 0.5f, 0.0f, // top left
        -0.5f, -0.5f, 0.0f, // bottom left
        0.5f, -0.5f, 0.0f, // bottom right
        0.5f, 0.5f, 0.0f }; // top right

然而,我得到的X值范围为(.3, -.3) Y值,范围为(.5,-.5),Z始终为-1.0,适用于整个视口。触摸(0.2,-0.2)中的方角和Y值时,(0.15, -0.15)中的X值。

如果需要更多代码,请告诉我。

1 个答案:

答案 0 :(得分:0)

所以我发现了问题所在。 OpenGL ES 2.0不支持glReadPixels() GL_DEPTH_COMPONENT。那是因为我总是得到错误的深度值,因此错误的坐标。现在我有两个选择是使用着色器来使用FBO和存储深度还是我可以做Ray Picking(因为我在场景中只有一个对象Si希望gluUnProject()会这样做) 。我选择前者是我的代码我希望它能帮助某人(它不是通用的,几何是硬编码的)

    public float[] getWorldSpaceFromMouseCoordinates(float mouseX, float mouseY)
{
    float[] farCoord = { 0.0f, 0.0f, 0.0f, 0.0f };
    float[] nearCoord = { 0.0f, 0.0f, 0.0f, 0.0f };

    // mouse Y needs to be inverted
    //mouseY = (float) _viewport[3] - mouseY;

    // calling glReadPixels() with GL_DEPTH_COMPONENT is not supported in
    // GLES so now i will try to implement ray picking
    int result = GLU.gluUnProject(mouseX, mouseY, 1.0f, mViewMatrix, 0, mProjectionMatrix, 0, _viewport, 0,
            farCoord, 0);

    if (result == GL10.GL_TRUE)
    {
        farCoord[0] = farCoord[0] / farCoord[3];
        farCoord[1] = farCoord[1] / farCoord[3];
        farCoord[2] = farCoord[2] / farCoord[3];
    }

    result = GLU.gluUnProject(mouseX, mouseY, 0.0f, mViewMatrix, 0, mProjectionMatrix, 0, _viewport, 0, nearCoord,
            0);

    if (result == GL10.GL_TRUE)
    {
        nearCoord[0] = nearCoord[0] / nearCoord[3];
        nearCoord[1] = nearCoord[1] / nearCoord[3];
        nearCoord[2] = nearCoord[2] / nearCoord[3];
    }

    float [] dirVector = Vector.normalize(Vector.minus(farCoord, nearCoord));
    float [] rayOrigin =  {0.0f, 0.0f, 3.0f};

    Log.d("Far Coordinate:", "" + farCoord[0] + "," + farCoord[1] + "," + farCoord[2]);
    Log.d("Near Coordinate:", "" + nearCoord[0] + "," + nearCoord[1] + "," + nearCoord[2]);
    float [] vertices = { -0.5f, 0.5f, 0.0f, // top left
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f, // bottom right
            0.5f, 0.5f, 0.0f }; // top right

    // calculate normal for square
    float[] v1 = { vertices[3] - vertices[0], vertices[4] - vertices[1], vertices[5] - vertices[2]};
    float[] v2 = { vertices[9] - vertices[0], vertices[10] - vertices[1], vertices[11] - vertices[2]};

    float[] n = Vector.normalize(Vector.crossProduct(v1, v2));

    // now calculate intersection point as per following link
    // http://antongerdelan.net/opengl/raycasting.html

    // our plane passes through origin so findint 't' ll be

    float t = -(Vector.dot(rayOrigin, n) / Vector.dot(dirVector, n));

    // now substitute above t in ray equation gives us intersection point
    float [] intersectionPoint = Vector.addition(rayOrigin, Vector.scalarProduct(t, dirVector));
    Log.d("Ipoint:", "" + intersectionPoint[0] + "," + intersectionPoint[1] + "," + intersectionPoint[2]);
    return intersectionPoint;
}