public void UpdateState(SimulatedHandData handData) { for (int i = 0; i < jointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; if (!jointPoses.ContainsKey(handJoint)) { jointPoses.Add(handJoint, handData.Joints[i]); } else { jointPoses[handJoint] = handData.Joints[i]; } } InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, jointPoses); UpdateVelocity(); UpdateInteractions(handData); }
public Transform RequestJointTransform(TrackedHandJoint joint, Handedness handedness) { IMixedRealityHand hand = null; Dictionary <TrackedHandJoint, Transform> fauxJoints = null; if (handedness == Handedness.Left) { hand = leftHand; fauxJoints = leftHandFauxJoints; } else if (handedness == Handedness.Right) { hand = rightHand; fauxJoints = rightHandFauxJoints; } else { return(null); } Transform jointTransform = null; if (fauxJoints != null && !fauxJoints.TryGetValue(joint, out jointTransform)) { jointTransform = new GameObject().transform; // Since this service survives scene loading and unloading, the fauxJoints it manages need to as well. Object.DontDestroyOnLoad(jointTransform.gameObject); jointTransform.name = string.Format("Joint Tracker: {1} {0}", joint, handedness); if (hand != null && hand.TryGetJoint(joint, out MixedRealityPose pose)) { jointTransform.SetPositionAndRotation(pose.Position, pose.Rotation); } fauxJoints.Add(joint, jointTransform); } return(jointTransform); }
public bool TryGetControllerPose(TrackedHandJoint handJointToTrack, out Vector3 position, out Quaternion rotation, bool getPointerOnly = false) { bool retrieved = false; position = Vector3.zero; rotation = Quaternion.identity; if (!XRSettings.enabled) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); position = ray.GetPoint(0.5f) + new Vector3(-0.01f, -0.015f, 0); rotation = Quaternion.Euler(Camera.main.transform.eulerAngles + new Vector3(-45, -45, 0));//Camera.main.transform.rotation + Quaternion.AngleAxis(90, Vector3.up) + Quaternion.AngleAxis(45, Vector3.left); retrieved = true; } else { if (getPointerOnly) { try { position = (detectedHand ?? detectedController).InputSource.Pointers[0].Position; rotation = (detectedHand ?? detectedController).InputSource.Pointers[0].Rotation; retrieved = true; } catch (Exception) { retrieved = false; } } else { retrieved = TryGetSpecificControllerPose(Handedness.None, handJointToTrack, out position, out rotation); } } return(retrieved); }
private void ScaleFingerTip(Transform jointTransform, TrackedHandJoint fingerTipJoint, Vector3 boneRootPos) { // Set fingertip base bone scale to match the bone length to the fingertip. // This will only scale correctly if the model was constructed to match // the standard "test" edit-time hand model from the LeapMotion TestHandFactory. if (!MixedRealityHand.TryGetJoint(fingerTipJoint, out MixedRealityPose pose)) { return; } var boneTipPos = pose.Position; var boneVec = boneTipPos - boneRootPos; if (transform.lossyScale.x != 0f && transform.lossyScale.x != 1f) { boneVec /= transform.lossyScale.x; } var newScale = jointTransform.transform.localScale; var lengthComponentIdx = GetLargestComponentIndex(ModelFingerPointing); newScale[lengthComponentIdx] = boneVec.magnitude / fingerTipLengths[fingerTipJoint]; jointTransform.transform.localScale = newScale; }
/// <summary> /// Get the pose of the metacarpal joints from the current frame of the LeapServiceProvider because the metacarpal joints /// are not included in AttachmentPointFlags. The metacarpal joints are those located directly above the wrist. /// </summary> /// <param name="metacarpalJoint">A metacarpal TrackedHandJoint</param> /// <returns>The MixedRealityPose for the leap metacarpal joint</returns> private MixedRealityPose GetMetacarpalPose(TrackedHandJoint metacarpalJoint) { int metacarpalIndex = metacarpals.IndexOf(metacarpalJoint); // Get the joint poses of the hand each frame // A reference to the leap Hand cannot be cached and needs to be retrieved each frame List <Hand> leapHandsInCurrentFrame = leapServiceProvider.CurrentFrame.Hands; foreach (Hand hand in leapHandsInCurrentFrame) { if ((hand.IsLeft && ControllerHandedness == Handedness.Left) || (hand.IsRight && ControllerHandedness == Handedness.Right)) { // Leapmotion thumb metacarpal is stored at index 1 int boneIndex = (metacarpalJoint == TrackedHandJoint.ThumbMetacarpalJoint) ? 1 : 0; Vector3 position = hand.Fingers[metacarpalIndex].bones[boneIndex].PrevJoint.ToVector3(); Quaternion rotation = hand.Fingers[metacarpalIndex].bones[boneIndex].Rotation.ToQuaternion(); return(new MixedRealityPose(position, rotation)); } } return(MixedRealityPose.ZeroIdentity); }
protected void UpdateJointPose(TrackedHandJoint joint, Vector3 position, Quaternion rotation) { // TODO Figure out kalman filter coefficients to get good quality smoothing #if LATER if (joint == TrackedHandJoint.IndexTip) { jointPosition = indexTipFilter.Update(position); } else if (joint == TrackedHandJoint.Palm) { jointPosition = palmFilter.Update(position); } #endif MixedRealityPose pose = new MixedRealityPose(position, rotation); if (!jointPoses.ContainsKey(joint)) { jointPoses.Add(joint, pose); } else { jointPoses[joint] = pose; } }
/// <inheritdoc/> void IMixedRealityHandJointHandler.OnHandJointsUpdated(InputEventData <IDictionary <TrackedHandJoint, MixedRealityPose> > eventData) { if (eventData.InputSource.SourceId != Controller.InputSource.SourceId) { return; } Debug.Assert(eventData.Handedness == Controller.ControllerHandedness); IMixedRealityInputSystem inputSystem = CoreServices.InputSystem; // Only runs if render skeleton joints is true MixedRealityHandTrackingProfile handTrackingProfile = inputSystem?.InputSystemProfile.HandTrackingProfile; if (handTrackingProfile != null && handTrackingProfile.EnableHandJointVisualization) { // This starts at 1 to skip over TrackedHandJoint.None. for (int i = 1; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; MixedRealityPose handJointPose = eventData.InputData[handJoint]; if (skeletonJoints.TryGetValue(handJoint, out Transform skeletonJointTransform)) { skeletonJointTransform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); } else { GameObject prefab; if (handJoint == TrackedHandJoint.Palm) { prefab = inputSystem.InputSystemProfile.HandTrackingProfile.PalmJointPrefab; } else if (handJoint == TrackedHandJoint.IndexTip) { prefab = inputSystem.InputSystemProfile.HandTrackingProfile.FingerTipPrefab; } else { prefab = inputSystem.InputSystemProfile.HandTrackingProfile.JointPrefab; } GameObject jointObject; if (prefab != null) { jointObject = Instantiate(prefab); } else { jointObject = new GameObject(); } jointObject.name = handJoint.ToString() + " Proxy Transform"; jointObject.transform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); jointObject.transform.parent = transform; skeletonJoints.Add(handJoint, jointObject.transform); } } } else { // clear existing joint GameObjects / meshes foreach (var joint in skeletonJoints) { Destroy(joint.Value.gameObject); } skeletonJoints.Clear(); } // Only runs if render hand mesh is true bool renderHandmesh = handTrackingProfile != null && handTrackingProfile.EnableHandMeshVisualization; HandRenderer.enabled = renderHandmesh; if (renderHandmesh) { // Render the rigged hand mesh itself // Apply updated TrackedHandJoint pose data to the assigned transforms // This starts at 1 to skip over TrackedHandJoint.None. for (int i = 1; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; MixedRealityPose handJointPose = eventData.InputData[handJoint]; if (joints.TryGetValue(handJoint, out Transform jointTransform) && jointTransform != null) { if (handJoint == TrackedHandJoint.Palm) { if (ModelPalmAtLeapWrist) { Palm.position = eventData.InputData[TrackedHandJoint.Wrist].Position; } else { Palm.position = handJointPose.Position; } Palm.rotation = handJointPose.Rotation * UserBoneRotation; } else if (handJoint == TrackedHandJoint.Wrist) { if (!ModelPalmAtLeapWrist) { Wrist.position = handJointPose.Position; } } else { // Finger joints jointTransform.rotation = handJointPose.Rotation * Reorientation(); if (DeformPosition) { jointTransform.position = handJointPose.Position; } if (ScaleLastFingerBone && (handJoint == TrackedHandJoint.ThumbDistalJoint || handJoint == TrackedHandJoint.IndexDistalJoint || handJoint == TrackedHandJoint.MiddleDistalJoint || handJoint == TrackedHandJoint.RingDistalJoint || handJoint == TrackedHandJoint.PinkyDistalJoint)) { ScaleFingerTip(eventData, jointTransform, handJoint + 1, jointTransform.position); } } } } // Update the hand material float pinchStrength = HandPoseUtils.CalculateIndexPinch(Controller.ControllerHandedness); // Hand Curl Properties: float indexFingerCurl = HandPoseUtils.IndexFingerCurl(Controller.ControllerHandedness); float middleFingerCurl = HandPoseUtils.MiddleFingerCurl(Controller.ControllerHandedness); float ringFingerCurl = HandPoseUtils.RingFingerCurl(Controller.ControllerHandedness); float pinkyFingerCurl = HandPoseUtils.PinkyFingerCurl(Controller.ControllerHandedness); if (handMaterial != null && handRendererInitialized) { float gripStrength = indexFingerCurl + middleFingerCurl + ringFingerCurl + pinkyFingerCurl; gripStrength /= 4.0f; gripStrength = gripStrength > 0.8f ? 1.0f : gripStrength; pinchStrength = Mathf.Pow(Mathf.Max(pinchStrength, gripStrength), 2.0f); if (handRenderer.sharedMaterial.HasProperty(pinchStrengthMaterialProperty)) { handRenderer.sharedMaterial.SetFloat(pinchStrengthMaterialProperty, pinchStrength); } // Only show this warning once else if (!displayedMaterialPropertyWarning) { Debug.LogWarning(String.Format("The property {0} for reacting to pinch strength was not found. A material with this property is required to visualize pinch strength.", pinchStrengthMaterialProperty)); displayedMaterialPropertyWarning = true; } } } }
/// <inheritdoc/> public override void OnHandJointsUpdated(InputEventData <IDictionary <TrackedHandJoint, MixedRealityPose> > eventData) { using (OnHandJointsUpdatedPerfMarker.Auto()) { // The base class takes care of updating all of the joint data base.OnHandJointsUpdated(eventData); // exit early and disable the rigged hand model if we've gotten a hand mesh from the underlying platform if (receivingPlatformHandMesh) { HandRenderer.enabled = false; return; } // Ensures that the hand only renders when the event data matches the controller this visualizer represents if (eventData.InputSource.SourceId != Controller.InputSource.SourceId) { return; } Debug.Assert(eventData.Handedness == Controller.ControllerHandedness); IMixedRealityInputSystem inputSystem = CoreServices.InputSystem; MixedRealityHandTrackingProfile handTrackingProfile = inputSystem?.InputSystemProfile.HandTrackingProfile; // Only runs if render hand mesh is true bool renderHandmesh = handTrackingProfile != null && handTrackingProfile.EnableHandMeshVisualization; HandRenderer.enabled = renderHandmesh; if (renderHandmesh) { // Render the rigged hand mesh itself // Apply updated TrackedHandJoint pose data to the assigned transforms // This starts at 1 to skip over TrackedHandJoint.None. for (int i = 1; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; // Skip this hand joint if the event data doesn't have an entry for it if (!eventData.InputData.ContainsKey(handJoint)) { continue; } MixedRealityPose handJointPose = eventData.InputData[handJoint]; Transform jointTransform = riggedVisualJointsArray[i]; if (jointTransform != null) { if (handJoint == TrackedHandJoint.Palm) { if (ModelPalmAtLeapWrist) { Palm.position = eventData.InputData[TrackedHandJoint.Wrist].Position; } else { Palm.position = handJointPose.Position; } Palm.rotation = handJointPose.Rotation * UserBoneRotation; } else if (handJoint == TrackedHandJoint.Wrist) { if (!ModelPalmAtLeapWrist) { Wrist.position = handJointPose.Position; } } else { // Finger riggedVisualJointsArray jointTransform.rotation = handJointPose.Rotation * Reorientation(); if (DeformPosition) { jointTransform.position = handJointPose.Position; } if (ScaleLastFingerBone && (handJoint == TrackedHandJoint.ThumbDistalJoint || handJoint == TrackedHandJoint.IndexDistalJoint || handJoint == TrackedHandJoint.MiddleDistalJoint || handJoint == TrackedHandJoint.RingDistalJoint || handJoint == TrackedHandJoint.PinkyDistalJoint)) { ScaleFingerTip(eventData, jointTransform, handJoint + 1, jointTransform.position); } } } } // Update the hand material float pinchStrength = HandPoseUtils.CalculateIndexPinch(Controller.ControllerHandedness); // Hand Curl Properties: float indexFingerCurl = HandPoseUtils.IndexFingerCurl(Controller.ControllerHandedness); float middleFingerCurl = HandPoseUtils.MiddleFingerCurl(Controller.ControllerHandedness); float ringFingerCurl = HandPoseUtils.RingFingerCurl(Controller.ControllerHandedness); float pinkyFingerCurl = HandPoseUtils.PinkyFingerCurl(Controller.ControllerHandedness); if (handMaterial != null && handRendererInitialized) { float gripStrength = indexFingerCurl + middleFingerCurl + ringFingerCurl + pinkyFingerCurl; gripStrength /= 4.0f; gripStrength = gripStrength > 0.8f ? 1.0f : gripStrength; pinchStrength = Mathf.Pow(Mathf.Max(pinchStrength, gripStrength), 2.0f); if (handRenderer.sharedMaterial.HasProperty(pinchStrengthMaterialProperty)) { handRenderer.sharedMaterial.SetFloat(pinchStrengthMaterialProperty, pinchStrength); } // Only show this warning once else if (!displayedMaterialPropertyWarning) { Debug.LogWarning(String.Format("The property {0} for reacting to pinch strength was not found. A material with this property is required to visualize pinch strength.", pinchStrengthMaterialProperty)); displayedMaterialPropertyWarning = true; } } } } }
/// <summary> /// Instantiates <see cref="FingerTipKinematicBodyPrefab"/>s for all <see cref="fingerTipTypes"/>. /// </summary> /// <remarks> /// Optionally instantiates <see cref="PalmKinematicBodyPrefab"/>. /// </remarks> /// <param name="rigidBodyPrefab">The prefab to instantiate.</param> /// <param name="layer">the layer to put the prefab on.</param> /// <param name="handednessType">the specified <see cref="Handedness"/> for the joint.</param> /// <param name="jointType">the specified <see cref="TrackedHandJoint"/> to instantiate against.</param> /// <param name="parent">The root <see href="https://docs.unity3d.com/ScriptReference/GameObject.html"> for the joints.</param> /// <param name="jointKinematicBody">When successful, the generated <see cref="JointKinematicBody"/>.</param> /// <returns>True when able to successfully intantiate and create a <see cref="JointKinematicBody"/>.</returns> private static bool TryCreateJointKinematicBody(GameObject rigidBodyPrefab, int layer, Handedness handednessType, TrackedHandJoint jointType, Transform parent, out JointKinematicBody jointKinematicBody) { jointKinematicBody = null; GameObject currentGameObject = GameObject.Instantiate(rigidBodyPrefab, parent); currentGameObject.layer = layer; JointKinematicBody currentJoint = currentGameObject.GetComponent <JointKinematicBody>(); if (currentJoint == null) { Debug.LogError("The HandPhysicsService assumes the FingerTipKinematicBodyPrefab has a JointKinematicBody component."); UnityEngine.Object.Destroy(currentGameObject); return(false); } currentJoint.JointType = jointType; currentJoint.HandednessType = handednessType; currentGameObject.name = handednessType + " " + jointType; if (currentGameObject.GetComponent <Collider>() == null) { Debug.LogError("The HandPhysicsService assumes the FingerTipKinematicBodyPrefab has a Collder component."); UnityEngine.Object.Destroy(currentGameObject); return(false); } Rigidbody rigidbody = currentGameObject.GetComponent <Rigidbody>(); if (rigidbody == null) { Debug.LogError("The HandPhysicsService assumes the FingerTipKinematicBodyPrefab has a Rigidbody component."); UnityEngine.Object.Destroy(currentGameObject); return(false); } if (!rigidbody.isKinematic) { Debug.LogWarning("The HandPhysicsService FingerTipKinematicBodyPrefab rigidbody should be marked as kinematic, making kinematic."); rigidbody.isKinematic = true; } jointKinematicBody = currentJoint; return(true); }
/// <summary> /// Update the hand data from the device. /// </summary> /// <param name="interactionSourceState">The InteractionSourceState retrieved from the platform.</param> private void UpdateHandData(InteractionSourceState interactionSourceState) { #if WINDOWS_UWP || DOTNETWINRT_PRESENT // Articulated hand support is only present in the 18362 version and beyond Windows // SDK (which contains the V8 drop of the Universal API Contract). In particular, // the HandPose related APIs are only present on this version and above. if (!articulatedHandApiAvailable) { return; } PerceptionTimestamp perceptionTimestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now); IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager?.GetDetectedSourcesAtTimestamp(perceptionTimestamp); foreach (SpatialInteractionSourceState sourceState in sources) { if (sourceState.Source.Id.Equals(interactionSourceState.source.id)) { HandPose handPose = sourceState.TryGetHandPose(); #if WINDOWS_UWP if (CoreServices.InputSystem.InputSystemProfile.HandTrackingProfile.EnableHandMeshVisualization) { // Accessing the hand mesh data involves copying quite a bit of data, so only do it if application requests it. if (handMeshObserver == null && !hasRequestedHandMeshObserver) { SetHandMeshObserver(sourceState); hasRequestedHandMeshObserver = true; } if (handMeshObserver != null && handMeshTriangleIndices == null) { uint indexCount = handMeshObserver.TriangleIndexCount; ushort[] indices = new ushort[indexCount]; handMeshObserver.GetTriangleIndices(indices); handMeshTriangleIndices = new int[indexCount]; Array.Copy(indices, handMeshTriangleIndices, (int)handMeshObserver.TriangleIndexCount); // Compute neutral pose Vector3[] neutralPoseVertices = new Vector3[handMeshObserver.VertexCount]; HandPose neutralPose = handMeshObserver.NeutralPose; var vertexAndNormals = new HandMeshVertex[handMeshObserver.VertexCount]; HandMeshVertexState handMeshVertexState = handMeshObserver.GetVertexStateForPose(neutralPose); handMeshVertexState.GetVertices(vertexAndNormals); for (int i = 0; i < handMeshObserver.VertexCount; i++) { neutralPoseVertices[i] = WindowsMixedRealityUtilities.SystemVector3ToUnity(vertexAndNormals[i].Position); } // Compute UV mapping InitializeUVs(neutralPoseVertices); } if (handPose != null && handMeshObserver != null && handMeshTriangleIndices != null) { var vertexAndNormals = new HandMeshVertex[handMeshObserver.VertexCount]; var handMeshVertexState = handMeshObserver.GetVertexStateForPose(handPose); handMeshVertexState.GetVertices(vertexAndNormals); var meshTransform = handMeshVertexState.CoordinateSystem.TryGetTransformTo(WindowsMixedRealityUtilities.SpatialCoordinateSystem); if (meshTransform.HasValue) { System.Numerics.Vector3 scale; System.Numerics.Quaternion rotation; System.Numerics.Vector3 translation; System.Numerics.Matrix4x4.Decompose(meshTransform.Value, out scale, out rotation, out translation); var handMeshVertices = new Vector3[handMeshObserver.VertexCount]; var handMeshNormals = new Vector3[handMeshObserver.VertexCount]; for (int i = 0; i < handMeshObserver.VertexCount; i++) { handMeshVertices[i] = WindowsMixedRealityUtilities.SystemVector3ToUnity(vertexAndNormals[i].Position); handMeshNormals[i] = WindowsMixedRealityUtilities.SystemVector3ToUnity(vertexAndNormals[i].Normal); } /// Hands should follow the Playspace to accommodate teleporting, so fold in the Playspace transform. Vector3 unityPosition = WindowsMixedRealityUtilities.SystemVector3ToUnity(translation); unityPosition = MixedRealityPlayspace.TransformPoint(unityPosition); Quaternion unityRotation = WindowsMixedRealityUtilities.SystemQuaternionToUnity(rotation); unityRotation = MixedRealityPlayspace.Rotation * unityRotation; HandMeshInfo handMeshInfo = new HandMeshInfo { vertices = handMeshVertices, normals = handMeshNormals, triangles = handMeshTriangleIndices, uvs = handMeshUVs, position = unityPosition, rotation = unityRotation }; CoreServices.InputSystem?.RaiseHandMeshUpdated(InputSource, ControllerHandedness, handMeshInfo); } } } else { // if hand mesh visualization is disabled make sure to destroy our hand mesh observer if it has already been created if (handMeshObserver != null) { // notify that hand mesh has been updated (cleared) HandMeshInfo handMeshInfo = new HandMeshInfo(); CoreServices.InputSystem?.RaiseHandMeshUpdated(InputSource, ControllerHandedness, handMeshInfo); hasRequestedHandMeshObserver = false; handMeshObserver = null; } } #endif // WINDOWS_UWP if (handPose != null && handPose.TryGetJoints(WindowsMixedRealityUtilities.SpatialCoordinateSystem, jointIndices, jointPoses)) { for (int i = 0; i < jointPoses.Length; i++) { unityJointOrientations[i] = WindowsMixedRealityUtilities.SystemQuaternionToUnity(jointPoses[i].Orientation); unityJointPositions[i] = WindowsMixedRealityUtilities.SystemVector3ToUnity(jointPoses[i].Position); // We want the controller to follow the Playspace, so fold in the playspace transform here to // put the controller pose into world space. unityJointPositions[i] = MixedRealityPlayspace.TransformPoint(unityJointPositions[i]); unityJointOrientations[i] = MixedRealityPlayspace.Rotation * unityJointOrientations[i]; if (jointIndices[i] == HandJointKind.IndexTip) { lastIndexTipRadius = jointPoses[i].Radius; } TrackedHandJoint handJoint = ConvertHandJointKindToTrackedHandJoint(jointIndices[i]); if (!unityJointPoses.ContainsKey(handJoint)) { unityJointPoses.Add(handJoint, new MixedRealityPose(unityJointPositions[i], unityJointOrientations[i])); } else { unityJointPoses[handJoint] = new MixedRealityPose(unityJointPositions[i], unityJointOrientations[i]); } } CoreServices.InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, unityJointPoses); } } } #endif // WINDOWS_UWP || DOTNETWINRT_PRESENT }
public ArticulatedHandPoseItem(TrackedHandJoint joint, MixedRealityPose pose) { this.joint = jointNames[(int)joint]; this.pose = pose; }
void IMixedRealityHandJointHandler.OnHandJointsUpdated(InputEventData <IDictionary <TrackedHandJoint, MixedRealityPose> > eventData) { using (OnHandJointsUpdatedPerfMarker.Auto()) { if (eventData.InputSource.SourceId != Controller.InputSource.SourceId) { return; } Debug.Assert(eventData.Handedness == Controller.ControllerHandedness); IMixedRealityInputSystem inputSystem = CoreServices.InputSystem; MixedRealityHandTrackingProfile handTrackingProfile = inputSystem?.InputSystemProfile != null ? inputSystem.InputSystemProfile.HandTrackingProfile : null; if (handTrackingProfile != null && !handTrackingProfile.EnableHandJointVisualization) { // clear existing joint GameObjects / meshes foreach (Transform joint in jointsArray) { if (joint != null) { Destroy(joint.gameObject); } } return; } // This starts at 1 to skip over TrackedHandJoint.None. for (int i = 1; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; MixedRealityPose handJointPose = eventData.InputData[handJoint]; Transform jointTransform = jointsArray[i]; if (jointTransform != null) { jointTransform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); } else { GameObject prefab; if (handJoint == TrackedHandJoint.None || handTrackingProfile == null) { // No visible mesh for the "None" joint prefab = null; } else if (handJoint == TrackedHandJoint.Palm) { prefab = handTrackingProfile.PalmJointPrefab; } else if (handJoint == TrackedHandJoint.IndexTip) { prefab = handTrackingProfile.FingerTipPrefab; } else { prefab = handTrackingProfile.JointPrefab; } GameObject jointObject; if (prefab != null) { jointObject = Instantiate(prefab); } else { jointObject = new GameObject(); } jointObject.name = handJoint.ToString() + " Proxy Transform"; jointObject.transform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); jointObject.transform.parent = transform; jointsArray[i] = jointObject.transform; } } } }
protected virtual bool UpdateHandJoints() { using (UpdateHandJointsPerfMarker.Auto()) { if (!handJointsUpdated || MixedRealityHand.IsNull()) { return(false); } IMixedRealityInputSystem inputSystem = CoreServices.InputSystem; MixedRealityHandTrackingProfile handTrackingProfile = inputSystem?.InputSystemProfile != null ? inputSystem.InputSystemProfile.HandTrackingProfile : null; if (handTrackingProfile != null && !handTrackingProfile.EnableHandJointVisualization) { // clear existing joint GameObjects / meshes foreach (Transform joint in JointsArray) { if (joint != null) { Destroy(joint.gameObject); } } JointsArray = System.Array.Empty <Transform>(); // Even though the base class isn't handling joint visualization, we still received new joints. // Return true here in case any derived classes want to update. return(true); } if (JointsArray.Length != ArticulatedHandPose.JointCount) { JointsArray = new Transform[ArticulatedHandPose.JointCount]; } // This starts at 1 to skip over TrackedHandJoint.None. for (int i = 1; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; // Skip this hand joint if the event data doesn't have an entry for it if (!MixedRealityHand.TryGetJoint(handJoint, out MixedRealityPose handJointPose)) { continue; } Transform jointTransform = JointsArray[i]; if (jointTransform != null) { jointTransform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); } else { GameObject prefab; if (handJoint == TrackedHandJoint.None || handTrackingProfile == null) { // No visible mesh for the "None" joint prefab = null; } else if (handJoint == TrackedHandJoint.Palm) { prefab = handTrackingProfile.PalmJointPrefab; } else if (handJoint == TrackedHandJoint.IndexTip) { prefab = handTrackingProfile.FingerTipPrefab; } else { prefab = handTrackingProfile.JointPrefab; } GameObject jointObject; if (prefab != null) { jointObject = Instantiate(prefab); } else { jointObject = new GameObject(); } jointObject.name = handJoint.ToString() + " Proxy Transform"; jointObject.transform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); jointObject.transform.parent = transform; JointsArray[i] = jointObject.transform; } } handJointsUpdated = false; return(true); } }
/// <summary> /// Constructs a new joint record. /// </summary> /// <param name="joint">The joint that was recorded.</param> /// <param name="pose">The joint pose that was recorded.</param> public RecordedHandJoint(TrackedHandJoint joint, MixedRealityPose pose) { this.joint = joint; this.pose = pose; }
public abstract bool TryGetJoint(TrackedHandJoint joint, out MixedRealityPose pose);
/// <inheritdoc/> public override bool TryGetJoint(TrackedHandJoint joint, out MixedRealityPose pose) { return(jointPoses.TryGetValue(joint, out pose)); }
/// <summary> /// Tries to get the pose of the requested joint for the first controller with the specified handedness. /// </summary> /// <param name="joint">The requested joint</param> /// <param name="handedness">The specific hand of interest. This should be either Handedness.Left or Handedness.Right</param> /// <param name="pose">The output pose data</param> public static bool TryGetJointPose(TrackedHandJoint joint, Handedness handedness, out MixedRealityPose pose) { return(TryGetJointPose <IMixedRealityHand>(joint, handedness, out pose)); }
/// <inheritdoc/> public bool TryGetJoint(TrackedHandJoint joint, out MixedRealityPose pose) => unityJointPoses.TryGetValue(joint, out pose);
private void GetJointPosition(Vector3[] positions, TrackedHandJoint jointId, Handedness handedness) { HandJointUtils.TryGetJointPose(jointId, handedness, out MixedRealityPose joint); positions[(int)jointId] = joint.Position; }