关于Android中3D拾取的问题(使用OpenGL ES 2)

时间:2011-06-07 07:24:25

标签: android opengl-es-2.0 ray-picking

我需要一些关于3D采摘的帮助。

我正在使用它的工作方式here。简而言之,我所拥有的是:

normalizedPoint[0] = (x * 2 / screenW) -1;
normalizedPoint[1] = 1 - (y * 2 / screenH);
normalizedPoint[2] = ?
normalizedPoint[3] = ?

对于2和3,我不知道它应该是什么(我把1,-1就像参考,它不起作用)

然后,对于我的根对象(仅使用伪代码):

matrix = perspective_matrix x model_matrix
inv_matrix = inverse(matrix)
outpoint = inv_matrix x normalizedPoint

这就是我所拥有的,但它不起作用,我收到的outPoint甚至没有接近我想点击的那一点。我在网上搜索了一个多星期。但不知道如何解决它。帮助!

1 个答案:

答案 0 :(得分:3)

喔。我实际上解决了这个问题。

首先,从glUnproject的源代码修改为:

public static Vec3 unProject(
        float winx, float winy, float winz,
        Matrix44 resultantMatrix,
        int width, int height){
    float[] m = new float[16],
    in = new float[4],
    out = new float[4];

    m = Matrix44.invert(resultantMatrix.get());

    in[0] = (winx / (float)width) * 2 - 1;
    in[1] = (winy / (float)height) * 2 - 1;
    in[2] = 2 * winz - 1;
    in[3] = 1;

    Matrix.multiplyMV(out, 0, m, 0, in, 0);

    if (out[3]==0)
        return null;

    out[3] = 1/out[3];
    return new Vec3(out[0] * out[3], out[1] * out[3], out[2] * out[3]);
}

上面的输入将是Projected View Frustum Coordinates中的点(即屏幕输入)。例如:

unProject(30, 50, 0, mvpMatrix, 800, 480) 

将(30,50)处的屏幕输入(单击)转换为对象所在的世界坐标。第三个参数winz实际上是在点击发生的投影平面上,这里,0表示投影平面的近Z。

我进行拣选功能的方法是在远近剪裁平面上使用上述函数取消投影两个点,所以:

Vec3 near = unProject(30, 50, 0, mvpMatrix, 800, 480);
Vec3 far = unProject(30, 50, 1, mvpMatrix, 800, 480);   // 1 for winz means projected on the far plane
Vec3 pickingRay = Subtract(far, near); // Vector subtraction

一旦我们有了采摘光线,我所做的只是测试采摘光线和"中心之间的距离。那些" pickable"对象。 (当然,你可以有一些更复杂的测试算法)。