Android 如何在ARCore中检查光线与对象的相交

Android 如何在ARCore中检查光线与对象的相交,android,arcore,Android,Arcore,有没有办法检查我是否触摸了屏幕上的物体?据我所知,HitResult类允许我检查我是否接触了已识别和映射的曲面。但我想检查一下,我接触了设置在该表面上的对象。ARCore实际上没有对象的概念,所以我们不能直接提供。我建议找一个起点 但是,我可以帮助获取光线本身(添加到HelloArActivity): 如果你每帧调用这个次数,请参阅关于 GETPrimeMatxMode < /code >和 RoopTM 调用。< /P> < P>除了伊恩的回答之外,另一种常用的技术是一个拾取缓冲区,详细解释(

有没有办法检查我是否触摸了屏幕上的物体?据我所知,HitResult类允许我检查我是否接触了已识别和映射的曲面。但我想检查一下,我接触了设置在该表面上的对象。

ARCore实际上没有对象的概念,所以我们不能直接提供。我建议找一个起点

但是,我可以帮助获取光线本身(添加到
HelloArActivity
):

如果你每帧调用这个次数,请参阅关于<代码> GETPrimeMatxMode < /code >和 RoopTM 调用。< /P> < P>除了伊恩的回答之外,另一种常用的技术是一个拾取缓冲区,详细解释(用C++代码)

3D拾取背后的技巧非常简单。我们将附上一份跑步记录 索引到每个三角形,并让FS输出三角形的索引 像素所属的三角形。最终的结果是我们得到了一个 “颜色”缓冲区并不真正包含颜色。相反,对于每个 被一些原语覆盖的像素,我们得到这个的索引 原始的。当鼠标点击窗口时,我们将返回阅读 该索引(根据鼠标的位置)并渲染 选择三角形红色。通过在过程中结合深度缓冲区,我们 确保当多个基本体重叠在同一像素上时 我们得到最上面的基本体(离相机最近)的索引

简言之:

  • 每个对象的绘制方法都需要一个进行中的索引和一个布尔值,以确定该绘制是否渲染像素缓冲区
  • 渲染方法将索引转换为灰度颜色,然后渲染场景
  • 整个渲染完成后,在触摸位置检索像素颜色
    GL11。glReadPixels(x,y,/*您想要颜色的像素的x和y*/)
    。然后将颜色转换回索引,并将索引转换回对象。瞧,你有你的点击对象
  • 公平地说,对于一个移动用例,你可能应该阅读一个10x10的矩形,通过它迭代,然后选择第一个找到的非背景色——因为触摸从来没有那么精确

    这种方法与对象的复杂性无关


    首先感谢您的回答。我担心的是,在网络上,我能找到许多不同的光线与简单物体相交的例子,而与更复杂的物体相交的例子又是什么呢?是的,但它可以与具有两种颜色的简单物体相交。当你在户外时,你将使用绿色作为对象,而不是容易产生错误的解释(例如草、树)不,你可以用“错误”的巨像渲染整个场景,即没有照明,没有纹理,。。。每个对象只有一个固定的颜色(参见上面我添加的屏幕截图)。此图像从未向用户显示,仅用于确定点击次数,因此我将有2层?一个是“错误”的颜色,另一个是用户可见的颜色?是的,如果“层”在这里是一个非正式的短语(正式的可以是“缓冲”)。“错误颜色层”仅在单击时渲染。
    /** 
     * Returns a world coordinate frame ray for a screen point.  The ray is
     * defined using a 6-element float array containing the head location
     * followed by a normalized direction vector.
     */
    float[] screenPointToWorldRay(float xPx, float yPx, Frame frame) {
        float[] points = new float[12];  // {clip query, camera query, camera origin}
        // Set up the clip-space coordinates of our query point
        // +x is right:
        points[0] = 2.0f * xPx / mSurfaceView.getMeasuredWidth() - 1.0f;
        // +y is up (android UI Y is down):
        points[1] = 1.0f - 2.0f * yPx / mSurfaceView.getMeasuredHeight(); 
        points[2] = 1.0f; // +z is forwards (remember clip, not camera)
        points[3] = 1.0f; // w (homogenous coordinates)
    
        float[] matrices = new float[32];  // {proj, inverse proj}
        // If you'll be calling this several times per frame factor out
        // the next two lines to run when Frame.isDisplayRotationChanged().
        mSession.getProjectionMatrix(matrices, 0, 1.0f, 100.0f);
        Matrix.invertM(matrices, 16, matrices, 0);
        // Transform clip-space point to camera-space.
        Matrix.multiplyMV(points, 4, matrices, 16, points, 0);
        // points[4,5,6] is now a camera-space vector.  Transform to world space to get a point
        // along the ray.
        float[] out = new float[6];
        frame.getPose().transformPoint(points, 4, out, 3);
        // use points[8,9,10] as a zero vector to get the ray head position in world space.
        frame.getPose().transformPoint(points, 8, out, 0);
        // normalize the direction vector:
        float dx = out[3] - out[0];
        float dy = out[4] - out[1];
        float dz = out[5] - out[2];
        float scale = 1.0f / (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
        out[3] = dx * scale;
        out[4] = dy * scale;
        out[5] = dz * scale;
        return out;
    }