示例#1
0
        /// <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;
            }

            Profiler.BeginSample("[MRTK] WindowsMixedRealityArticulatedHand.UpdateHandData");

            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))
                {
#if WINDOWS_UWP
                    handDefinition?.UpdateHandMesh(sourceState);
#endif // WINDOWS_UWP

                    HandPose handPose = sourceState.TryGetHandPose();

                    if (handPose != null && handPose.TryGetJoints(WindowsMixedRealityUtilities.SpatialCoordinateSystem, jointIndices, jointPoses))
                    {
                        for (int i = 0; i < jointPoses.Length; i++)
                        {
                            Vector3    jointPosition    = jointPoses[i].Position.ToUnityVector3();
                            Quaternion jointOrientation = jointPoses[i].Orientation.ToUnityQuaternion();

                            // We want the joints to follow the playspace, so fold in the playspace transform here to
                            // put the joint pose into world space.
                            jointPosition    = MixedRealityPlayspace.TransformPoint(jointPosition);
                            jointOrientation = MixedRealityPlayspace.Rotation * jointOrientation;

                            TrackedHandJoint handJoint = ConvertHandJointKindToTrackedHandJoint(jointIndices[i]);

                            if (handJoint == TrackedHandJoint.IndexTip)
                            {
                                lastIndexTipRadius = jointPoses[i].Radius;
                            }

                            unityJointPoses[handJoint] = new MixedRealityPose(jointPosition, jointOrientation);
                        }

                        handDefinition?.UpdateHandJoints(unityJointPoses);
                    }
                    break;
                }
            }

            Profiler.EndSample(); // UpdateHandData
#endif // WINDOWS_UWP || DOTNETWINRT_PRESENT
        }
        private bool GetHistoricalPose(out Vector3 cameraPosition, out Quaternion cameraRotation)
        {
#if !UNITY_EDITOR && UNITY_WSA
            SpatialCoordinateSystem unityCoordinateSystem = Marshal.GetObjectForIUnknown(WorldManager.GetNativeISpatialCoordinateSystemPtr()) as SpatialCoordinateSystem;
            if (unityCoordinateSystem == null)
            {
                Debug.LogError("Failed to get the native SpatialCoordinateSystem");
                cameraPosition = default(Vector3);
                cameraRotation = default(Quaternion);
                return(false);
            }

            if (timeConversionCalendar == null)
            {
                timeConversionCalendar = new Calendar();
            }

            timeConversionCalendar.SetToNow();

            PerceptionTimestamp perceptionTimestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(timeConversionCalendar.GetDateTime());

            if (perceptionTimestamp != null)
            {
                SpatialLocator locator = SpatialLocator.GetDefault();
                if (locator != null)
                {
                    SpatialLocation headPose = locator.TryLocateAtTimestamp(perceptionTimestamp, unityCoordinateSystem);
                    if (headPose != null)
                    {
                        var systemOrientation = headPose.Orientation;
                        var systemPostion     = headPose.Position;

                        // Convert the orientation and position from Windows to Unity coordinate spaces
                        cameraRotation.x = -systemOrientation.X;
                        cameraRotation.y = -systemOrientation.Y;
                        cameraRotation.z = systemOrientation.Z;
                        cameraRotation.w = systemOrientation.W;

                        cameraPosition.x = systemPostion.X;
                        cameraPosition.y = systemPostion.Y;
                        cameraPosition.z = -systemPostion.Z;
                        return(true);
                    }
                }
            }

            cameraPosition = default(Vector3);
            cameraRotation = default(Quaternion);
            return(false);
#else
            cameraPosition = Camera.main.transform.position;
            cameraRotation = Camera.main.transform.rotation;
            return(true);
#endif
        }
        /// <summary>
        /// Gets currently detected <see cref="SpatialInteractionSource"/>s. This list may
        /// differ from the data provider's internal <see cref="activeControllers"/> registry.
        /// </summary>
        /// <returns>List of tracked <see cref="SpatialInteractionSource"/>s.</returns>
        private IReadOnlyList <SpatialInteractionSourceState> GetDetectedSources()
        {
            if (WindowsMixedRealityUtilities.SpatialInteractionManager == null)
            {
                return(new List <SpatialInteractionSourceState>());
            }

            var perceptionTimestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now);

            return(WindowsMixedRealityUtilities.SpatialInteractionManager.GetDetectedSourcesAtTimestamp(perceptionTimestamp));
        }
