【问题标题】:Using gluUnProject to map touches to x,y cords on z=0 plane in Android OpenGL ES 2.0在 Android OpenGL ES 2.0 中使用 gluUnProject 将触摸映射到 z=0 平面上的 x、y 线
【发布时间】:2013-12-20 10:03:37
【问题描述】:

我在 OpenGL 2.0 ES 中的 z=0 处绘制了一个网格,并且只想将触摸输入转换为该平面上的 x/y 坐标。似乎这最好通过光线追踪来完成,这包括在 0 和 1 上运行 gluUnProject,然后创建一条光线,解决 z=0 的光线?

我找到了这段代码,但它是 OpenGL ES 1.0:i-schuetz / Android_OpenGL_Picking

Screenshot of app running so you can see camera distortion.

My code on Github, only 4 files。我正在尝试编写的 unproject 函数在 MyGLRenderer.java 中:

    public float[] unproject(float rx, float ry) {
            float rz = 1;
        float[] xyzw = {0, 0, 0, 0};
        int[] viewport = {0, 0, mDisplayWidth, mDisplayHeight};
        android.opengl.GLU.gluUnProject(
                        rx, ry, rz, // window coordinates
                        mViewMatrix, 0,
                        mProjectionMatrix, 0, 
                        viewport, 0,
                        xyzw, 0);
        xyzw[0] /= xyzw[3];
        xyzw[1] /= xyzw[3];
        xyzw[2] /= xyzw[3];
        xyzw[3] = 1;
        return xyzw;
    }

我希望这个函数为屏幕获取一个 rx 和 ry,并为 z=0 平面返回一个 rx 和 ry。

【问题讨论】:

    标签: android opengl-es touch opengl-es-2.0 raytracing


    【解决方案1】:

    gluUnProject (...) 所做的并没有什么特别之处。如果您拥有所有矩阵和视口尺寸 (x,ywidth,h)我可以引导你自己完成它的实现过程。

    注意:我倾向于使用与您习惯不同的名称来调用每个坐标空间,请理解屏幕空间window space 的别称,view spaceeye space 的别称对象空间模型空间的别称。


    第 1 步:

       屏幕空间到 NDC 空间 (撤消视口变换)

              NDCX = (2.0 × (屏幕X - 视口X) / 视口W) - 1.0

              NDCY = (2.0 × (ScreenY - 视口) / 视口H)  - 1.0

       屏幕空间到 NDC 空间 (撤消深度范围映射)

             通常在屏幕空间中,深度范围会将z=0映射到附近 z=1

                   NDCZ = 2.0 × 屏幕Z子> - 1.0


    第 2 步

       NDC 空间到对象空间 (撤消投影、视图和模型变换)

             (投影矩阵)-1  × NDCXYZ1   = 查看XYZW

             (ModelView矩阵)-1 × ViewXYZW  = 对象XYZW

                      这实际上可以合并为一个步骤,如下所示...


                              对象XYZw = (投影 矩阵 × ModelView 矩阵)-1 × NDCXYZ em>1


    现在,您可能会注意到我在 ObjectXYZ 中划掉了 W,我们真的根本不关心这个,但数学会产生然而,一个讨厌的 W 值。此时,您可以将 ObjectXYZ 的各个组件返回为您的 rX、rYrZ

    【讨论】:

    • 谢谢!我现在正在编写你的答案。
    • 所以我完成了实施,但似乎我正是我开始的地方。我有一个 XYZ 点,但它不在 Z=0 平面上。我想我可能需要使用那个点和相机点,并为 z 解决它们?这是我编写您的答案的地方:github.com/rkuykendall/ProjectRome/commit/…
    • @RobertKuykendall:另外,如果你想用它来挑选,你只能通过取消保护一个点来解决方程的一半。您想要做的是求解(找到等效的对象空间位置)屏幕空间 (x,y,0) 上的一个点和屏幕空间 (x,y,1) 上的一个点,然后计算穿过两者的射线点(并从您解决的第一个点开始)。一旦你有了这条射线,你就可以用它来对你场景中的任何东西进行交叉测试。
    • 我认为“近”和“远”剪切平面是指相机,而不是绘图平面。我指的是飞机items are drawn on。我在 z=0 处绘制了所有这些图块,现在我试图找出点击了哪个图块。我不知道我拥有的 xyz 线将如何帮助我找到我在绘图表面上单击的位置,因为我在 z=0 处绘制了东西。
    • 显然,如果我在绘制它们的 Z=0 平面上有一条 XY 线,我可以计算出我点击了哪个图块,但我不知道如何得到那个点。
    猜你喜欢
    • 1970-01-01
    • 2010-10-09
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    相关资源
    最近更新 更多