Jetpack XR-এর জন্য ARCore ব্যবহার করে হাতের মাধ্যমে কাজ করা

প্রযোজ্য XR ডিভাইস
এইসব XR ডিভাইসের জন্য অভিজ্ঞতা তৈরি করতে এই নির্দেশিকা আপনাকে সাহায্য করে।
XR হেডসেট
ওয়্যারড XR গ্লাস

Jetpack XR-এর জন্য ARCore ব্যবহারকারীর শনাক্ত করা হাত সম্পর্কে তথ্য প্রদান করতে পারে, এবং হাত ও তার সাথে যুক্ত জয়েন্ট সম্পর্কে পোজ সংক্রান্ত তথ্য দেয়। এই হাতের ডেটা ব্যবহারকারীর হাতে এন্টিটি ও মডেল অ্যাটাচ করতে ব্যবহার করা যেতে পারে, যেমন, টুল মেনু:

সেশন অ্যাক্সেস করা

Jetpack XR Runtime Session-এর মাধ্যমে হাতের তথ্য অ্যাক্সেস করুন, যা আপনার অ্যাপ তৈরি করতে পারে।

সেশন কনফিগার করা

XR সেশনে ডিফল্ট হিসেবে হ্যান্ড ট্র্যাকিং চালু থাকে না। হ্যান্ড ডেটা পেতে, সেশন কনফিগার করুন এবং HandTrackingMode.BOTH মোড সেট করুন:

val newConfig = Config.Builder(session.config)
    .setHandTracking(HandTrackingMode.BOTH)
    .build()
when (val result = session.configure(newConfig)) {
    is SessionConfigureSuccess -> TODO(/* Success! */)
    else ->
        TODO(/* The session could not be configured. See SessionConfigureResult for possible causes. */)
}

হ্যান্ড ডেটা ফিরিয়ে আনা

বাঁ ও ডান হাতের ডেটা আলাদাভাবে উপলভ্য। প্রতিটি জয়েন্টের জন্য পোজ পজিশন অ্যাক্সেস করতে, প্রতিটি হাতের 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 স্ট্যান্ডার্ড অনুযায়ী হাতের জয়েন্ট পোজ নির্দিষ্ট করা হয়।

আপনার অ্যাপে হাতের ডেটা ব্যবহার করা

ব্যবহারকারীর হাতের জয়েন্টের পজিশন 3D অবজেক্টকে অ্যাঙ্কর করতে ব্যবহার করা যেতে পারে, যেমন, কোনও মডেলকে বাঁ হাতের তালুতে অ্যাটাচ করতে:

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 == HandSide.LEFT) Hand.right(session) else Hand.left(session)
detectGesture(secondaryHand.state)


OpenXR™ এবং OpenXR লোগো হল The Khronos Group Inc.-এর মালিকানাধীন ট্রেডমার্ক এবং এগুলি চীন, ইউরোপীয় ইউনিয়ন, জাপান ও যুক্তরাজ্যে ট্রেডমার্ক হিসেবে রেজিস্টার করা আছে।