示例#4
0
    // TODO: which is the smoothest experience?  FixedUpdate for physics, or LateUpdate/Prerender for more accurate onscreen representation
    // (or if we move away from physics, then see if LateUpdate is just better.
    private void FixedUpdate()
    {
#if WINDOWS_UWP
        PerceptionTimestamp perceptionTimestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(
            DateTimeOffset.Now + TimeSpan.FromSeconds(Time.fixedDeltaTime * 3.0f));

        if (!UpdateAtTime(perceptionTimestamp))
        {
            // prediction failed, fall back to current timestamp
            UpdateAtTime(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
        }
#endif
    }
示例#5
0
    private void UpdateHands()
    {
        PerceptionTimestamp perceptionTimestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now);
        IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager?.GetDetectedSourcesAtTimestamp(perceptionTimestamp);

        foreach (SpatialInteractionSourceState sourceState in sources)
        {
            HandPose handPose = sourceState.TryGetHandPose();
            if (handPose != null && handPose.TryGetJoints(SpatialCoordinateSystem, jointIndices, jointPoses))
            {
                SpatialInteractionSourceHandedness handIndex = sourceState.Source.Handedness;
                if (handIndex == SpatialInteractionSourceHandedness.Left)
                {
                    ApplyTransforms(leftHandProxy, jointPoses);
                }
                else
                {
                    ApplyTransforms(rightHandProxy, jointPoses);
                }
            }
        }
    }
