From fa2bce89ce572e3c2041c6899206a8339078439a Mon Sep 17 00:00:00 2001 From: Dereck Bridie Date: Wed, 7 May 2025 16:22:59 +0200 Subject: [PATCH 1/2] Add snippet that demonstrates how to detect a secondary hand --- xr/src/main/java/com/example/xr/arcore/Hands.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/xr/src/main/java/com/example/xr/arcore/Hands.kt b/xr/src/main/java/com/example/xr/arcore/Hands.kt index af3a547b0..8e90b735a 100644 --- a/xr/src/main/java/com/example/xr/arcore/Hands.kt +++ b/xr/src/main/java/com/example/xr/arcore/Hands.kt @@ -16,6 +16,7 @@ package com.example.xr.arcore +import android.app.Activity import androidx.activity.ComponentActivity import androidx.lifecycle.lifecycleScope import androidx.xr.arcore.Hand @@ -30,6 +31,7 @@ import androidx.xr.runtime.math.Quaternion import androidx.xr.runtime.math.Vector3 import androidx.xr.scenecore.GltfModelEntity import androidx.xr.scenecore.scene +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch @Suppress("RestrictedApi") // b/416288516 - session.config and session.configure() are incorrectly restricted @@ -65,6 +67,16 @@ fun ComponentActivity.collectHands(session: Session) { } } +fun secondaryHandDetection(activity: Activity, session: Session) { + fun detectGesture(handState: Flow) {} + // [START androidxr_arcore_hand_handedness] + val handedness = Hand.getHandedness(activity.contentResolver) + val secondaryHand = if (handedness == Hand.Handedness.LEFT) Hand.right(session) else Hand.left(session) + val handState = secondaryHand?.state ?: return + detectGesture(handState) + // [END androidxr_arcore_hand_handedness] +} + fun ComponentActivity.renderPlanetAtHandPalm(leftHandState: Hand.State) { val session: Session = null!! val palmEntity: GltfModelEntity = null!! From 58677d5e2629bd6518598881652b5e691b187aac Mon Sep 17 00:00:00 2001 From: Dereck Bridie Date: Wed, 7 May 2025 17:06:02 +0200 Subject: [PATCH 2/2] Add snippet to demonstrate how to detect a basic stop gesture --- .../main/java/com/example/xr/arcore/Hands.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/xr/src/main/java/com/example/xr/arcore/Hands.kt b/xr/src/main/java/com/example/xr/arcore/Hands.kt index 8e90b735a..13346b202 100644 --- a/xr/src/main/java/com/example/xr/arcore/Hands.kt +++ b/xr/src/main/java/com/example/xr/arcore/Hands.kt @@ -29,6 +29,7 @@ import androidx.xr.runtime.SessionConfigureSuccess import androidx.xr.runtime.math.Pose import androidx.xr.runtime.math.Quaternion import androidx.xr.runtime.math.Vector3 +import androidx.xr.runtime.math.toRadians import androidx.xr.scenecore.GltfModelEntity import androidx.xr.scenecore.scene import kotlinx.coroutines.flow.Flow @@ -118,3 +119,27 @@ fun ComponentActivity.renderPlanetAtFingerTip(rightHandState: Hand.State) { indexFingerEntity.setPose(Pose(position, rotation)) // [END androidxr_arcore_hand_entityAtIndexFingerTip] } + +private fun detectPinch(session: Session, handState: Hand.State): Boolean { + // [START androidxr_arcore_hand_pinch_gesture] + 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 + // [END androidxr_arcore_hand_pinch_gesture] +} + +private fun detectStop(session: Session, handState: Hand.State): Boolean { + // [START androidxr_arcore_hand_stop_gesture] + 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) + // [END androidxr_arcore_hand_stop_gesture] +}