检测带有 ARCore 的点击事件是不是击中了已添加的 3d 对象

Posted

技术标签:

【中文标题】检测带有 ARCore 的点击事件是不是击中了已添加的 3d 对象【英文标题】: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 对象?

【问题讨论】:

【参考方案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....

 

【讨论】:

以上是关于检测带有 ARCore 的点击事件是不是击中了已添加的 3d 对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ARCore Android 中禁用表面检测

总结一下今天做的unity面试题:刚体的点击事件

在 viewpager 中检测触摸/点击事件

没有平面的 ARCore 对象跟踪

如何使用带有arcore的Android获取以mm为单位的真实图片尺寸

击中断点时鼠标冻结/滞后