示例#6
0
        private async Task GetController()
        {
            var access = await VibrationDevice.RequestAccessAsync();

            if (access == VibrationAccessStatus.Allowed)
            {
                var mgr       = SpatialInteractionManager.GetForCurrentView();
                var calendar  = new Calendar();
                var timestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(calendar.GetDateTime());
                controller = (from s in mgr.GetDetectedSourcesAtTimestamp(timestamp)
                              where s.Source.Id == ControllerID
                              select s.Source.Controller.SimpleHapticsController)
                             .FirstOrDefault();
                expressions = new Dictionary <ushort, SimpleHapticsControllerFeedback>(5);
                if (controller != null)
                {
                    foreach (var fb in controller.SupportedFeedback)
                    {
                        if (fb.Waveform == KnownSimpleHapticsControllerWaveforms.BuzzContinuous)
                        {
                            buzz = fb;
                        }
                        else if (fb.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
                        {
                            click = fb;
                        }
                        else if (fb.Waveform == KnownSimpleHapticsControllerWaveforms.Press)
                        {
                            press = fb;
                        }
                        else if (fb.Waveform == KnownSimpleHapticsControllerWaveforms.Release)
                        {
                            release = fb;
                        }
                        expressions[fb.Waveform] = fb;
                    }
                }
            }
        }
示例#7
0
    // Update is called once per frame
    void Update()
    {
#if ENABLE_WINMD_SUPPORT
        if (!_isReadyToRender)
        {
            return;
        }

        // The HolographicFrame has information that the app needs in order
        // to update and render the current frame. The app begins each new
        // frame by calling CreateNextFrame.
        //HolographicFrame ^ holographicFrame = m_holographicSpace->CreateNextFrame();

        // Get a prediction of where holographic cameras will be when this frame
        // is presented.
        //HolographicFramePrediction prediction = holographicFrame->CurrentPrediction;

        IntPtr spatialCoordinateSystemPtr               = WorldManager.GetNativeISpatialCoordinateSystemPtr();
        SpatialCoordinateSystem unityWorldOrigin        = Marshal.GetObjectForIUnknown(spatialCoordinateSystemPtr) as SpatialCoordinateSystem;
        SpatialCoordinateSystem currentCoordinateSystem = unityWorldOrigin;

        _isTrackingFaces = _faceTrackerProcessor.IsTrackingFaces();

        if (_isTrackingFaces)
        {
            MediaFrameReference frame = _videoFrameProcessor.GetLatestFrame();
            if (frame == null)
            {
                return;
            }
            var faces = _faceTrackerProcessor.GetLatestFaces();
            ProcessFaces(faces, frame, currentCoordinateSystem);


            TimeSpan currentTimeStamp = frame.SystemRelativeTime.Value.Duration();
            if (currentTimeStamp > _previousFrameTimestamp)
            {
                // TODO: copy to texture
                _previousFrameTimestamp = frame.SystemRelativeTime.Value.Duration();
            }
        }

        SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(currentCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
#endif
    }
        /// <inheritdoc />
        public override void Update()
        {
            // Override gaze before base.Update() updates the controllers
            if (mixedRealityGazeProviderHeadOverride != null && mixedRealityGazeProviderHeadOverride.UseHeadGazeOverride && WindowsMixedRealityUtilities.SpatialCoordinateSystem != null)
            {
                SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(WindowsMixedRealityUtilities.SpatialCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
                if (pointerPose != null)
                {
                    HeadPose head = pointerPose.Head;
                    if (head != null)
                    {
                        mixedRealityGazeProviderHeadOverride.OverrideHeadGaze(head.Position.ToUnityVector3(), head.ForwardDirection.ToUnityVector3());
                    }
                }
            }

            base.Update();
        }
示例#9
0
        public override void Update()
        {
#if UNITY_WSA
            if (WindowsMixedRealityUtilities.SpatialCoordinateSystem == null || typeof(SpatialPointerPose).GetProperty("Eyes") == null)
            {
                return;
            }

            SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(WindowsMixedRealityUtilities.SpatialCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
            if (pointerPose != null)
            {
                var eyes = pointerPose.Eyes;
                if (eyes != null)
                {
                    InputSystem?.EyeGazeProvider?.UpdateEyeTrackingStatus(this, eyes.IsCalibrationValid);

                    if (eyes.Gaze.HasValue)
                    {
                        Ray newGaze = new Ray(WindowsMixedRealityUtilities.SystemVector3ToUnity(eyes.Gaze.Value.Origin), WindowsMixedRealityUtilities.SystemVector3ToUnity(eyes.Gaze.Value.Direction));

                        if (SmoothEyeTracking)
                        {
                            newGaze = SmoothGaze(newGaze);
                        }

                        InputSystem?.EyeGazeProvider?.UpdateEyeGaze(this, newGaze, eyes.UpdateTimestamp.TargetTime.UtcDateTime);
                    }
                }
            }
#endif // UNITY_WSA
        }
        public override void Update()
        {
#if WINDOWS_UWP
            if (WindowsMixedRealityUtilities.SpatialCoordinateSystem == null || !WindowsApiChecker.UniversalApiContractV8_IsAvailable)
            {
                return;
            }

            SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(WindowsMixedRealityUtilities.SpatialCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
            if (pointerPose != null)
            {
                var eyes = pointerPose.Eyes;
                if ((eyes != null) && (eyes.Gaze.HasValue))
                {
                    Ray newGaze = new Ray(WindowsMixedRealityUtilities.SystemVector3ToUnity(eyes.Gaze.Value.Origin), WindowsMixedRealityUtilities.SystemVector3ToUnity(eyes.Gaze.Value.Direction));

                    if (SmoothEyeTracking)
                    {
                        newGaze = SmoothGaze(newGaze);
                    }

                    InputSystem?.EyeGazeProvider?.UpdateEyeGaze(this, newGaze, eyes.UpdateTimestamp.TargetTime.UtcDateTime);
                }
            }
#endif // WINDOWS_UWP
        }
        public static IAsyncOperation <IRandomAccessStreamWithContentType> TryGetRenderableModelAsync(this InteractionSource interactionSource)
        {
            IAsyncOperation <IRandomAccessStreamWithContentType> returnValue = null;

            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));

                foreach (SpatialInteractionSourceState sourceState in sources)
                {
                    if (sourceState.Source.Id.Equals(interactionSource.id))
                    {
                        //Build error
                        //returnValue = sourceState.Source.Controller.TryGetRenderableModelAsync();
                    }
                }
            }, true);

            return(returnValue);
        }
        public static void StopHaptics(this InteractionSource interactionSource)
        {
            if (!WindowsApiChecker.UniversalApiContractV4_IsAvailable && !Application.isEditor)
            {
                return;
            }

#if !UNITY_EDITOR
            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));

                foreach (SpatialInteractionSourceState sourceState in sources)
                {
                    if (sourceState.Source.Id.Equals(interactionSource.id))
                    {
                        sourceState.Source.Controller.SimpleHapticsController.StopFeedback();
                    }
                }
            }, true);
