private void HandleKeyPoseChanged(ManagedHand hand, MLHandTracking.HandKeyPose pose)
 {
     //both hands holding thumbs?
     if (HandInput.Left.Hand.KeyPose == MLHandTracking.HandKeyPose.Thumb && HandInput.Right.Hand.KeyPose == MLHandTracking.HandKeyPose.Thumb)
     {
         StartCoroutine("ThumbsUpReset");
     }
     else
     {
         StopCoroutine("ThumbsUpReset");
     }
 }
示例#2
0
 private bool GetGesture(MLHandTracking.Hand hand, MLHandTracking.HandKeyPose type)
 {
     if (hand != null)
     {
         if (hand.KeyPose == type)
         {
             if (hand.HandKeyPoseConfidence > 0.9f)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
        private void HandleGestureChanged(ManagedHand hand, MLHandTracking.HandKeyPose pose)
        {
            //snap transform changes to avoid force pops:
            switch (pose)
            {
            case MLHandTracking.HandKeyPose.Fist:
                _handCollider.transform.position   = _managedHand.Skeleton.Position;
                _handCollider.transform.localScale = Vector3.one * _managedHand.Gesture.Grasp.radius;
                break;

            case MLHandTracking.HandKeyPose.L:
            case MLHandTracking.HandKeyPose.Finger:
                _handCollider.transform.localScale = Vector3.one * _pointColliderSize;
                _handCollider.transform.position   = _managedHand.Skeleton.Index.Tip.positionFiltered;
                break;

            case MLHandTracking.HandKeyPose.OpenHand:
                _handCollider.transform.localScale = new Vector3(_managedHand.Gesture.Grasp.radius, _openHandColliderWidth, _managedHand.Gesture.Grasp.radius);
                _handCollider.transform.position   = _managedHand.Skeleton.Position;
                _handCollider.transform.rotation   = _managedHand.Skeleton.Rotation;
                break;
            }
        }
            /// <summary>
            /// Sets the values of a specific key pose.
            /// </summary>
            /// <param name="config">The native config object of key poses to use.</param>
            /// <param name="handKeyPose">The key pose to set.</param>
            /// <param name="enable">The value to set the key pose with.</param>
            private static void SetKeyPoseConfig(NativeBindings.ConfigurationNative config, MLHandTracking.HandKeyPose handKeyPose, bool enable)
            {
                if (handKeyPose > MLHandTracking.HandKeyPose.NoPose)
                {
                    MLPluginLog.WarningFormat("KeyPoseManager.SetKeyPoseConfig trying to set {0}. Ignoring.", handKeyPose);
                    return;
                }

                config.KeyposeConfig[(uint)handKeyPose] = Convert.ToByte(enable);
            }
 //Event Handlers:
 private void HandleKeyposeChanged(MLHandTracking.HandKeyPose keyPose)
 {
     OnKeyPoseChanged?.Invoke(_managedHand, keyPose);
 }
        //Public Methods:
        public void Update()
        {
            if (!_managedHand.Visible)
            {
                return;
            }

            //pinch rotation offset mirror:
            Vector3 rotationOffset = _pinchAbsoluteRotationOffset;

            if (_managedHand.Hand.Type == MLHandTracking.HandType.Left)
            {
                rotationOffset.y *= -1;
            }

            //holders:
            Vector3    pinchPosition = Vector3.zero;
            Quaternion pinchRotation = Quaternion.identity;

            //pinch interaction point radius:
            if (_managedHand.Skeleton.Thumb.Tip.Visible && _managedHand.Skeleton.Index.Tip.Visible)
            {
                Pinch.radius = Vector3.Distance(_managedHand.Skeleton.Thumb.Tip.positionFiltered, _managedHand.Skeleton.Index.Tip.positionFiltered);
            }

            if (_managedHand.Skeleton.Thumb.Tip.Visible) //absolute placement:
            {
                //are we swapping modes?
                if (_pinchIsRelative)
                {
                    _pinchIsRelative          = false;
                    _pinchTransitioning       = true;
                    _pinchTransitionStartTime = Time.realtimeSinceStartup;
                }

                pinchPosition = _managedHand.Skeleton.Thumb.Tip.positionFiltered;
                pinchRotation = TransformUtilities.RotateQuaternion(_managedHand.Skeleton.Rotation, rotationOffset);

                //gather offset distance:
                if (_managedHand.Skeleton.Index.Knuckle.Visible && _managedHand.Skeleton.Thumb.Knuckle.Visible)
                {
                    Vector3 mcpMidpoint = Vector3.Lerp(_managedHand.Skeleton.Index.Knuckle.positionFiltered, _managedHand.Skeleton.Thumb.Knuckle.positionFiltered, .5f);
                    _pinchRelativePositionDistance = Vector3.Distance(mcpMidpoint, pinchPosition);
                }
            }
            else //relative placement:
            {
                //are we swapping modes?
                if (!_pinchIsRelative)
                {
                    _pinchIsRelative          = true;
                    _pinchTransitioning       = true;
                    _pinchTransitionStartTime = Time.realtimeSinceStartup;
                }

                //place between available mcps:
                if (_managedHand.Skeleton.Index.Knuckle.Visible && _managedHand.Skeleton.Thumb.Knuckle.Visible)
                {
                    pinchPosition = Vector3.Lerp(_managedHand.Skeleton.Index.Knuckle.positionFiltered, _managedHand.Skeleton.Thumb.Knuckle.positionFiltered, .5f);

                    //rotate:
                    pinchRotation = TransformUtilities.RotateQuaternion(_managedHand.Skeleton.Rotation, _pinchRelativeRotationOffset);

                    //move out along rotation forward:
                    pinchPosition += pinchRotation * Vector3.forward * _pinchRelativePositionDistance;
                }
                else
                {
                    //just use previous:
                    pinchPosition = Pinch.position;
                    pinchRotation = Pinch.rotation;
                }
            }

            //sticky release reduction:
            if (_collapsed)
            {
                if (_managedHand.Skeleton.Thumb.Tip.Visible && _managedHand.Skeleton.Index.Tip.Visible)
                {
                    //if starting to release, start using a point between the thumb and index tips:
                    if (Vector3.Distance(_managedHand.Skeleton.Thumb.Tip.positionFiltered, _managedHand.Skeleton.Index.Tip.positionFiltered) > _dynamicReleaseDistance)
                    {
                        pinchPosition = Vector3.Lerp(_managedHand.Skeleton.Thumb.Tip.positionFiltered, _managedHand.Skeleton.Index.Tip.positionFiltered, .3f);
                    }
                }
            }

            //apply pinch pose - to avoid jumps when relative placement is used we smooth until close enough:
            if (_pinchTransitioning)
            {
                //position:
                Pinch.position = Vector3.SmoothDamp(Pinch.position, pinchPosition, ref _pinchArrivalPositionVelocity, _pinchTransitionTime);
                float positionDelta = Vector3.Distance(Pinch.position, pinchPosition);

                //rotation:
                Pinch.rotation = MotionUtilities.SmoothDamp(Pinch.rotation, pinchRotation, ref _pinchArrivalRotationVelocity, _pinchTransitionTime);
                float rotationDelta = Quaternion.Angle(Pinch.rotation, pinchRotation);

                //close enough to hand off?
                if (positionDelta < .001f && rotationDelta < 5)
                {
                    _pinchTransitioning = false;
                }

                //taking too long?
                if (Time.realtimeSinceStartup - _pinchTransitionStartTime > _pinchTransitionMaxDuration)
                {
                    _pinchTransitioning = false;
                }
            }
            else
            {
                Pinch.position = pinchPosition;
                Pinch.rotation = pinchRotation;
            }

            //grasp interaction point:
            Bounds graspBounds = CalculateGraspBounds
                                 (
                _managedHand.Skeleton.Thumb.Knuckle,
                _managedHand.Skeleton.Thumb.Joint,
                _managedHand.Skeleton.Thumb.Tip,
                _managedHand.Skeleton.Index.Knuckle,
                _managedHand.Skeleton.Index.Joint,
                _managedHand.Skeleton.Index.Tip,
                _managedHand.Skeleton.Middle.Knuckle,
                _managedHand.Skeleton.Middle.Joint,
                _managedHand.Skeleton.Middle.Tip
                                 );

            Grasp.position = _managedHand.Skeleton.Position;
            //when points are being initially found they can be wildly off and this could cause a massively large volume:
            Grasp.radius   = Mathf.Min(graspBounds.size.magnitude, _maxGraspRadius);
            Grasp.rotation = _managedHand.Skeleton.Rotation;

            //intent updated:
            if (_currentInteractionState != null)
            {
                _currentInteractionState.FireUpdate();
            }

            //keypose change proposed:
            if (_managedHand.Hand.KeyPose != VerifiedGesture && _managedHand.Hand.KeyPose != _proposedKeyPose)
            {
                //queue a new proposed change to keypose:
                _proposedKeyPose    = _managedHand.Hand.KeyPose;
                _keyPoseChangedTime = Time.realtimeSinceStartup;
            }

            //keypose change acceptance:
            if (_managedHand.Hand.KeyPose != VerifiedGesture && Time.realtimeSinceStartup - _keyPoseChangedTime > _keyPoseStabailityDuration)
            {
                //reset:
                Point.active = false;
                Pinch.active = false;
                Grasp.active = false;

                if (_collapsed)
                {
                    //intent end:
                    if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.C || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.OpenHand || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.L || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Finger)
                    {
                        if (_managedHand.Skeleton.Thumb.Tip.Visible && _managedHand.Skeleton.Index.Tip.Visible)
                        {
                            //dynamic release:
                            if (Vector3.Distance(_managedHand.Skeleton.Thumb.Tip.positionFiltered, _managedHand.Skeleton.Index.Tip.positionFiltered) > _dynamicReleaseDistance)
                            {
                                //end intent:
                                _collapsed = false;
                                _currentInteractionState.FireEnd();
                                _currentInteractionState = null;

                                //accept keypose change:
                                VerifiedGesture  = _managedHand.Hand.KeyPose;
                                _proposedKeyPose = _managedHand.Hand.KeyPose;
                                OnVerifiedGestureChanged?.Invoke(_managedHand, VerifiedGesture);

                                if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Finger || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.L)
                                {
                                    Intent = IntentPose.Pointing;
                                    OnIntentChanged?.Invoke(_managedHand, Intent);
                                }
                                else if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.C || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.OpenHand || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Thumb)
                                {
                                    Intent = IntentPose.Relaxed;
                                    OnIntentChanged?.Invoke(_managedHand, Intent);
                                }
                            }
                        }
                    }
                }
                else
                {
                    //intent begin:
                    if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Pinch || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Ok || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Fist)
                    {
                        _collapsed = true;

                        if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Pinch || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Ok)
                        {
                            Intent                   = IntentPose.Pinching;
                            Pinch.active             = true;
                            _currentInteractionState = Pinch.Touch;
                            _currentInteractionState.FireBegin();
                            OnIntentChanged?.Invoke(_managedHand, Intent);
                        }
                        else if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Fist)
                        {
                            Intent                   = IntentPose.Grasping;
                            Grasp.active             = true;
                            _currentInteractionState = Grasp.Touch;
                            _currentInteractionState.FireBegin();
                            OnIntentChanged?.Invoke(_managedHand, Intent);
                        }
                    }

                    if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Finger || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.L)
                    {
                        Intent       = IntentPose.Pointing;
                        Point.active = true;
                        OnIntentChanged?.Invoke(_managedHand, Intent);
                    }
                    else if (_managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.C || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.OpenHand || _managedHand.Hand.KeyPose == MLHandTracking.HandKeyPose.Thumb)
                    {
                        Intent = IntentPose.Relaxed;
                        OnIntentChanged?.Invoke(_managedHand, Intent);
                    }

                    //accept keypose change:
                    VerifiedGesture  = _managedHand.Hand.KeyPose;
                    _proposedKeyPose = _managedHand.Hand.KeyPose;
                    OnVerifiedGestureChanged?.Invoke(_managedHand, VerifiedGesture);
                }
            }

            UpdateCurrentInteractionPoint();
            UpdatePalmEvents();
        }
示例#7
0
 private bool IsHandInGesture(MLHandTracking.HandKeyPose keyPose, float confidence = 0.8f)
 {
     return(_managedHand.Hand.KeyPose == keyPose &&
            _managedHand.Hand.HandKeyPoseConfidence >= confidence);
 }
 /// <summary>
 /// Method to call when a pose is no longer detected.
 /// </summary>
 /// <param name="pose">The pose that has no longer been detected.</param>
 public void EndKeyPose(MLHandTracking.HandKeyPose pose)
 {
     this.KeyPose = pose;
     this.OnHandKeyPoseEnd?.Invoke(pose);
 }
 /// <summary>
 /// Method to call when a pose is detected for the first time.
 /// </summary>
 /// <param name="pose">The pose that has no longer been detected.</param>
 public void BeginKeyPose(MLHandTracking.HandKeyPose pose)
 {
     this.KeyPose = pose;
     this.OnHandKeyPoseBegin?.Invoke(pose);
 }