检测带有 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 对象的主要内容,如果未能解决你的问题,请参考以下文章