【问题标题】:Question about 3D Picking in Android (with OpenGL ES 2)关于 Android 中 3D Picking 的问题(使用 OpenGL ES 2)
【发布时间】:2011-06-07 07:24:24
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    哦。我实际上解决了这个问题,有点。

    我首先从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
    

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

    【讨论】:

    • 这很好xandy!关于这个解决方案的两个 cmets。对于 Android,您需要反转 winy (winy = screenheight-winy) 以实现 android 屏幕原点(屏幕左上角)和 Opengl 原点(左下角)之间的兼容性。另外,如果你有摄像头的位置,你可以保存一个调用 unProject,并使用摄像头的眼睛位置构建你的pickRay: Vec3 PickRay = Subtract(near, eye)
    猜你喜欢
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多