|
| 1 | +# Hand Tracking Profile |
| 2 | + |
| 3 | +The _Hand Tracking profile_ is found under the _Input System profile_. It contains settings for customizing hand representation. |
| 4 | + |
| 5 | +<a target="_blank" href="../../External/Documentation/Images/MRTK_Core_Input_Hands_HandTrackingProfile.png"> |
| 6 | + <img src="../../External/Documentation/Images/MRTK_Core_Input_Hands_HandTrackingProfile.png" title="Hand Tracking Profile" width="50%" class="center" /> |
| 7 | +</a> |
| 8 | + |
| 9 | +## Joint Prefabs |
| 10 | + |
| 11 | +Joint prefabs are visualized using simple prefabs. The _Palm_ and _Index Finger_ joints are of special importance and have their own prefab, while all other joints share the same prefab. |
| 12 | + |
| 13 | +By default the hand joint prefabs are simple geometric primitives. These can be replaced if desired. If no prefab is specified at all, empty [GameObjects](href:https://docs.unity3d.com/ScriptReference/GameObject.html) are created instead. |
| 14 | + |
| 15 | +| Warning: Avoid using complex scripts or expensive rendering in joint prefabs, since joint objects are transformed on every frame and can have significant performance cost! | |
| 16 | +| --- | |
| 17 | + |
| 18 | +<a target="_blank" href="../../External/Documentation/Images/MRTK_Core_Input_Hands_JointVisualizerPrefabs.png"> |
| 19 | + <img src="../../External/Documentation/Images/MRTK_Core_Input_Hands_JointVisualizerPrefabs.png" title="Hand Joint Visualizers" width="50%" class="center" /> |
| 20 | +</a> |
| 21 | + |
| 22 | +## Hand Mesh Prefab |
| 23 | + |
| 24 | +The hand mesh is used if fully defined mesh data is provided by the hand tracking device. The mesh renderable in the prefab is replaced by data from the device, so a dummy mesh such as a cube is sufficient. The material of the prefab is used for the hand mesh. |
| 25 | + |
| 26 | +<a target="_blank" href="../../External/Documentation/Images/MRTK_Core_Input_Hands_ArticulatedHandMesh.png"> |
| 27 | + <img src="../../External/Documentation/Images/MRTK_Core_Input_Hands_ArticulatedHandMesh.png" title="Full Hand Mesh" width="50%" class="center" /> |
| 28 | +</a> |
| 29 | + |
| 30 | +Hand mesh display can have a noticeable performance impact, for this reason it can be disabled entirely using the _Enable Hand Mesh Updates_ option. |
| 31 | + |
| 32 | +# Scripting |
| 33 | + |
| 34 | +Position and rotation can be requested from the input system for each individual hand joint as a [MixedRealityPose](xref:Microsoft.MixedReality.Toolkit.Utilities.MixedRealityPose). |
| 35 | + |
| 36 | +Alternatively we also have access to [GameObjects](https://docs.unity3d.com/ScriptReference/GameObject.html) that follow the joints. This can be useful if another GameObject should track a joint continuously. |
| 37 | + |
| 38 | +| Note: Joint object are destroyed when hand tracking is lost! Make sure that any scripts using the joint object handle the `null` case gracefully to avoid errors! | |
| 39 | +| --- | |
| 40 | + |
| 41 | +Available joints are listed in the [TrackedHandJoint](xref:Microsoft.MixedReality.Toolkit.Utilities.TrackedHandJoint) enum. |
| 42 | + |
| 43 | +## Accessing a given Hand Controller |
| 44 | + |
| 45 | +A specific hand controller is often available, e.g. when handling input events. In this case the joint data can be requested directly from the device, using the [IMixedRealityHand](xref:Microsoft.MixedReality.Toolkit.Input.IMixedRealityHand) interface. |
| 46 | + |
| 47 | +### Polling Joint Pose from Controller |
| 48 | + |
| 49 | +<!-- [TryGetJoint](xref:Microsoft.MixedReality.Toolkit.Input.IMixedRealityHand.TryGetJoint(TrackedHandJoint, MixedRealityPose)) --> |
| 50 | +The [TryGetJoint](xref:Microsoft.MixedReality.Toolkit.Input.IMixedRealityHand.TryGetJoint*) function returns `false` if the requested joint is not available for some reason. In that case the resulting pose will be [MixedRealityPose.ZeroIdentity](xref:Microsoft.MixedReality.Toolkit.Utilities.MixedRealityPose.ZeroIdentity). |
| 51 | + |
| 52 | +```csharp |
| 53 | +public void OnSourceDetected(SourceStateEventData eventData) |
| 54 | +{ |
| 55 | + var hand = eventData.Controller as IMixedRealityHand; |
| 56 | + if (hand != null) |
| 57 | + { |
| 58 | + if (hand.TryGetJoint(TrackedHandJoint.IndexTip, out MixedRealityPose jointPose) |
| 59 | + { |
| 60 | + // ... |
| 61 | + } |
| 62 | + } |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +### Joint Transform from Hand Visualizer |
| 67 | + |
| 68 | +Joint objects can be requested from the [controller visualizer](xref:Microsoft.MixedReality.Toolkit.Input.IMixedRealityController.Visualizer). |
| 69 | + |
| 70 | +```csharp |
| 71 | +public void OnSourceDetected(SourceStateEventData eventData) |
| 72 | +{ |
| 73 | + var handVisualizer = eventData.Controller.Visualizer as IMixedRealityHandVisualizer; |
| 74 | + if (handVisualizer != null) |
| 75 | + { |
| 76 | + if (handVisualizer.TryGetJointTransform(TrackedHandJoint.IndexTip, out Transform jointTransform) |
| 77 | + { |
| 78 | + // ... |
| 79 | + } |
| 80 | + } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +## Simplified joint data access |
| 85 | + |
| 86 | +If no specific controller is given then utility classes are provided for convenient access to hand joint data. These functions request joint data from the first available hand device currently tracked. |
| 87 | + |
| 88 | +### Polling Joint Pose from HandJointUtils |
| 89 | + |
| 90 | +[HandJointUtils](xref:Microsoft.MixedReality.Toolkit.Input.HandJointUtils) is a static class that queries the first active hand device. |
| 91 | + |
| 92 | +```csharp |
| 93 | + if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose pose)) |
| 94 | + { |
| 95 | + // ... |
| 96 | + } |
| 97 | +``` |
| 98 | + |
| 99 | +### Joint Transform from Hand Joint Service |
| 100 | + |
| 101 | +[IMixedRealityHandJointService](xref:Microsoft.MixedReality.Toolkit.Input.IMixedRealityHandJointService) keeps a persistent set of [GameObjects](https://docs.unity3d.com/ScriptReference/GameObject.html) for tracking joints. |
| 102 | +
|
| 103 | +```csharp |
| 104 | + var handJointService = MixedRealityToolkit.Instance.GetService<IMixedRealityHandJointService>(); |
| 105 | + if (handJointService != null) |
| 106 | + { |
| 107 | + Transform jointTransform = handJointService.RequestJointTransform(TrackedHandJoint.IndexTip, Handedness.Right); |
| 108 | + // ... |
| 109 | + } |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +## Hand Tracking Events |
| 114 | + |
| 115 | +<!-- The Input Simulation Service emulates the behaviour of devices and platforms that may not be available in the Unity editor. Examples include: |
| 116 | +* Hololens or VR device head tracking |
| 117 | +* Hololens version 1 hand gestures |
| 118 | +* Hololens version 2 articulated hand tracking |
| 119 | + |
| 120 | +Users can use a conventional keyboard and mouse combination to control simulated devices at runtime. This allows testing of interactions in the Unity editor without first deploying to a device. |
| 121 | + |
| 122 | +## Enabling the Input Simulation Service |
| 123 | + |
| 124 | +Input simulation is enabled by default in MRTK. |
| 125 | + |
| 126 | +Input simulation is an optional [Mixed Reality service](../../External/Documentation/MixedRealityServices.md). It can be added as a data provider in the [Input System profile](../TODO.md). |
| 127 | +* __Type__ must be _Microsoft.MixedReality.Toolkit.Input > InputSimulationService_. |
| 128 | +* __Platform(s)__ should always be _Windows Editor_ since the service depends on keyboard and mouse input. |
| 129 | +* __Profile__ has all settings for input simulation. |
| 130 | + |
| 131 | + | __Warning__: Any type of profile can be assigned to services at the time of this writing. If you assign a different profile to the service, make sure to use a profile of type _Input Simulation_ or it will not work! | |
| 132 | + | --- | |
| 133 | + |
| 134 | + |
| 135 | + |
| 136 | +Open the linked profile to access settings for input simulation. |
| 137 | + |
| 138 | + |
| 139 | + |
| 140 | +# Camera Control |
| 141 | + |
| 142 | +Head movement can be emulated by the Input Simulation Service. |
| 143 | + |
| 144 | + |
| 145 | + |
| 146 | +## Rotating the camera |
| 147 | + |
| 148 | +1. Hover over the viewport editor window. |
| 149 | + |
| 150 | + _You may need to click the window to give it input focus if button presses don't work._ |
| 151 | + |
| 152 | +2. Press and hold the __Mouse Look Button__ (default: Right mouse button). |
| 153 | +3. Move the mouse in the viewport window to rotate the camera. |
| 154 | + |
| 155 | +## Moving the camera |
| 156 | + |
| 157 | +Press and hold the movement keys (W/A/S/D for forward/left/back/right). |
| 158 | + |
| 159 | +--- |
| 160 | + |
| 161 | +<video width="600" controls="controls"> |
| 162 | + <source type="video/mp4" src="../../External/Documentation/Videos/MRTK_InputSimulation_CameraControl.mp4"></source> |
| 163 | +</video> |
| 164 | + |
| 165 | +# Hand Simulation |
| 166 | + |
| 167 | +The input simulation supports emulated hand devices. These virtual hands can interact with any object that supports regular hand devices, such as buttons or grabable objects. |
| 168 | + |
| 169 | + |
| 170 | + |
| 171 | +The __Hand Simulation Mode__ switches between two distinct input models. |
| 172 | + |
| 173 | +* _Articulated Hands_: Simulates a fully articulated hand device with joint position data. |
| 174 | + |
| 175 | + Emulates Hololens version 2 interaction model. |
| 176 | + |
| 177 | + Interactions that are based precise positioning of the hand or use touching can be simulated in this mode. |
| 178 | + |
| 179 | +* _Gestures_: Simulates a simplified hand model with air tap and basic gestures. |
| 180 | + |
| 181 | + Emulates [Hololens version 1 interaction model](https://docs.microsoft.com/en-us/windows/mixed-reality/gestures). |
| 182 | +
|
| 183 | + Focus is controlled using the Gaze pointer. The _Air Tap_ gesture is used to interact with buttons. |
| 184 | + |
| 185 | +## Controlling hand movement |
| 186 | + |
| 187 | + |
| 188 | + |
| 189 | +Press and hold the _Left/Right Hand Manipulation Key_ (default: Left Shift/Space for left/right respectively) to gain control of either hand. While the manipulation key is pressed, the hand will appear in the viewport. Mouse movement will move the hand in the view plane. |
| 190 | + |
| 191 | +Once the manipulation key is released the hands will disappear after a short _Hand Hide Timeout_. To toggle hands on permanently, press the _Toggle Left/Right Hand Key_ (default: T/Y for left/right respectively). Press the toggle key again to hide the hands again. |
| 192 | + |
| 193 | + |
| 194 | + |
| 195 | +Hands can be moved further or closer to the camera using the _mouse wheel_. |
| 196 | + |
| 197 | + |
| 198 | + |
| 199 | +Hands can be rotated when precise direction is required. |
| 200 | +* Yaw rotates around the Y axis (default: E/Q keys for clockwise/counter-clockwise rotation) |
| 201 | +* Pitch rotates around the X axis (default: F/R keys for clockwise/counter-clockwise rotation) |
| 202 | +* Roll rotates around the Z axis (default: X/Z keys for clockwise/counter-clockwise rotation) |
| 203 | + |
| 204 | +--- |
| 205 | + |
| 206 | +<video width="600" controls="controls"> |
| 207 | + <source type="video/mp4" src="../../External/Documentation/Videos/MRTK_InputSimulation_HandMovement.mp4"></source> |
| 208 | +</video> |
| 209 | + |
| 210 | +## Hand Gestures |
| 211 | + |
| 212 | +Hand gestures such as pinching, grabbing, poking, etc. can also be simulated. |
| 213 | + |
| 214 | + |
| 215 | + |
| 216 | +1. First enable hand control using the manipulation keys (Left Shift/Space) |
| 217 | + |
| 218 | + Alternatively toggle the hands on/off using the toggle keys (T/Y). |
| 219 | + |
| 220 | +2. While manipulating, press and hold a mouse button to perform a hand gesture. |
| 221 | + |
| 222 | +Each of the mouse buttons can be mapped to transform the hand shape into a different gesture using the _Left/Middle/Right Mouse Hand Gesture_ settings. The _Default Hand Gesture_ is the shape of the hand when no button is pressed. |
| 223 | + |
| 224 | +| Note: The _Pinch_ gesture is the only gesture that performs the "Select" action at this point. | |
| 225 | +| --- | |
| 226 | + |
| 227 | +## One-Hand Manipulation |
| 228 | + |
| 229 | +1. Press and hold hand control key (Space/Left Shift) |
| 230 | +2. Point at object |
| 231 | +3. Hold mouse button to pinch |
| 232 | +4. Use mouse to move the object |
| 233 | +5. Release mouse button to stop interaction |
| 234 | + |
| 235 | +--- |
| 236 | + |
| 237 | +<video width="600" controls="controls"> |
| 238 | + <source type="video/mp4" src="../../External/Documentation/Videos/MRTK_InputSimulation_OneHandManipulation.mp4"></source> |
| 239 | +</video> |
| 240 | + |
| 241 | +## Two-Hand Manipulation |
| 242 | + |
| 243 | +For manipulating objects with two hands at the same time the persistent hand mode is recommended. |
| 244 | + |
| 245 | +1. Toggle on both hands by pressing the toggle keys (T/Y). |
| 246 | +2. Manipulate one hand at a time: |
| 247 | + 1. Hold _Space_ to control the right hand |
| 248 | + 2. Move the hand to where you want to grab the object |
| 249 | + 3. Press mouse button to activate the _Pinch_ gesture. In persistent mode the gesture will remain active when you release the mouse button. |
| 250 | +3. Repeat the process with the other hand, grabbing the same object in a second spot. |
| 251 | +4. Now that both hands are grabbing the same object, you can move either of them to perform two-handed manipulation. |
| 252 | + |
| 253 | +--- |
| 254 | + |
| 255 | +<video width="600" controls="controls"> |
| 256 | + <source type="video/mp4" src="../../External/Documentation/Videos/MRTK_InputSimulation_TwoHandManipulation.mp4"></source> |
| 257 | +</video> |
| 258 | + |
| 259 | +## GGV Interaction |
| 260 | + |
| 261 | +1. Enable GGV simulation by switching __Hand Simulation Mode__ to _Gestures_ in the [Input Simulation Profile](#enabling-the-input-simulation-service) |
| 262 | +  |
| 263 | +2. Rotate the camera to point the gaze cursor at the interactable object (right mouse button) |
| 264 | +3. Hold _Space_ to control the right hand |
| 265 | +4. Click and hold _left mouse button_ to interact |
| 266 | +5. Rotate the camera again to manipulate the object |
| 267 | + |
| 268 | +--- |
| 269 | + |
| 270 | +<video width="600" controls="controls"> |
| 271 | + <source type="video/mp4" src="../../External/Documentation/Videos/MRTK_InputSimulation_GGVManipulation.mp4"></source> |
| 272 | +</video> --> |
0 commit comments