0

我需要一些关于 3D 拾取的帮助。

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

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 甚至不接近我想点击的点。我已经在网上搜索了一个多星期。但不知道如何解决它。帮助!

4

1 回答 1

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

上面的输入将是投影视图平截头体坐标中的点(即屏幕输入)。例如:

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

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

我制作拾取函数的方式是使用上述函数在远近裁剪平面上取消投影两个点,因此:

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

一旦我们有了拾取射线,我所做的只是测试拾取射线与那些“可拾取”对象的“中心”之间的距离。(当然,你可以有一些更复杂的测试算法)。

于 2011-06-24T00:48:05.903 回答