コード例 #1
0
        /// <summary>
        /// Capture a snapshot of simulated hand data based on current state.
        /// </summary>
        public bool UpdateHandData(SimulatedHandData handDataLeft, SimulatedHandData handDataRight)
        {
            SimulateUserInput();

            bool handDataChanged = false;
            // TODO: DateTime.UtcNow can be quite imprecise, better use Stopwatch.GetTimestamp
            // https://stackoverflow.com/questions/2143140/c-sharp-datetime-now-precision
            long timestamp = DateTime.UtcNow.Ticks;

            // Cache the generator delegates so we don't gc alloc every frame
            if (generatorLeft == null)
            {
                generatorLeft = HandStateLeft.FillCurrentFrame;
            }

            if (generatorRight == null)
            {
                generatorRight = HandStateRight.FillCurrentFrame;
            }

            handDataChanged |= handDataLeft.UpdateWithTimestamp(timestamp, HandStateLeft.IsTracked, HandStateLeft.IsPinching, generatorLeft);
            handDataChanged |= handDataRight.UpdateWithTimestamp(timestamp, HandStateRight.IsTracked, HandStateRight.IsPinching, generatorRight);

            return(handDataChanged);
        }
コード例 #2
0
        public void UpdateState(SimulatedHandData handData)
        {
            UpdateHandJoints(handData);
            UpdateVelocity();

            UpdateInteractions(handData);
        }
コード例 #3
0
        /// <summary>
        /// Capture a snapshot of simulated hand data based on current state.
        /// </summary>
        public bool UpdateHandData(SimulatedHandData handDataLeft, SimulatedHandData handDataRight, SimulatedHandData handDataGaze, MouseDelta mouseDelta)
        {
            SimulateUserInput(mouseDelta);

            HandStateLeft.Update();
            HandStateRight.Update();
            HandStateGaze.Update();

            bool handDataChanged = false;

            // Cache the generator delegates so we don't gc alloc every frame
            if (generatorLeft == null)
            {
                generatorLeft = HandStateLeft.FillCurrentFrame;
            }

            if (generatorRight == null)
            {
                generatorRight = HandStateRight.FillCurrentFrame;
            }

            if (generatorGaze == null)
            {
                generatorGaze = HandStateGaze.FillCurrentFrame;
            }

            handDataChanged |= handDataLeft.Update(HandStateLeft.IsTracked, HandStateLeft.IsPinching, generatorLeft);
            handDataChanged |= handDataRight.Update(HandStateRight.IsTracked, HandStateRight.IsPinching, generatorRight);
            handDataChanged |= handDataGaze.Update(HandStateGaze.IsTracked, HandStateGaze.IsPinching, generatorGaze);

            return(handDataChanged);
        }
        private bool UpdateHandDataFromState(SimulatedHandData frame, SimulatedHandState state)
        {
            bool handDataChanged = false;
            bool wasTracked      = frame.IsTracked;
            bool wasPinching     = frame.IsPinching;

            frame.IsTracked  = state.IsVisible;
            frame.IsPinching = state.IsPinching;
            if (wasTracked != frame.IsTracked || wasPinching != frame.IsPinching)
            {
                handDataChanged = true;
            }

            if (frame.IsTracked)
            {
                var prevTime = frame.Timestamp;
                frame.Timestamp = DateTime.UtcNow.Ticks;
                if (frame.Timestamp != prevTime)
                {
                    state.FillCurrentFrame(frame.Joints);
                    handDataChanged = true;
                }
            }
            else
            {
                // If frame is not tracked, set timestamp to zero
                frame.Timestamp = 0;
            }

            return(handDataChanged);
        }
コード例 #5
0
        public void UpdateState(SimulatedHandData handData)
        {
            Array.Copy(handData.Joints, jointPositions, jointCount);

            SimulatedHandUtils.CalculateJointRotations(ControllerHandedness, jointPositions, jointOrientations);

            for (int i = 0; i < jointPositions.Length; i++)
            {
                TrackedHandJoint handJoint = (TrackedHandJoint)i;

                if (!jointPoses.ContainsKey(handJoint))
                {
                    jointPoses.Add(handJoint, new MixedRealityPose(jointPositions[i], jointOrientations[i]));
                }
                else
                {
                    jointPoses[handJoint] = new MixedRealityPose(jointPositions[i], jointOrientations[i]);
                }
            }

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

            UpdateVelocity();

            UpdateInteractions(handData);
        }
コード例 #6
0
 public void Copy(SimulatedHandData other)
 {
     isTracked  = other.isTracked;
     isPinching = other.isPinching;
     for (int i = 0; i < jointCount; ++i)
     {
         joints[i] = other.joints[i];
     }
 }
コード例 #7
0
        private void EvaluateHandData(SimulatedHandData handData, Handedness handedness)
        {
            animation.EvaluateHandState(localTime, handedness, out bool isTracked, out bool isPinching);

            handData.Update(isTracked, isPinching,
                            (MixedRealityPose[] joints) =>
            {
                for (int i = 0; i < jointCount; ++i)
                {
                    joints[i] = animation.EvaluateHandJoint(localTime, handedness, (TrackedHandJoint)i);
                }
            });
        }
