コード例 #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
        }
コード例 #2
0
        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
        }
コード例 #3
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
    }
コード例 #4
0
    private bool UpdateAtTime(PerceptionTimestamp timestamp)
    {
        IReadOnlyList <SpatialInteractionSourceState> sources = SpatialInteractionManager?.GetDetectedSourcesAtTimestamp(timestamp);

        bool leftHandFound  = false;
        bool rightHandFound = false;

        foreach (var source in sources)
        {
            if (source.Source.Kind == SpatialInteractionSourceKind.Hand)
            {
                var handPose = source.TryGetHandPose();
                if (handPose != null)
                {
                    int handIdx = HandednessToIndex(source.Source.Handedness);

                    if (source.Source.Handedness == SpatialInteractionSourceHandedness.Right)
                    {
                        rightHandFound = true;
                    }
                    else if (source.Source.Handedness == SpatialInteractionSourceHandedness.Left)
                    {
                        leftHandFound = true;
                    }

                    UpdateHand(handPose, source.Source.Handedness);
                }
            }
        }

        if (!leftHandFound)
        {
            foreach (var go in leftHandObjects)
            {
                go.SetActive(false);
            }
        }

        if (!rightHandFound)
        {
            foreach (var go in rightHandObjects)
            {
                go.SetActive(false);
            }
        }

        return(rightHandFound || leftHandFound);
    }
        Node AddNode(SpatialAnchor anchor, PerceptionTimestamp perceptionTimestamp)
        {
            var position = Vector3.Zero;
            var forward  = Vector3.Zero;

            var anchorPose = SpatialPointerPose.TryGetAtTimestamp(anchor.CoordinateSystem, perceptionTimestamp);

            if (anchorPose != null)
            {
                position = anchorPose.Head.Position;
                forward  = anchorPose.Head.ForwardDirection;
            }

            var node = new Node(anchor, position, forward);

            nodes.Add(node);

            return(node);
        }
コード例 #6
0
        public void Update(PerceptionTimestamp timeStamp, SpatialCoordinateSystem coordinateSystem)
        {
            var states = interactionManager.GetDetectedSourcesAtTimestamp(timeStamp);

            foreach (SpatialInteractionSourceState state in states)
            {
                if (state.Source.Handedness == hand)
                {
                    SpatialInteractionSourceLocation location = state.Properties.TryGetLocation(coordinateSystem);

                    if (location != null)
                    {
                        SetSpatialInteractionSourceLocation(location);
                    }

                    previousState = currentState;
                    currentState  = state;

                    internalState = previousState != null ? DeviceState.Valid : DeviceState.Invalid;
                }
            }
        }
コード例 #7
0
ファイル: Hands.cs プロジェクト: GregBahm/HandBasedUi
    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);
                }
            }
        }
    }