#elif UNITY_EDITOR_WIN
            StopHaptics(interactionSource.id);
#endif // !UNITY_EDITOR
        }
        /// <summary>
        /// Gets the current native SpatialInteractionSourceState for this InteractionSource.
        /// </summary>
        /// <param name="interactionSource">This InteractionSource to search for via the native Windows APIs.</param>
        /// <returns>The current native SpatialInteractionSourceState.</returns>
        public static SpatialInteractionSourceState GetSpatialInteractionSourceState(this InteractionSource interactionSource)
        {
            IReadOnlyList <SpatialInteractionSourceState> sources = WindowsMixedRealityUtilities.SpatialInteractionManager?.GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.UtcNow));

            for (var i = 0; i < sources?.Count; i++)
            {
                if (sources[i].Source.Id.Equals(interactionSource.id))
                {
                    return(sources[i]);
                }
            }

            return(null);
        }
        private IAsyncOperation <IRandomAccessStreamWithContentType> TryGetRenderableModelAsync(uint interactionSourceId)
        {
            IAsyncOperation <IRandomAccessStreamWithContentType> returnValue = null;

            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                var sources = SpatialInteractionManager.GetForCurrentView()?.GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
                if (sources != null)
                {
                    foreach (SpatialInteractionSourceState sourceState in sources)
                    {
                        if (sourceState.Source.Id.Equals(interactionSourceId))
                        {
                            returnValue = sourceState.Source.Controller.TryGetRenderableModelAsync();
                        }
                    }
                }
            }, true);

            return(returnValue);
        }
示例#15
0
        public override void StartHaptics(float normalizedIntensity, float durationInSeconds)
        {
#if !UNITY_EDITOR && UNITY_2017_2_OR_NEWER && UNITY_WSA
            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager
                                                                        .GetForCurrentView()
                                                                        .GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper
                                                                                                       .FromHistoricalTargetTime(DateTimeOffset
                                                                                                                                 .Now));

                foreach (SpatialInteractionSourceState sourceState in sources)
                {
                    if (sourceState.Source.Id.Equals(_interactionSourceId))
                    {
                        SimpleHapticsController simpleHapticsController = sourceState
                                                                          .Source
                                                                          .Controller
                                                                          .SimpleHapticsController;

                        foreach (SimpleHapticsControllerFeedback hapticsFeedback in simpleHapticsController.SupportedFeedback)
                        {
                            if (hapticsFeedback.Waveform.Equals(ContinuousBuzzWaveform))
                            {
                                if (durationInSeconds.Equals(float.MaxValue))
                                {
                                    simpleHapticsController.SendHapticFeedback(hapticsFeedback, intensity);
                                }
                                else
                                {
                                    simpleHapticsController.SendHapticFeedbackForDuration(
                                        hapticsFeedback,
                                        intensity,
                                        TimeSpan.FromSeconds(durationInSeconds));
                                }
                                return;
                            }
                        }
                    }
                }
            }, true);