コード例 #8
0
        private void EvaluateHandData(SimulatedHandData handData, Handedness handedness)
        {
            animation.EvaluateHandState(localTime, handedness, out bool isTracked, out bool isPinching);

            if (handData.Update(isTracked, isPinching,
                                (MixedRealityPose[] joints) =>
            {
                for (int i = 0; i < ArticulatedHandPose.JointCount; ++i)
                {
                    joints[i] = animation.EvaluateHandJoint(localTime, handedness, (TrackedHandJoint)i);
                }
            }))
            {
                UpdateControllerDevice(ControllerSimulationMode.ArticulatedHand, handedness, handData);
            }
        }
コード例 #9
0
        /// <inheritdoc />
        protected override void UpdateHandJoints(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];
                }
            }

            handDefinition?.UpdateHandJoints(jointPoses);
        }
コード例 #10
0
        /// <inheritdoc />
        protected override void UpdateHandJoints(SimulatedHandData handData)
        {
            for (int i = 0; i < ArticulatedHandPose.JointCount; i++)
            {
                TrackedHandJoint handJoint = (TrackedHandJoint)i;

                if (!jointPoses.ContainsKey(handJoint))
                {
                    jointPoses.Add(handJoint, handData.Joints[i]);
                }
                else
                {
                    jointPoses[handJoint] = handData.Joints[i];
                }
            }

            CoreServices.InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, jointPoses);
        }
コード例 #11
0
        // Register input sources for hands based on changes of the data provider
        private void UpdateHandInputSource(Handedness handedness, SimulatedHandData handData)
        {
            var profile = InputSimulationProfile;

            if (profile.HandSimulationMode == HandSimulationMode.Disabled)
            {
                RemoveAllHandDevices();
            }
            else
            {
                if (handData != null && handData.IsTracked)
                {
                    SimulatedHand controller = GetOrAddHandDevice(handedness, profile.HandSimulationMode);
                    controller.UpdateState(handData);
                }
                else
                {
                    RemoveHandDevice(handedness);
                }
            }
        }
コード例 #12
0
        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];
                }
            }

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

            UpdateVelocity();

            UpdateInteractions(handData);
        }
コード例 #13
0
 // Register input sources for hands based on hand data
 protected void UpdateHandDevice(HandSimulationMode simulationMode, Handedness handedness, SimulatedHandData handData)
 {
     if (handData != null && handData.IsTracked)
     {
         SimulatedHand controller = GetOrAddHandDevice(handedness, simulationMode);
         controller.UpdateState(handData);
     }
     else
     {
         RemoveHandDevice(handedness);
     }
 }
コード例 #14
0
        /// <inheritdoc />
        protected override void UpdateInteractions(SimulatedHandData handData)
        {
            EnsureProfileSettings();

            Vector3 lastPosition = currentPosition;

            currentPosition          = jointPoses[TrackedHandJoint.IndexTip].Position;
            cumulativeDelta         += currentPosition - lastPosition;
            currentGripPose.Position = currentPosition;

            if (lastPosition != currentPosition)
            {
                CoreServices.InputSystem?.RaiseSourcePositionChanged(InputSource, this, currentPosition);
            }

            for (int i = 0; i < Interactions?.Length; i++)
            {
                switch (Interactions[i].InputType)
                {
                case DeviceInputType.SpatialGrip:
                    Interactions[i].PoseData = currentGripPose;
                    if (Interactions[i].Changed)
                    {
                        CoreServices.InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentGripPose);
                    }
                    break;

                case DeviceInputType.Select:
                    Interactions[i].BoolData = handData.IsPinching;

                    if (Interactions[i].Changed)
                    {
                        if (Interactions[i].BoolData)
                        {
                            CoreServices.InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);

                            SelectDownStartTime = Time.time;
                            cumulativeDelta     = Vector3.zero;
                        }
                        else
                        {
                            CoreServices.InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);

                            // Stop active gestures
                            TryCompleteSelect();
                            TryCompleteHold();
                            TryCompleteManipulation();
                            TryCompleteNavigation();
                        }
                    }
                    else if (Interactions[i].BoolData)
                    {
                        if (manipulationInProgress)
                        {
                            UpdateManipulation();
                        }
                        if (navigationInProgress)
                        {
                            UpdateNavigation();
                        }

                        if (cumulativeDelta.magnitude > navigationStartThreshold)
                        {
                            TryCancelHold();
                            TryStartNavigation();
                            TryStartManipulation();
                        }
                        else if (Time.time >= SelectDownStartTime + holdStartDuration)
                        {
                            TryStartHold();
                        }
                    }
                    break;
                }
            }
        }
