【问题标题】:Detecting planes and tap events with ARCore使用 ARCore 检测平面和点击事件
【发布时间】:2018-02-20 03:06:33
【问题描述】:

我正在努力了解Google's ARCore API并推送他们的sample project (java_arcore_hello_ar) to GitHub

在此示例中,当您将应用部署到 Android 时,会检测到任何水平表面/平面。如果您点击检测到的平面,“Andy”Andrid 机器人将在您点击的位置呈现。很酷。

我正在尝试查找代码中的位置:

  1. 检测到水平表面/平面;和
  2. 正确调整 Andy 大小和重新定向 Andy 的逻辑所在(我假设如果您点击的点距离相机更远,他会被渲染得很小,等等)

相信当检测到平面时,Android 框架会调用onSurfaceCreated 方法:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);

    // Create the texture and pass it to ARCore session to be filled during update().
    mBackgroundRenderer.createOnGlThread(/*context=*/this);
    mSession.setCameraTextureName(mBackgroundRenderer.getTextureId());

    // Prepare the other rendering objects.
    try {
        mVirtualObject.createOnGlThread(/*context=*/this, "andy.obj", "andy.png");
        mVirtualObject.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);

        mVirtualObjectShadow.createOnGlThread(/*context=*/this,
            "andy_shadow.obj", "andy_shadow.png");
        mVirtualObjectShadow.setBlendMode(BlendMode.Shadow);
        mVirtualObjectShadow.setMaterialProperties(1.0f, 0.0f, 0.0f, 1.0f);
    } catch (IOException e) {
        Log.e(TAG, "Failed to read obj file");
    }
    try {
        mPlaneRenderer.createOnGlThread(/*context=*/this, "trigrid.png");
    } catch (IOException e) {
        Log.e(TAG, "Failed to read plane texture");
    }
    mPointCloud.createOnGlThread(/*context=*/this);
}

但是代码看起来像,它假定用户已经点击了表面。我没有看到 if-conditional 基本上说“渲染 Andy 如果用户已经点击了检测到的平面/表面。”。谁能发现这可能发生在哪里?

【问题讨论】:

    标签: java android augmented-reality arcore


    【解决方案1】:

    点击检测由mGestureDetector:

    mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            onSingleTap(e);
            return true;
        }
    
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
    });
    

    链接到SurfaceView

    mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return mGestureDetector.onTouchEvent(event);
        }
    });
    

    这两件事都发生在onCreate(),所以现在每次点击表面视图(活动中的“主”视图)时,

    private void onSingleTap(MotionEvent e) {
        // Queue tap if there is space. Tap is lost if queue is full.
        mQueuedSingleTaps.offer(e);
    }
    

    被调用并且点击被存储。然后在每帧绘制中处理这个队列(依次由系统的UI绘制周期发出)here

    MotionEvent tap = mQueuedSingleTaps.poll();
    if (tap != null && frame.getTrackingState() == TrackingState.TRACKING) {
        for (HitResult hit : frame.hitTest(tap)) {
           ...
    

    这会添加一个新的锚点(即物理世界中“锁定”的点),Android 对象在该点处呈现(cf. this line)

    【讨论】:

    • 谢谢@PhilLab (+1) - 你是说GLSurfaceView 的触摸监听器是 ARCore 可以检测给定表面/平面的触摸事件的地方吗?如果是这样,该代码如何链接到 onSurfaceCreated 方法(首先被调用 -> 触摸侦听器的 onTouchonSurfaceCreated)?
    • 触摸监听器仅将触摸添加到处理队列中。然后在 draw 方法中对其进行轮询
    • 谢谢@PhilLab(再次+1)我正在关注您所说的大部分,除了一件事:(具体而言)应用程序/框架在哪里检测到用户点击了一个特定的平面(而不是仅仅点击不是平面的东西,因此不能在上面渲染“Andy”)?再次感谢!
    • 是的,今天早上我再次查看了您的答案和代码,我认为我们在这里肯定缺少 something。首先,我认为我们需要明确说明 GLSurfaceView 是什么。在阅读了它的 Javadocs 之后,我不清楚它是否代表一个(检测到的)平面/水平平面,或者它是否只代表任何(平面或其他)3D 对象的外部纹理。在我理解之后,代码对我来说会更有意义!
    • 这是frame.hitTest(tap)
    猜你喜欢
    • 1970-01-01
    • 2018-02-09
    • 2018-03-25
    • 2019-12-16
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    相关资源
    最近更新 更多