Exemple #1
0
 public static bool IsGrabbing(Handedness trackedHand)
 {
     return(!IsPinching(trackedHand) &&
            HandPoseUtils.MiddleFingerCurl(trackedHand) > GrabThreshold &&
            HandPoseUtils.RingFingerCurl(trackedHand) > GrabThreshold &&
            HandPoseUtils.PinkyFingerCurl(trackedHand) > GrabThreshold &&
            HandPoseUtils.ThumbFingerCurl(trackedHand) > GrabThreshold);
 }
Exemple #2
0
        /// <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;
                    }
                }
            }
        }
Exemple #3
0
        /// <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;
                        }
                    }
                }
            }
        }
        protected bool UpdateHandData(OVRHand ovrHand, OVRSkeleton ovrSkeleton)
        {
            bool isTracked = ovrHand.IsTracked;

            if (ovrHand.HandConfidence == OVRHand.TrackingConfidence.High)
            {
                _lastHighConfidenceTime = Time.unscaledTime;
            }
            if (ovrHand.HandConfidence == OVRHand.TrackingConfidence.Low)
            {
                if (settingsProfile.MinimumHandConfidence == OVRHand.TrackingConfidence.High)
                {
                    isTracked = false;
                }
                else
                {
                    float lowConfidenceTime = Time.time - _lastHighConfidenceTime;
                    if (settingsProfile.LowConfidenceTimeThreshold > 0 &&
                        settingsProfile.LowConfidenceTimeThreshold < lowConfidenceTime)
                    {
                        isTracked = false;
                    }
                }
            }

            if (ControllerHandedness == Handedness.Left)
            {
                settingsProfile.CurrentLeftHandTrackingConfidence = ovrHand.HandConfidence;
            }
            else
            {
                settingsProfile.CurrentRightHandTrackingConfidence = ovrHand.HandConfidence;
            }

            if (ovrSkeleton != null)
            {
                var bones = ovrSkeleton.Bones;
                foreach (var bone in bones)
                {
                    UpdateBone(bone);
                }

                UpdatePalm();
            }

            HandDefinition?.UpdateHandJoints(jointPoses);

            // Note: After some testing, it seems when moving your hand fast, Oculus's pinch estimation data gets frozen, which leads to stuck pinches.
            // To counter this, we perform a distance check between thumb and index to determine if we should force the pinch to a false state.
            float pinchStrength = HandPoseUtils.CalculateIndexPinch(ControllerHandedness);

            if (pinchStrength == 0.0f)
            {
                IsPinching = false;
            }
            else
            {
                if (IsPinching)
                {
                    // If we are already pinching, we make the pinch a bit sticky
                    IsPinching = pinchStrength > 0.5f;
                }
                else
                {
                    // If not yet pinching, only consider pinching if finger confidence is high
                    IsPinching = pinchStrength > 0.85f && ovrHand.GetFingerConfidence(OVRHand.HandFinger.Index) == OVRHand.TrackingConfidence.High;
                }
            }

            isIndexGrabbing  = HandPoseUtils.IsIndexGrabbing(ControllerHandedness);
            isMiddleGrabbing = HandPoseUtils.IsMiddleGrabbing(ControllerHandedness);


            // Pinch was also used as grab, we want to allow hand-curl grab not just pinch.
            // Determine pinch and grab separately
            if (isTracked)
            {
                IsGrabbing = isIndexGrabbing && isMiddleGrabbing;
            }

            return(isTracked);
        }