コード例 #8
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
        }
        Node UpdateCurrentNode(SpatialCoordinateSystem referenceFrameCoordinateSystem, PerceptionTimestamp perceptionTimestamp, float nodeRadius = 1.0f)
        {
            SpatialPointerPose pose = SpatialPointerPose.TryGetAtTimestamp(referenceFrameCoordinateSystem, perceptionTimestamp);

            if (pose == null)
            {
                return(currentNode);
            }

            if (currentNode == null)
            {
                // create current node
                var nodeAnchor = Spatial​Anchor.TryCreateRelativeTo(referenceFrameCoordinateSystem, pose.Head.ForwardDirection * 0.1f);

                if (nodeAnchor == null)
                {
                    Debug.WriteLine($"WARN: Failed to create Anchor");
                    return(null);
                }

                Debug.WriteLine($"Creating new node Head position {pose.Head.Position} and direction {pose.Head.ForwardDirection}");

                AddNode(nodeAnchor, perceptionTimestamp);

                return(nodes[nodes.Count - 1]);
            }
            else
            {
                // outside the current nodes threshold?
                var distance = currentNode.TryGetDistance(referenceFrameCoordinateSystem, pose.Head.Position);
                if (distance.HasValue && distance.Value > nodeRadius)
                {
                    // search for node
                    var closestNodes = GetClosestNodes(referenceFrameCoordinateSystem, pose, nodeRadius);
                    if (closestNodes != null && closestNodes.Count > 0)
                    {
                        foreach (var node in closestNodes)
                        {
                            if (node == currentNode)
                            {
                                continue;
                            }

                            return(node);
                        }
                    }

                    // no node exist... try to create one
                    // position of current node in respect to the reference frame
                    var currentNodesPosition = currentNode.TryGetTransformedPosition(referenceFrameCoordinateSystem);
                    if (currentNodesPosition.HasValue)
                    {
                        var direction = Vector3.Normalize(
                            new Vector3(pose.Head.Position.X, 0f, pose.Head.Position.Z) -
                            new Vector3(currentNodesPosition.Value.X, 0f, currentNodesPosition.Value.Z)
                            );

                        var targetPosition   = currentNodesPosition.Value + direction * nodeRadius;
                        var distanceFromPose = (targetPosition - new Vector3(pose.Head.Position.X, 0f, pose.Head.Position.Z)).Length();

                        var nodeAnchor = Spatial​Anchor.TryCreateRelativeTo(referenceFrameCoordinateSystem, (direction * distanceFromPose));

                        if (nodeAnchor != null)
                        {
                            var newNode = AddNode(nodeAnchor, perceptionTimestamp);

                            // create a new edge connecting the current node and this node
                            edges.Add(new Edge
                            {
                                NodeA = currentNode,
                                NodeB = newNode
                            });

                            Debug.WriteLine($"Creating new node ({newNode.Name}) Head position {pose.Head.Position} and direction {pose.Head.ForwardDirection}, direction from current node {direction}.. Edge created {currentNode.Name}");
                            return(nodes[nodes.Count - 1]);
                        }
                        else
                        {
                            Debug.WriteLine($"WARN: Failed to create Anchor");
                        }
                    }
                }
            }

            return(currentNode);
        }
        int RebuildTrailToTarget(SpatialCoordinateSystem referenceFrameCoordinateSystem, PerceptionTimestamp perceptionTimestamp, Node startNode, Node endNode,
                                 int lookAhead = 100)
        {
            Debug.WriteLine($"RebuildTrailToTarget {startNode.Name} -> {endNode.Name}");

            entities.Clear();

            Stack <Node> trail = new Stack <Node>();

            BuildPath(endNode, startNode, trail);

            if (trail.Count == 0)
            {
                Debug.WriteLine($"Unable to find Path for startNode {startNode.Name} and {endNode.Name}");
                return(-1);
            }

            var rootEntity = GetRootEntity(referenceFrameCoordinateSystem);

            int i = 0;

            while (i < lookAhead && trail.Count > 0)
            {
                var node = trail.Pop();

                var entity = new Entity($"node_{i}");
                entity.Node     = node;
                entity.Renderer = entity.Node == targetNode ? targetNodeRenderer : nodeRenderer;
                entity.UpdateTransform(referenceFrameCoordinateSystem);
                var targetPosition = rootEntity.Transform.Translation;
                entity.Position = new Vector3(0, (targetPosition - entity.Transform.Translation).Y, 0f);
                entities.Add(entity);

                i += 1;
            }

            return(1);
        }
        int RebuildTrailToTarget(SpatialCoordinateSystem referenceFrameCoordinateSystem, PerceptionTimestamp perceptionTimestamp, Node startNode, Node endNode, int lookAhead = 3)
        {
            Debug.WriteLine($"RebuildTrailToTarget {startNode.Name} -> {endNode.Name}");

            entities.Clear();

            var trail = new List <Node>();

            if (startNode == endNode)
            {
                trail.Add(startNode);
            }
            else
            {
                BuildPath(endNode, startNode, trail, new List <Node>());
            }

            if (trail.Count == 0)
            {
                Debug.WriteLine($"Unable to find Path for startNode {startNode.Name} and {endNode.Name}");
                return(-1);
            }

            Debug.WriteLine($"Creating trials {trail.ToArray()}");

            var baseEntity = GetReferenceEntitySpatialCoordinateSystem(referenceFrameCoordinateSystem);

            for (var i = 0; i < Math.Min(trail.Count, lookAhead); i++)
            {
                var node = trail[i];

                var entity = new Entity($"node_{i}");
                entity.Node     = node;
                entity.Renderer = nodeRenderer;

                entity.UpdateTransform(referenceFrameCoordinateSystem);
                // offset from baseEntity (to keep the y positions uniform and consistent)
                var targetPosition = baseEntity.Transform.Translation;
                entity.Position = new Vector3(0, (targetPosition - entity.Transform.Translation).Y, 0f);

                entities.Add(entity);
            }

            return(1);
        }