#endif
        }
        /// <inheritdoc/>
        public override void Update()
        {
            Profiler.BeginSample("[MRTK] WindowsMixedRealityDeviceManager.Update");

            base.Update();

#if (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP
            if (mixedRealityGazeProviderHeadOverride != null && mixedRealityGazeProviderHeadOverride.UseHeadGazeOverride)
            {
                SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(WindowsMixedRealityUtilities.SpatialCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
                if (pointerPose != null)
                {
                    HeadPose head = pointerPose.Head;
                    if (head != null)
                    {
                        mixedRealityGazeProviderHeadOverride.OverrideHeadGaze(head.Position.ToUnityVector3(), head.ForwardDirection.ToUnityVector3());
                    }
                }
            }
#endif // (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP

            UpdateInteractionManagerReading();

            for (var i = 0; i < numInteractionManagerStates; i++)
            {
                // SourceDetected gets raised when a new controller is detected and, if previously present,
                // when OnEnable is called. Do not create a new controller here.
                var controller = GetOrAddController(interactionManagerStates[i].source, false);

                if (controller != null)
                {
                    controller.UpdateController(interactionManagerStates[i]);
                }
            }

            LastInteractionManagerStateReading = interactionManagerStates;

            Profiler.EndSample(); // Update
        }
示例#17
0
        /// <summary>
        /// Function which checks for new eye tracking data and is called periodically by the timer
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void CheckForEyeData(object source, ElapsedEventArgs e)
        {
            // Make sure the previous event isn't still running
            if (System.Threading.Interlocked.CompareExchange(ref fetchDataTimerIsBusy, 1, 0) == 1)
            {
                //Debug.LogError("Previous event still running!");
                return;
            }

            try {
#if (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP
                // Make sure we have the spatial coordinate system (which is cached every update) and the eyes API is available
                if (currentSpatialCoordinateSystem == null || !EyesApiAvailable)
                {
                    //Debug.Log("[UWPDataAccess] No currentSpatialCoordinateSystem or Eyes API not available!");
                    return;
                }

                // Try to get the new pointer data (which includes eye tracking)
                SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(currentSpatialCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
                if (pointerPose != null)
                {
                    // Check if we actually got any eye tracking data
                    var eyes = pointerPose.Eyes;
                    if (eyes != null)
                    {
                        // Unix time stamp from when the eye tracking data we got was acquired
                        long targetTimeUnix = eyes.UpdateTimestamp.TargetTime.ToUnixTimeMilliseconds();

                        // Check if we have new data
                        if (lastEyeDataTimestamp != targetTimeUnix)
                        {
                            // Save new time stamp
                            lastEyeDataTimestamp = targetTimeUnix;

                            // Save the information whether the calibration is valid
                            IsGazeCalibrationValid = eyes.IsCalibrationValid;

                            // If we have eye tracking data announce it in the event, otherwise simply announce Vector3.zero as origin and direction
                            if (eyes.Gaze.HasValue)
                            {
                                dataQueue.Enqueue(new GazeAPIData()
                                {
                                    EyeDataTimestamp         = targetTimeUnix,
                                    EyeDataRelativeTimestamp = eyes.UpdateTimestamp.SystemRelativeTargetTime.TotalMilliseconds,
                                    IsCalibrationValid       = eyes.IsCalibrationValid,
                                    GazeHasValue             = eyes.Gaze.HasValue,
                                    GazeOrigin    = eyes.Gaze.Value.Origin.ToUnityVector3(),
                                    GazeDirection = eyes.Gaze.Value.Direction.ToUnityVector3()
                                });
                            }
                            else
                            {
                                dataQueue.Enqueue(new GazeAPIData()
                                {
                                    EyeDataTimestamp         = targetTimeUnix,
                                    EyeDataRelativeTimestamp = eyes.UpdateTimestamp.SystemRelativeTargetTime.TotalMilliseconds,
                                    IsCalibrationValid       = eyes.IsCalibrationValid,
                                    GazeHasValue             = eyes.Gaze.HasValue,
                                    GazeOrigin    = Vector3.zero,
                                    GazeDirection = Vector3.zero
                                });
                            }
                        }
                    }
                }
#else
                // On all platforms which are not UWP print error
                Debug.Log("[UWPDataAccess] Not on correct platform! Doing nothing!");
#endif
            }
            finally
            {
                fetchDataTimerIsBusy = 0;
            }
        }
示例#18
0
        /// <summary>
        /// Tries to get an active SpatialInteractionSource with the corresponding handedness and input source type.
        /// </summary>
        /// <param name="handedness">The handedness of the source to get.</param>
        /// <param name="inputSourceType">The input source type of the source to get.</param>
        /// <returns>The input source or null if none could be found.</returns>
        public static SpatialInteractionSource GetSpatialInteractionSource(Handedness handedness, InputSourceType inputSourceType)
        {
            SpatialInteractionSourceHandedness sourceHandedness;

            switch (handedness)
            {
            default:
                sourceHandedness = SpatialInteractionSourceHandedness.Unspecified;
                break;

            case Handedness.Left:
                sourceHandedness = SpatialInteractionSourceHandedness.Left;
                break;

            case Handedness.Right:
                sourceHandedness = SpatialInteractionSourceHandedness.Right;
                break;
            }

            SpatialInteractionSourceKind sourceKind;

            switch (inputSourceType)
            {
            default:
                sourceKind = SpatialInteractionSourceKind.Other;
                break;

            case InputSourceType.Controller:
                sourceKind = SpatialInteractionSourceKind.Controller;
                break;

            case InputSourceType.Hand:
                sourceKind = SpatialInteractionSourceKind.Hand;
                break;
            }

            System.Collections.Generic.IReadOnlyList <SpatialInteractionSourceState> sourceStates =
                WindowsMixedRealityUtilities.SpatialInteractionManager?.GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(System.DateTimeOffset.UtcNow));

            if (sourceStates == null)
            {
                return(null);
            }

            foreach (SpatialInteractionSourceState sourceState in sourceStates)
            {
                if (sourceState.Source.Handedness == sourceHandedness && sourceState.Source.Kind == sourceKind)
                {
                    return(sourceState.Source);
                }
            }

            return(null);
        }
示例#19
0
        public static IAsyncOperation <IRandomAccessStreamWithContentType> TryGetRenderableModelAsync(this InteractionSource interactionSource)
        {
            IAsyncOperation <IRandomAccessStreamWithContentType> returnValue = null;

            // GetForCurrentView and GetDetectedSourcesAtTimestamp were both introduced in the same Windows version.
            // We need only check for one of them.
            if (WindowsApiChecker.IsMethodAvailable(
                    "Windows.UI.Input.Spatial",
                    "SpatialInteractionManager",
                    "GetForCurrentView"))
            {
                IReadOnlyList <SpatialInteractionSourceState> sources = null;

                UnityEngine.WSA.Application.InvokeOnUIThread(() =>
                {
                    sources = SpatialInteractionManager.GetForCurrentView()?.GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
                }, true);

                for (var i = 0; i < sources?.Count; i++)
                {
                    if (sources[i].Source.Id.Equals(interactionSource.id))
                    {
                        returnValue = sources[i].Source.Controller.TryGetRenderableModelAsync();
                    }
                }
            }

            return(returnValue);
        }
示例#20
0
        public override void Initialize(Chirality chirality)
        {
#if !UNITY_EDITOR && UNITY_2017_2_OR_NEWER && UNITY_WSA
            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager
                                                                        .GetForCurrentView()
                                                                        .GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper
                                                                                                       .FromHistoricalTargetTime(DateTimeOffset
                                                                                                                                 .Now));

                foreach (SpatialInteractionSourceState sourceState in sources)
                {
                    if (sourceState.Source.Handedness == SpatialInteractionSourceHandedness.Left && chirality == Chirality.Left)
                    {
                        _interactionSourceId = sourceState.Source.Id;
                    }
                    if (sourceState.Source.Handedness == SpatialInteractionSourceHandedness.Right && chirality == Chirality.Right)
                    {
                        _interactionSourceId = sourceState.Source.Id;
                    }
                }
            }, true);
