在您的 Android 应用中执行点击测试

执行命中测试,以确定 3D 对象在场景中的正确位置。正确的放置可确保 AR 内容以适当的(表观)尺寸呈现。

命中结果类型

一项命中测试可产生四种不同类型的命中结果,如下表所示。

命中结果类型 说明 方向 使用场景 方法调用
深度 (DepthPoint) 使用来自整个场景的深度信息来确定点的正确深度和方向 与 3D 表面垂直 将虚拟对象放置在任意表面(不只是地板和墙壁)上 必须启用ArDepthMode才能使用此功能。

Frame.hitTest(…),请检查返回列表中是否有 DepthPoint
Plane 敲击水平和/或垂直表面,以确定点的正确深度和方向 与 3D 表面垂直 使用平面的完整几何图形将对象放置在平面(地板或墙壁)上。需要立即更正体重。深度点击测试的回退 Frame.hitTest(…),检查返回列表中是否有 Plane
特征点 (Point) 依靠用户点按点周围的视觉特征来确定点的正确位置和方向 与 3D 表面垂直 将对象放在任意表面上(不仅限于地板和墙壁) Frame.hitTest(…),检查返回列表中是否有 Point
即时展示位置 (InstantPlacementPoint) 使用屏幕空间来放置内容。最初使用应用提供的估算深度。可立即运作,但一旦 ARCore 能够确定实际场景几何图形,姿势和实际深度就会发生变化 +Y 指向上方,与重力相反 使用平面的完整几何体将对象放置在平面(地板或墙壁)上,并且快速放置至关重要,并且体验可以容忍未知的初始深度和缩放 Frame.hitTestInstantPlacement(float, float, float)

执行标准点击测试

调用 Frame.hitTest() 以执行点击测试,使用 TapHelper 实用程序从 AR 视图中获取 MotionEvent

Java

MotionEvent tap = tapHelper.poll();
if (tap == null) {
  return;
}

if (usingInstantPlacement) {
  // When using Instant Placement, the value in APPROXIMATE_DISTANCE_METERS will determine
  // how far away the anchor will be placed, relative to the camera's view.
  List<HitResult> hitResultList =
      frame.hitTestInstantPlacement(tap.getX(), tap.getY(), APPROXIMATE_DISTANCE_METERS);
  // Hit-test results using Instant Placement will only have one result of type
  // InstantPlacementResult.
} else {
  List<HitResult> hitResultList = frame.hitTest(tap);
  // TODO: Filter hitResultList to find a hit result of interest.
}

Kotlin

val tap = tapHelper.poll() ?: return
val hitResultList =
  if (usingInstantPlacement) {
    // When using Instant Placement, the value in APPROXIMATE_DISTANCE_METERS will determine
    // how far away the anchor will be placed, relative to the camera's view.
    frame.hitTestInstantPlacement(tap.x, tap.y, APPROXIMATE_DISTANCE_METERS)
    // Hit-test results using Instant Placement will only have one result of type
    // InstantPlacementResult.
  } else {
    frame.hitTest(tap)
  }

您可以根据您感兴趣的类型过滤命中结果。例如,如果您希望专注于 DepthPoint

Java

// Returned hit-test results are sorted by increasing distance from the camera or virtual ray's
// origin.
// The first hit result is often the most relevant when responding to user input.
for (HitResult hit : hitResultList) {
  Trackable trackable = hit.getTrackable();
  if (trackable instanceof DepthPoint) { // Replace with any type of trackable type
    // Do something with this hit result. For example, create an anchor at this point of
    // interest.
    Anchor anchor = hit.createAnchor();
    // TODO: Use this anchor in your AR experience.
    break;
  }
}

Kotlin

// Returned hit-test results are sorted by increasing distance from the camera or virtual ray's
// origin.
// The first hit result is often the most relevant when responding to user input.
val firstHitResult =
  hitResultList.firstOrNull { hit ->
    when (val trackable = hit.trackable!!) {
      is DepthPoint -> true // Replace with any type of trackable type
      else -> false
    }
  }
if (firstHitResult != null) {
  // Do something with this hit result. For example, create an anchor at this point of interest.
  val anchor = firstHitResult.createAnchor()
  // TODO: Use this anchor in your AR experience.
}

使用任意射线和方向进行点击测试

点击测试通常被视为来自设备或设备相机的光线,但您可以使用 Frame.hitTest(float[], int, float[], int),通过在世界空间坐标中使用任意光线(而非屏幕空间点)来执行点击测试。

使用命中结果创建锚点

获得命中结果后,您可以使用其姿势作为输入,在场景中放置 AR 内容。使用 HitResult.createAnchor() 创建新的 Anchor,确保相应内容附加到命中结果的底层 Trackable 中。例如,对于平面命中结果,锚点将保持附加到检测到的平面上,因此看起来就像现实世界的一部分。

后续步骤