hit-testを行って、3D オブジェクトがシーン内に正しく配置されているか確認します。正しく配置することで、AR コンテンツが適切な(見かけの)サイズでレンダリングされます。
ヒット結果のタイプ
ヒットテストでは、次の表に示すように、4 つの異なるタイプのヒット結果が生成されます。
ヒット結果のタイプ | 説明 | 向き | ユースケース | メソッド呼び出し |
---|---|---|---|---|
奥行き(DepthPoint ) |
シーン全体の奥行き情報を使用して、ポイントの正しい奥行きと向きを割り出します | 3D 表面に垂直 | 仮想オブジェクトを(床や壁だけでなく)任意の面に置く |
これを行うには、ArDepthMode を有効にする必要があります。Frame.hitTest(…) 、戻り値リストで DepthPoint を確認
|
Plane |
水平面または垂直面をヒットして、点の正しい深さと向きを決定します。 | 3D 表面に垂直 | 平面の完全なジオメトリを使用して平面(床または壁)にオブジェクトを配置します。すぐに適切なスケールが必要。Depth ヒットテストのフォールバック |
Frame.hitTest(…) 、戻りリストに Plane がないか確認します。
|
特徴(Point ) |
ユーザーがタップした位置周辺の視覚的な特徴に基づいて、ポイントの正しい位置と向きを判断します。 | 3D 表面に垂直 | 物体を(床や壁だけでなく)任意の面に置く |
Frame.hitTest(…) 、戻り値リストで Point を確認
|
インスタント プレースメント(InstantPlacementPoint ) |
画面スペースを使用してコンテンツを配置します。最初は、アプリが提供する推定深度を使用します。すぐに使用できますが、ARCore が実際のシーンのジオメトリを決定できるようになると、ポーズと実際の奥行きが変わります | 重力の反対の方向、上向き +Y | 迅速な配置が重要で、初期の深度とスケールが不明な場合に、プレーンの完全なジオメトリを使用してプレーン(床または壁)にオブジェクトを配置します。 |
Frame.hitTestInstantPlacement(float, float, float)
|
標準のヒットテストを行う
Frame.hitTest()
を呼び出してヒットテストを実行し、TapHelper
ユーティリティを使用して AR ビューから MotionEvent
を取得します。
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.
}
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
にフォーカスする場合は、次のようにします。
// 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;
}
}
// 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
に関連付けられるようにします。たとえば、平面ヒットの結果では、検出された平面にアンカーが付加されたままになるため、現実世界の一部であるかのように見えます。
次のステップ
- GitHub で
hello_ar_java
とhello_ar_kotlin
のサンプルアプリを確認する。