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

執行 hit-test 以確定 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。舉例來說,在偵測到飛機命中時,錨點會保持附在偵測到的平面上,因此出現在真實世界中。

後續步驟