Exemple #5
0
        protected bool UpdateHandData(OVRHand ovrHand, OVRSkeleton ovrSkeleton)
        {
            bool isTracked = ovrHand.IsTracked;

            if (ovrHand.HandConfidence == OVRHand.TrackingConfidence.High)
            {
                _lastHighConfidenceTime = Time.unscaledTime;
            }
            if (ovrHand.HandConfidence == OVRHand.TrackingConfidence.Low)
            {
                if (MRTKOculusConfig.Instance.MinimumHandConfidence == OVRHand.TrackingConfidence.High)
                {
                    isTracked = false;
                }
                else
                {
                    float lowConfidenceTime = Time.time - _lastHighConfidenceTime;
                    if (MRTKOculusConfig.Instance.LowConfidenceTimeThreshold > 0 &&
                        MRTKOculusConfig.Instance.LowConfidenceTimeThreshold < lowConfidenceTime)
                    {
                        isTracked = false;
                    }
                }
            }

            if (ControllerHandedness == Handedness.Left)
            {
                MRTKOculusConfig.Instance.CurrentLeftHandTrackingConfidence = ovrHand.HandConfidence;
            }
            else
            {
                MRTKOculusConfig.Instance.CurrentRightHandTrackingConfidence = ovrHand.HandConfidence;
            }

            // Disable hand if not tracked
            if (handRenderer != null)
            {
                handRenderer.enabled = isTracked;
            }

            if (ovrSkeleton != null)
            {
                var bones = ovrSkeleton.Bones;
                foreach (var bone in bones)
                {
                    UpdateBone(bone);
                }

                UpdatePalm();
            }

            CoreServices.InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, jointPoses);

            // Note: After some testing, it seems when moving your hand fast, Oculus's pinch estimation data gets frozen, which leads to stuck pinches.
            // To counter this, we perform a distance check between thumb and index to determine if we should force the pinch to a false state.
            float pinchStrength;

            if (AreIndexAndThumbFarApart())
            {
                pinchStrength = 0f;
                IsPinching    = false;
            }
            else
            {
                pinchStrength = ovrHand.GetFingerPinchStrength(OVRHand.HandFinger.Index);
                if (IsPinching)
                {
                    // If we are already pinching, we make the pinch a bit sticky
                    IsPinching = ovrHand.GetFingerPinchStrength(OVRHand.HandFinger.Index) > 0.85f;
                }
                else
                {
                    // If not yet pinching, only consider pinching if finger confidence is high
                    IsPinching = ovrHand.GetFingerIsPinching(OVRHand.HandFinger.Index) &&
                                 ovrHand.GetFingerConfidence(OVRHand.HandFinger.Index) == OVRHand.TrackingConfidence.High;
                }
            }

            isIndexGrabbing  = HandPoseUtils.IsIndexGrabbing(ControllerHandedness);
            isMiddleGrabbing = HandPoseUtils.IsMiddleGrabbing(ControllerHandedness);
            isThumbGrabbing  = HandPoseUtils.IsThumbGrabbing(ControllerHandedness);

            // Hand Curl Properties:
            float indexFingerCurl  = HandPoseUtils.IndexFingerCurl(ControllerHandedness);
            float middleFingerCurl = HandPoseUtils.MiddleFingerCurl(ControllerHandedness);
            float ringFingerCurl   = HandPoseUtils.RingFingerCurl(ControllerHandedness);
            float pinkyFingerCurl  = HandPoseUtils.PinkyFingerCurl(ControllerHandedness);

            // Pinch was also used as grab, we want to allow hand-curl grab not just pinch.
            // Determine pinch and grab separately
            if (isTracked)
            {
                IsGrabbing = isIndexGrabbing && isMiddleGrabbing;
            }

            if (MRTKOculusConfig.Instance.UpdateMaterialPinchStrengthValue && handMaterial != null)
            {
                float gripStrength = indexFingerCurl + middleFingerCurl + ringFingerCurl + pinkyFingerCurl;
                gripStrength /= 4.0f;
                gripStrength  = gripStrength > 0.8f ? 1.0f : gripStrength;

                pinchStrength = Mathf.Max(pinchStrength, gripStrength);
                handMaterial.SetFloat(pinchStrengthProp, pinchStrength);
            }
            return(isTracked);
        }
Exemple #6
0
 public static bool IsPinching(Handedness trackedHand)
 {
     return(HandPoseUtils.CalculateIndexPinch(trackedHand) > PinchThreshold);
 }