يمكن أن يوفّر ARCore for Jetpack XR معلومات عن الأيدي التي تم رصدها للمستخدم، ويقدّم معلومات عن وضعيات الأيدي والمفاصل المرتبطة بها. يمكن استخدام بيانات اليد هذه لربط الكيانات والنماذج بأيدي المستخدم، مثل قائمة الأدوات:
الحصول على جلسة
الوصول إلى معلومات اليد من خلال Session
Android XR اطّلِع على فهم دورة حياة الجلسة للحصول على Session
.
ضبط الجلسة
لا يتم تفعيل ميزة "تتبُّع اليد" تلقائيًا في جلسات XR. لتلقّي بيانات اليد،
اضبط الجلسة واضبط وضع HandTrackingMode.BOTH
:
val newConfig = session.config.copy( handTracking = Config.HandTrackingMode.BOTH ) when (val result = session.configure(newConfig)) { is SessionConfigureConfigurationNotSupported -> TODO(/* Some combinations of configurations are not valid. Handle this failure case. */) is SessionConfigureSuccess -> TODO(/* Success! */) else -> TODO(/* A different unhandled exception was thrown. */) }
استرداد بيانات اليد
تتوفّر بيانات اليدين بشكل منفصل لكل من اليد اليسرى واليد اليمنى. استخدِم state
في كل يد للوصول إلى مواضع الوضعيات لكل مفصل:
Hand.left(session)?.state?.collect { handState -> // or Hand.right(session) // Hand state has been updated. // Use the state of hand joints to update an entity's position. renderPlanetAtHandPalm(handState) }
تتضمّن الأيدي السمات التالية:
-
trackingState
: ما إذا كان يتم تتبُّع اليد أم لا
handJoints
: خريطة لمفاصل اليد إلى أوضاع يتم تحديد وضعيات مفاصل اليد وفقًا لمعايير OpenXR.
استخدام بيانات اليد في تطبيقك
يمكن استخدام مواضع مفاصل يد المستخدم لتثبيت عناصر ثلاثية الأبعاد على يدي المستخدم، مثلاً لربط نموذج براحة اليد اليسرى:
val palmPose = leftHandState.handJoints[HandJointType.PALM] ?: return // the down direction points in the same direction as the palm val angle = Vector3.angleBetween(palmPose.rotation * Vector3.Down, Vector3.Up) palmEntity.setEnabled(angle > Math.toRadians(40.0)) val transformedPose = session.scene.perceptionSpace.transformPoseTo( palmPose, session.scene.activitySpace, ) val newPosition = transformedPose.translation + transformedPose.down * 0.05f palmEntity.setPose(Pose(newPosition, transformedPose.rotation))
أو لإرفاق نموذج بطرف إصبع السبابة في يدك اليمنى:
val tipPose = rightHandState.handJoints[HandJointType.INDEX_TIP] ?: return // the forward direction points towards the finger tip. val angle = Vector3.angleBetween(tipPose.rotation * Vector3.Forward, Vector3.Up) indexFingerEntity.setEnabled(angle > Math.toRadians(40.0)) val transformedPose = session.scene.perceptionSpace.transformPoseTo( tipPose, session.scene.activitySpace, ) val position = transformedPose.translation + transformedPose.forward * 0.03f val rotation = Quaternion.fromLookTowards(transformedPose.up, Vector3.Up) indexFingerEntity.setPose(Pose(position, rotation))
رصد إيماءات اليد الأساسية
استخدام أوضاع المفاصل في اليد لرصد إيماءات اليد الأساسية راجِع اتفاقيات مفاصل اليد لتحديد نطاق الوضعيات التي يجب أن تكون فيها المفاصل ليتم تسجيلها كوضعية معيّنة.
على سبيل المثال، لرصد عملية الضغط بالإبهام والسبابة، استخدِم المسافة بين مفصلَي الإصبعَين:
val thumbTip = handState.handJoints[HandJointType.THUMB_TIP] ?: return false val thumbTipPose = session.scene.perceptionSpace.transformPoseTo(thumbTip, session.scene.activitySpace) val indexTip = handState.handJoints[HandJointType.INDEX_TIP] ?: return false val indexTipPose = session.scene.perceptionSpace.transformPoseTo(indexTip, session.scene.activitySpace) return Vector3.distance(thumbTipPose.translation, indexTipPose.translation) < 0.05
من الأمثلة على الإيماءات الأكثر تعقيدًا إيماءة "التوقّف". في هذه الإيماءة، يجب أن تكون كل الأصابع ممدودة، أي يجب أن تشير كل مفاصل كل إصبع إلى الاتجاه نفسه تقريبًا:
val threshold = toRadians(angleInDegrees = 30f) fun pointingInSameDirection(joint1: HandJointType, joint2: HandJointType): Boolean { val forward1 = handState.handJoints[joint1]?.forward ?: return false val forward2 = handState.handJoints[joint2]?.forward ?: return false return Vector3.angleBetween(forward1, forward2) < threshold } return pointingInSameDirection(HandJointType.INDEX_PROXIMAL, HandJointType.INDEX_TIP) && pointingInSameDirection(HandJointType.MIDDLE_PROXIMAL, HandJointType.MIDDLE_TIP) && pointingInSameDirection(HandJointType.RING_PROXIMAL, HandJointType.RING_TIP)
يُرجى مراعاة النقاط التالية عند تطوير عملية رصد مخصّصة لإيماءات اليد:
- قد يفسّر المستخدمون أي إيماءة معيّنة بشكل مختلف. على سبيل المثال، قد يرى البعض أنّ إشارة "التوقف" تتطلّب فرد الأصابع، بينما قد يجد البعض الآخر أنّ ضمّ الأصابع إلى بعضها أكثر سهولة.
- قد يكون من الصعب الحفاظ على بعض الإيماءات. استخدِم إيماءات بديهية لا تسبّب إجهادًا ليدي المستخدم.
تحديد اليد الثانوية للمستخدم
يضع نظام التشغيل Android عناصر التنقّل في النظام في يد المستخدم الأساسية، وذلك وفقًا لما يحدّده المستخدم في الإعدادات المفضّلة للنظام. استخدِم اليد الثانوية لتنفيذ الإيماءات المخصّصة لتجنُّب التعارض مع إيماءات التنقّل في النظام:
val handedness = Hand.getPrimaryHandSide(activity.contentResolver) val secondaryHand = if (handedness == Hand.HandSide.LEFT) Hand.right(session) else Hand.left(session) val handState = secondaryHand?.state ?: return detectGesture(handState)
OpenXR™ وشعار OpenXR هما علامتان تجاريتان مملوكتان لشركة The Khronos Group Inc. ومسجّلتان كعلامة تجارية في الصين والاتحاد الأوروبي واليابان والمملكة المتحدة.