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

أجهزة XR المعنيّة
تساعدك هذه الإرشادات في إنشاء تجارب لهذه الأنواع من أجهزة الواقع الممتد.
سماعات رأس بنظام الواقع الممتد
نظارات الواقع الممتد السلكية

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

إنشاء جلسة ARCore لـ Jetpack XR

الحصول على معلومات عن وضع الرأس من خلال Session Jetpack XR Runtime، الذي يمكن لتطبيقك إنشاؤه

ضبط الجلسة

لا يتم تفعيل تتبُّع حركة الرأس تلقائيًا في جلسات 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
        }
    }
}