ARCore for Jetpack XR を使用してアプリに頭の位置を組み込む

ユーザーがヘッド トラッキングの権限を付与すると、アプリは ARCore for Jetpack XR を通じて頭部のポーズ情報を取得できるようになります。頭の向きの情報は、ユーザーの視野に追従するウィンドウなど、より直感的なエクスペリエンスをアプリで作成するのに役立ちます。

ARCore for Jetpack XR セッションを作成する

ARCore for Jetpack XR セッションを通じて頭のポーズ情報を取得します。Session を取得するには、セッションのライフサイクルを理解するをご覧ください。

セッションを構成する

XR セッションでは、ヘッド トラッキングはデフォルトで有効になっていません。ヘッド トラッキングを有効にするには、セッションを構成して HeadTrackingMode.LAST_KNOWN モードを設定します。

val newConfig = session.config.copy(
    headTracking = Config.HeadTrackingMode.LAST_KNOWN,
)
when (val result = session.configure(newConfig)) {
    is SessionConfigureSuccess -> TODO(/* Success! */)
    is SessionConfigureConfigurationNotSupported ->
        TODO(/* Some combinations of configurations are not valid. Handle this failure case. */)

    else ->
        TODO(/* The session could not be configured. See SessionConfigureResult for possible causes. */)
}

ヘッドポーズ データを取得する

ヘッドポーズ データは RenderViewpoint を介して公開されます。RenderViewpoint は、デバイスの特定の視点のポーズと視野を表します。デバイスの機能に応じて、左、右、モノラル ビューポイントを設定できます。

モノラル ビューポイントのデータを取得するには:

val mono = RenderViewpoint.mono(session) ?: return
mono.state.collect { state ->
    val fov = state.fieldOfView
    val viewpointPose = state.pose
}

ヘッド トラッキングの応用

ヘッド トラッキングのアプリでの使用方法の 1 つは、ユーザーが周囲を見回したり移動したりする必要があるアプリで、エンティティをユーザーの視野内に維持することです。

ユーザーの視野内でヘッドロックされたエンティティを使用すると、乗り物酔いを引き起こす可能性があるため、使用しないでください。代わりに、ユーザーの頭の動きに少し遅れて追従するエンティティの動きを使用します。

val viewpointPose = RenderViewpoint.left(session)!!.state
lifecycleScope.launch {
    while (true) {
        delay(2000)
        val start = panel.getPose()
        val startTime = session.state.value.timeMark

        val pose = session.scene.perceptionSpace.transformPoseTo(
            viewpointPose.value.pose,
            session.scene.activitySpace
        )
        val target = Pose(pose.translation + pose.forward * 1f, pose.rotation)
        while (true) {
            val ratio =
                (session.state.value.timeMark - startTime).inWholeMilliseconds / 500f
            panel.setPose(Pose.lerp(start, target, ratio))
            if (ratio > 1f) break
        }
    }
}