دمج موضع الرأس في تطبيقك باستخدام ARCore for Jetpack XR

بعد أن يمنح المستخدم إذنًا بتتبُّع حركة الرأس، يمكن لتطبيقك استرداد معلومات وضع الرأس من خلال ARCore for Jetpack XR. يمكن أن تساعد معلومات وضعية الرأس تطبيقك في إنشاء تجارب أكثر سهولة، مثل نافذة تتبع مجال رؤية المستخدم.

إنشاء جلسة ARCore لـ 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
}

استخدامات تتبُّع حركة الرأس

إحدى الطرق التي يمكن أن يستخدم بها تطبيقك ميزة تتبُّع حركة الرأس هي إبقاء العناصر ضمن مجال رؤية المستخدم، وذلك في التطبيقات التي تتطلّب من المستخدمين النظر إلى محيطهم أو التحرّك فيه.

تجنَّب استخدام عناصر ثابتة في مجال رؤية المستخدم لأنّ ذلك قد يؤدي إلى الشعور بدوار الحركة. بدلاً من ذلك، استخدِم حركة الكائنات التي تتبع رأس المستخدم بعد فترة قصيرة:

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
        }
    }
}