【问题标题】:Detecting if an tap event with ARCore hits an already added 3d object检测带有 ARCore 的点击事件是否击中了已添加的 3d 对象
【发布时间】:2018-03-25 11:29:51
【问题描述】:

我正在关注 ARCore 示例 (https://github.com/google-ar/arcore-android-sdk),我正在尝试删除已添加的对象 3d (andy)。 如何检测带有 ARCore 的点击事件是否击中了已添加的 3d 对象?

【问题讨论】:

    标签: java android augmented-reality arcore


    【解决方案1】:

    在这种情况下使用listener 是很常见的方法:

    private Node getModel() {
        Node node = new Node();
        node.setRenderable(modelRenderable);
        Context cont = this;
        node.setOnTapListener((v, event) -> {
            Toast.makeText(
                cont, "Model was touched", Toast.LENGTH_LONG)   // Toast Notification 
                .show();
        });
        return node;
    }
    

    【讨论】:

      【解决方案2】:

      这几天我有同样的问题,我尝试了 2 个解决方案,

      1. frame.hitTest(MotionEvent)

      2.将顶点从arcore世界投影到视图中的二维坐标

      一开始我使用1.来获取平面上的命中姿势并与已经存在的3d物体的姿势进行比较,但是一旦3d物体离开平面,这将不起作用。

      最后我使用 2. 来获取视图中 3d 对象的顶点,然后使用点击位置进行命中测试。

      如果你正在关注 ARCore 示例,你可以在 ObjectRenderer.java 的 draw 方法中看到这一行

      Matrix.multiplyMM(mModelViewProjectionMatrix, 0, 
                        cameraPerspective, 0, mModelViewMatrix, 0);
      

      “mModelViewProjectionMatrix”只需使用此 ModelViewProjection 矩阵将您已添加的 3d 对象的顶点从 3d arccore 世界映射到 2d 视图。

      就我而言,我会做这样的事情,

      pose.toMatrix(mAnchorMatrix, 0);
      objectRenderer.updateModelMatrix(mAnchorMatrix, 1);
      objectRenderer.draw(cameraView, cameraPerspective, lightIntensity);
      
      float[] centerVertexOf3dObject = {0f, 0f, 0f, 1};
      float[] vertexResult = new float[4];
      Matrix.multiplyMV(vertexResult, 0, 
                        objectRenderer.getModelViewProjectionMatrix(), 0, 
                        centerVertexOf3dObject, 0);
      // circle hit test
      float radius = (viewWidth / 2) * (cubeHitAreaRadius/vertexResult[3]);
      float dx = event.getX() - (viewWidth / 2) * (1 + vertexResult[0]/vertexResult[3]);
      float dy = event.getY() - (viewHeight / 2) * (1 - vertexResult[1]/vertexResult[3]);
      double distance = Math.sqrt(dx * dx + dy * dy);
      boolean isHit = distance < radius;
      

      我在 ARCore Measure 应用中使用它,
      https://play.google.com/store/apps/details?id=com.hl3hl3.arcoremeasure

      和源代码, https://github.com/hl3hl3/ARCoreMeasure/blob/master/app/src/main/java/com/hl3hl3/arcoremeasure/ArMeasureActivity.java

      【讨论】:

        【解决方案3】:

        您可以在添加对象的节点上添加一个侦听器。

            node.setOnTapListener((v, event) -> {
                showMessage("tap happened");
            });
        

        【讨论】:

          【解决方案4】:

          除了其他答案中列出的其他方法之外,您还可以检查 hitTestResult 以查看它是否包含节点(这是 Kotlin,但同样的方法也适用于 Java):

           if (hitTestResult.getNode() != null) {
              //We have hit an AR node
              Log.d(TAG, "hitTestResult.getNode() != null: " + hitTestResult.getNode());
              var hitNode: Node? = hitTestResult.node
          
              //You can add additional checks to see if it is a particuar type if renderable for example
              if (hitNode?.renderable == yourRenderable1) {
              //Do whatever you want if this renderable type is hit
          
              }
           } else {
              //We have not hit an ARNode - add your 
              //code here for this case....
          
           }
          

          【讨论】:

            猜你喜欢
            • 2017-05-03
            • 2018-02-20
            • 1970-01-01
            • 1970-01-01
            • 2022-08-10
            • 1970-01-01
            • 2016-11-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多