#endif
        }
示例#21
0
        /// <inheritdoc />
        public override void Update()
        {
            using (UpdatePerfMarker.Auto())
            {
                if (WindowsMixedRealityUtilities.SpatialCoordinateSystem == null || !eyesApiAvailable)
                {
                    return;
                }

                SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(WindowsMixedRealityUtilities.SpatialCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
                if (pointerPose != null)
                {
                    var eyes = pointerPose.Eyes;
                    if (eyes != null)
                    {
                        Service?.EyeGazeProvider?.UpdateEyeTrackingStatus(this, eyes.IsCalibrationValid);

                        if (eyes.Gaze.HasValue)
                        {
                            Ray newGaze = new Ray(eyes.Gaze.Value.Origin.ToUnityVector3(), eyes.Gaze.Value.Direction.ToUnityVector3());

                            if (SmoothEyeTracking)
                            {
                                newGaze = SmoothGaze(newGaze);
                            }

                            Service?.EyeGazeProvider?.UpdateEyeGaze(this, newGaze, eyes.UpdateTimestamp.TargetTime.UtcDateTime);
                        }
                    }
                }
            }
        }
示例#22
0
        public override void StopHaptics()
        {
#if !UNITY_EDITOR && UNITY_2017_2_OR_NEWER && UNITY_WSA
            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager
                                                                        .GetForCurrentView()
                                                                        .GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper
                                                                                                       .FromHistoricalTargetTime(DateTimeOffset
                                                                                                                                 .Now));

                foreach (SpatialInteractionSourceState sourceState in sources)
                {
                    if (sourceState.Source.Id.Equals(_interactionSourceId))
                    {
                        sourceState.Source.Controller.SimpleHapticsController.StopFeedback();
                    }
                }
            }, true);
