在 Android 應用程式中執行命中測試

執行命中測試,判斷 3D 物件在場景中的正確位置。正確放置 AR 內容可確保 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。舉例來說,當飛機命中結果時,錨點會保持與偵測到的飛機保持連接,因此看起來是真實世界的一部分。

後續步驟