Skip to content

Commit 8f703cc

Browse files
authored
Add snippets for XR alpha04 hands (#530)
* Add snippet that demonstrates how to detect a secondary hand * Add snippet to demonstrate how to detect a basic stop gesture
1 parent ce81ef6 commit 8f703cc

File tree

1 file changed

+37
-0
lines changed
  • xr/src/main/java/com/example/xr/arcore

1 file changed

+37
-0
lines changed

xr/src/main/java/com/example/xr/arcore/Hands.kt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.example.xr.arcore
1818

19+
import android.app.Activity
1920
import androidx.activity.ComponentActivity
2021
import androidx.lifecycle.lifecycleScope
2122
import androidx.xr.arcore.Hand
@@ -28,8 +29,10 @@ import androidx.xr.runtime.SessionConfigureSuccess
2829
import androidx.xr.runtime.math.Pose
2930
import androidx.xr.runtime.math.Quaternion
3031
import androidx.xr.runtime.math.Vector3
32+
import androidx.xr.runtime.math.toRadians
3133
import androidx.xr.scenecore.GltfModelEntity
3234
import androidx.xr.scenecore.scene
35+
import kotlinx.coroutines.flow.Flow
3336
import kotlinx.coroutines.launch
3437

3538
@Suppress("RestrictedApi") // b/416288516 - session.config and session.configure() are incorrectly restricted
@@ -65,6 +68,16 @@ fun ComponentActivity.collectHands(session: Session) {
6568
}
6669
}
6770

71+
fun secondaryHandDetection(activity: Activity, session: Session) {
72+
fun detectGesture(handState: Flow<Hand.State>) {}
73+
// [START androidxr_arcore_hand_handedness]
74+
val handedness = Hand.getHandedness(activity.contentResolver)
75+
val secondaryHand = if (handedness == Hand.Handedness.LEFT) Hand.right(session) else Hand.left(session)
76+
val handState = secondaryHand?.state ?: return
77+
detectGesture(handState)
78+
// [END androidxr_arcore_hand_handedness]
79+
}
80+
6881
fun ComponentActivity.renderPlanetAtHandPalm(leftHandState: Hand.State) {
6982
val session: Session = null!!
7083
val palmEntity: GltfModelEntity = null!!
@@ -106,3 +119,27 @@ fun ComponentActivity.renderPlanetAtFingerTip(rightHandState: Hand.State) {
106119
indexFingerEntity.setPose(Pose(position, rotation))
107120
// [END androidxr_arcore_hand_entityAtIndexFingerTip]
108121
}
122+
123+
private fun detectPinch(session: Session, handState: Hand.State): Boolean {
124+
// [START androidxr_arcore_hand_pinch_gesture]
125+
val thumbTip = handState.handJoints[HandJointType.THUMB_TIP] ?: return false
126+
val thumbTipPose = session.scene.perceptionSpace.transformPoseTo(thumbTip, session.scene.activitySpace)
127+
val indexTip = handState.handJoints[HandJointType.INDEX_TIP] ?: return false
128+
val indexTipPose = session.scene.perceptionSpace.transformPoseTo(indexTip, session.scene.activitySpace)
129+
return Vector3.distance(thumbTipPose.translation, indexTipPose.translation) < 0.05
130+
// [END androidxr_arcore_hand_pinch_gesture]
131+
}
132+
133+
private fun detectStop(session: Session, handState: Hand.State): Boolean {
134+
// [START androidxr_arcore_hand_stop_gesture]
135+
val threshold = toRadians(angleInDegrees = 30f)
136+
fun pointingInSameDirection(joint1: HandJointType, joint2: HandJointType): Boolean {
137+
val forward1 = handState.handJoints[joint1]?.forward ?: return false
138+
val forward2 = handState.handJoints[joint2]?.forward ?: return false
139+
return Vector3.angleBetween(forward1, forward2) < threshold
140+
}
141+
return pointingInSameDirection(HandJointType.INDEX_PROXIMAL, HandJointType.INDEX_TIP) &&
142+
pointingInSameDirection(HandJointType.MIDDLE_PROXIMAL, HandJointType.MIDDLE_TIP) &&
143+
pointingInSameDirection(HandJointType.RING_PROXIMAL, HandJointType.RING_TIP)
144+
// [END androidxr_arcore_hand_stop_gesture]
145+
}

0 commit comments

Comments
 (0)