#endif
        }
示例#23
0
        /// <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 static IAsyncOperation <IRandomAccessStreamWithContentType> TryGetRenderableModelAsync(this InteractionSource interactionSource)
        {
            IAsyncOperation <IRandomAccessStreamWithContentType> returnValue = null;

            if (WindowsApiChecker.UniversalApiContractV5_IsAvailable)
            {
                UnityEngine.WSA.Application.InvokeOnUIThread(() =>
                {
                    IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));

                    for (var i = 0; i < sources.Count; i++)
                    {
                        if (sources[i].Source.Id.Equals(interactionSource.id))
                        {
                            returnValue = sources[i].Source.Controller.TryGetRenderableModelAsync();
                        }
                    }
                }, true);
            }

            return(returnValue);
        }
        public static void StartHaptics(this InteractionSource interactionSource, float intensity, float durationInSeconds)
        {
            if (!WindowsApiChecker.UniversalApiContractV4_IsAvailable && !Application.isEditor)
            {
                return;
            }

#if !UNITY_EDITOR
            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));

                foreach (SpatialInteractionSourceState sourceState in sources)
                {
                    if (sourceState.Source.Id.Equals(interactionSource.id))
                    {
                        SimpleHapticsController simpleHapticsController = sourceState.Source.Controller.SimpleHapticsController;
                        foreach (SimpleHapticsControllerFeedback hapticsFeedback in simpleHapticsController.SupportedFeedback)
                        {
                            if (hapticsFeedback.Waveform.Equals(ContinuousBuzzWaveform))
                            {
                                if (durationInSeconds.Equals(float.MaxValue))
                                {
                                    simpleHapticsController.SendHapticFeedback(hapticsFeedback, intensity);
                                }
                                else
                                {
                                    simpleHapticsController.SendHapticFeedbackForDuration(hapticsFeedback, intensity, TimeSpan.FromSeconds(durationInSeconds));
                                }
                                return;
                            }
                        }
                    }
                }
            }, true);
#elif UNITY_EDITOR_WIN
            StartHaptics(interactionSource.id, intensity, durationInSeconds);
#endif // !UNITY_EDITOR
        }