コード例 #15
0
 /// <summary>
 /// Updates the positions and orientations of the hand joints of the simulated hand
 /// </summary>
 /// <param name="handData">hand data provided by the simulation</param>
 protected abstract void UpdateHandJoints(SimulatedHandData handData);
        /// <inheritdoc />
        protected override void UpdateInteractions(SimulatedHandData handData)
        {
            lastPointerPose = currentPointerPose;
            lastGripPose    = currentGripPose;

            // For convenience of simulating in Unity Editor, make the ray use the index
            // finger position instead of knuckle, since the index finger doesn't move when we press.
            Vector3 pointerPosition = jointPoses[TrackedHandJoint.IndexTip].Position;

            IsPositionAvailable = IsRotationAvailable = pointerPosition != Vector3.zero;

            if (IsPositionAvailable)
            {
                HandRay.Update(pointerPosition, GetPalmNormal(), CameraCache.Main.transform, ControllerHandedness);

                Ray ray = HandRay.Ray;

                currentPointerPose.Position = ray.origin;
                currentPointerPose.Rotation = Quaternion.LookRotation(ray.direction);

                currentGripPose = jointPoses[TrackedHandJoint.Palm];

                currentIndexPose = jointPoses[TrackedHandJoint.IndexTip];
            }

            if (lastGripPose != currentGripPose)
            {
                if (IsPositionAvailable && IsRotationAvailable)
                {
                    InputSystem?.RaiseSourcePoseChanged(InputSource, this, currentGripPose);
                }
                else if (IsPositionAvailable && !IsRotationAvailable)
                {
                    InputSystem?.RaiseSourcePositionChanged(InputSource, this, currentPointerPosition);
                }
                else if (!IsPositionAvailable && IsRotationAvailable)
                {
                    InputSystem?.RaiseSourceRotationChanged(InputSource, this, currentPointerRotation);
                }
            }

            for (int i = 0; i < Interactions?.Length; i++)
            {
                switch (Interactions[i].InputType)
                {
                case DeviceInputType.SpatialPointer:
                    Interactions[i].PoseData = currentPointerPose;
                    if (Interactions[i].Changed)
                    {
                        InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentPointerPose);
                    }
                    break;

                case DeviceInputType.SpatialGrip:
                    Interactions[i].PoseData = currentGripPose;
                    if (Interactions[i].Changed)
                    {
                        InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentGripPose);
                    }
                    break;

                case DeviceInputType.Select:
                    Interactions[i].BoolData = handData.IsPinching;

                    if (Interactions[i].Changed)
                    {
                        if (Interactions[i].BoolData)
                        {
                            InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);
                        }
                        else
                        {
                            InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);
                        }
                    }
                    break;

                case DeviceInputType.TriggerPress:
                    Interactions[i].BoolData = handData.IsPinching;

                    if (Interactions[i].Changed)
                    {
                        if (Interactions[i].BoolData)
                        {
                            InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);
                        }
                        else
                        {
                            InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);
                        }
                    }
                    break;

                case DeviceInputType.IndexFinger:
                    Interactions[i].PoseData = currentIndexPose;
                    if (Interactions[i].Changed)
                    {
                        InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentIndexPose);
                    }
                    break;
                }
            }
        }
コード例 #17
0
        protected override void UpdateInteractions(SimulatedHandData handData)
        {
            lastPosition             = currentPosition;
            currentPosition          = jointPositions[(int)TrackedHandJoint.IndexTip];
            currentGripPose.Position = currentPosition;
            if (lastPosition != currentPosition)
            {
                MixedRealityToolkit.InputSystem?.RaiseSourcePositionChanged(InputSource, this, currentPosition);
            }

            for (int i = 0; i < Interactions?.Length; i++)
            {
                switch (Interactions[i].InputType)
                {
                case DeviceInputType.SpatialGrip:
                    Interactions[i].PoseData = currentGripPose;
                    if (Interactions[i].Changed)
                    {
                        MixedRealityToolkit.InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentGripPose);
                    }
                    break;

                case DeviceInputType.Select:
                    Interactions[i].BoolData = handData.IsPinching;

                    if (Interactions[i].Changed)
                    {
                        if (Interactions[i].BoolData)
                        {
                            MixedRealityToolkit.InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);

                            SelectDownStartTime = Time.time;
                            cumulativeDelta     = Vector3.zero;
                        }
                        else
                        {
                            MixedRealityToolkit.InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction);

                            // Stop gestures
                            CompleteHoldGesture();
                            CompleteManipulationNavigationGesture();
                        }
                    }
                    else if (Interactions[i].BoolData)
                    {
                        // For convenience of simulating in Unity Editor, make the ray use the index
                        // finger position instead of knuckle, since the index finger doesn't move when we press.
                        Vector3 newPosition = jointPositions[(int)TrackedHandJoint.IndexTip];
                        cumulativeDelta += newPosition - currentPosition;
                        currentPosition  = newPosition;

                        if (!manipulationInProgress)
                        {
                            if (cumulativeDelta.magnitude > manipulationStartThreshold)
                            {
                                CancelHoldGesture();
                                StartManipulationNavigationGesture();
                            }
                            else if (!holdInProgress)
                            {
                                float time = Time.time;
                                if (time >= SelectDownStartTime + holdStartDuration)
                                {
                                    StartHoldGesture();
                                }
                            }
                        }
                        else
                        {
                            UpdateManipulationNavigationGesture();
                        }
                    }
                    break;
                }
            }
        }
コード例 #18
0
 protected abstract void UpdateInteractions(SimulatedHandData handData);