示例#26
0
        /// <inheritdoc />
        public override void Update()
        {
#if (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP
            if (WindowsMixedRealityUtilities.SpatialCoordinateSystem == null || !eyesApiAvailable)
            {
                return;
            }

            SpatialPointerPose pointerPose = SpatialPointerPose.TryGetAtTimestamp(WindowsMixedRealityUtilities.SpatialCoordinateSystem, PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
            if (pointerPose != null)
            {
                var eyes = pointerPose.Eyes;
                if (eyes != null)
                {
                    InputSystem?.EyeGazeProvider?.UpdateEyeTrackingStatus(this, eyes.IsCalibrationValid);

                    if (eyes.Gaze.HasValue)
                    {
                        Ray newGaze = new Ray(eyes.Gaze.Value.Origin.ToUnityVector3(), eyes.Gaze.Value.Direction.ToUnityVector3());

                        if (SmoothEyeTracking)
                        {
                            newGaze = SmoothGaze(newGaze);
                        }

                        InputSystem?.EyeGazeProvider?.UpdateEyeGaze(this, newGaze, eyes.UpdateTimestamp.TargetTime.UtcDateTime);
                    }
                }
            }
#endif // (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP
        }
示例#27
0
        /// <summary>
        ///     Updates the application state once per frame.
        /// </summary>
        public HolographicFrame Update()
        {
            // Before doing the timer update, there is some work to do per-frame
            // to maintain holographic rendering. First, we will get information
            // about the current frame.

            // The HolographicFrame has information that the app needs in order
            // to update and render the current frame. The app begins each new
            // frame by calling CreateNextFrame.
            var holographicFrame = holographicSpace.CreateNextFrame();

            // Get a prediction of where holographic cameras will be when this frame
            // is presented.
            var prediction = holographicFrame.CurrentPrediction;

            // Back buffers can change from frame to frame. Validate each buffer, and recreate
            // resource views and depth buffers as needed.
            deviceResources.EnsureCameraResources(holographicFrame, prediction);

            // Next, we get a coordinate system from the attached frame of reference that is
            // associated with the current frame. Later, this coordinate system is used for
            // for creating the stereo view matrices when rendering the sample content.
            var currentCoordinateSystem = referenceFrame.CoordinateSystem;

#if DRAW_SAMPLE_CONTENT
            // Check for new input state since the last frame.
            var pointerState = spatialInputHandler.CheckForInput();
            if (null != pointerState)
            {
                // When a Pressed gesture is detected, the sample hologram will be repositioned
                // two meters in front of the user.
                spinningCubeRenderer.PositionHologram(
                    pointerState.TryGetPointerPose(currentCoordinateSystem)
                    );
            }
#endif

            timer.Tick(() =>
            {
                //
                // TODO: Update scene objects.
                //
                // Put time-based updates here. By default this code will run once per frame,
                // but if you change the StepTimer to use a fixed time step this code will
                // run as many times as needed to get to the current step.
                //

#if DRAW_SAMPLE_CONTENT
                spinningCubeRenderer.Update(timer);
                var perceptionTimestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now);
                var spatialPointerPose  = SpatialPointerPose.TryGetAtTimestamp(currentCoordinateSystem,
                                                                               perceptionTimestamp);
                _holoCursor.PositionHologram(spatialPointerPose);
                _holoCursor.Update(spatialPointerPose);
#endif
            });

            // We complete the frame update by using information about our content positioning
            // to set the focus point.
            foreach (var cameraPose in prediction.CameraPoses)
            {
#if DRAW_SAMPLE_CONTENT
                // The HolographicCameraRenderingParameters class provides access to set
                // the image stabilization parameters.
                var renderingParameters = holographicFrame.GetRenderingParameters(cameraPose);

                // SetFocusPoint informs the system about a specific point in your scene to
                // prioritize for image stabilization. The focus point is set independently
                // for each holographic camera.
                // You should set the focus point near the content that the user is looking at.
                // In this example, we put the focus point at the center of the sample hologram,
                // since that is the only hologram available for the user to focus on.
                // You can also set the relative velocity and facing of that content; the sample
                // hologram is at a fixed point so we only need to indicate its position.
                renderingParameters.SetFocusPoint(
                    currentCoordinateSystem,
                    spinningCubeRenderer.Position
                    );
#endif
            }

            // The holographic frame will be used to get up-to-date view and projection matrices and
            // to present the swap chain.
            return(holographicFrame);
        }