コード例 #1
0
        public IEnumerator TestHandConstraintPalmUpSolverPlacement()
        {
            // Instantiate our test GameObject with solver.
            var testObjects = InstantiateTestSolver <HandConstraintPalmUp>();

            testObjects.handler.TrackedTargetType = TrackedObjectType.HandJoint;
            testObjects.handler.TrackedHandness   = Handedness.Both;

            var handConstraintSolver = (HandConstraintPalmUp)testObjects.solver;

            handConstraintSolver.FollowHandUntilFacingCamera = true;

            // Ensure that FacingCameraTrackingThreshold is greater than FollowHandCameraFacingThresholdAngle
            Assert.AreEqual(handConstraintSolver.FacingCameraTrackingThreshold - handConstraintSolver.FollowHandCameraFacingThresholdAngle > 0, true);

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            TestUtilities.AssertAboutEqual(testObjects.target.transform.position, Vector3.zero, "HandConstraintPalmUp solver did not start at the origin");

            var cameraTransform = CameraCache.Main.transform;

            // Place hand 1 meter in front of user, 50 cm below eye level
            var handTestPos = cameraTransform.position + cameraTransform.forward - (Vector3.up * 0.5f);

            var cameraLookVector = (handTestPos - cameraTransform.position).normalized;

            // Generate hand rotation with hand palm facing camera
            var handRoation = Quaternion.LookRotation(cameraTransform.up, cameraLookVector);

            // Add a right hand.
            var rightHand = new TestHand(Handedness.Right);

            yield return(rightHand.Show(handTestPos));

            yield return(rightHand.SetRotation(handRoation));

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            // Ensure Rotation and offset behavior are following camera
            Assert.AreEqual(handConstraintSolver.RotationBehavior, HandConstraint.SolverRotationBehavior.LookAtMainCamera);
            Assert.AreEqual(handConstraintSolver.OffsetBehavior, HandConstraint.SolverOffsetBehavior.LookAtCameraRotation);

            // Rotate hand so palm is no longer within the FollowHandCameraFacingThresholdAngle
            var newHandRot = handRoation * Quaternion.Euler(-(handConstraintSolver.FollowHandCameraFacingThresholdAngle + 1), 0f, 0f);

            yield return(rightHand.SetRotation(newHandRot));

            yield return(new WaitForSeconds(SolverUpdateWaitTime));

            // Ensure Rotation and offset behavior are following camera
            Assert.AreEqual(handConstraintSolver.RotationBehavior, HandConstraint.SolverRotationBehavior.LookAtTrackedObject);
            Assert.AreEqual(handConstraintSolver.OffsetBehavior, HandConstraint.SolverOffsetBehavior.TrackedObjectRotation);

            yield return(rightHand.Hide());

            yield return(new WaitForSeconds(SolverUpdateWaitTime));
        }
コード例 #2
0
        private static IEnumerator MoveAround(bool moveHands, bool moveCamera, bool moveGaze)
        {
            if (moveHands)
            {
                var rightHand = new TestHand(Handedness.Right);

                yield return(rightHand.Show(new Vector3(0, 0, 0.5f)));

                yield return(rightHand.SetRotation(Quaternion.identity, 0));

                yield return(rightHand.MoveTo(new Vector3(0, 0, 2f), 40));

                yield return(rightHand.MoveTo(new Vector3(0, 0, 0.5f), 40));

                yield return(rightHand.SetRotation(Quaternion.AngleAxis(-90f, Vector3.forward), 40));

                yield return(rightHand.SetRotation(Quaternion.AngleAxis(90f, Vector3.forward), 40));

                yield return(rightHand.SetRotation(Quaternion.identity, 20));
            }

            if (moveCamera)
            {
                var camera = CameraCache.Main.transform;

                camera.rotation = Quaternion.identity;

                yield return(InterpRotation(camera, 0.5f, Quaternion.AngleAxis(-90f, Vector3.up)));

                yield return(InterpRotation(camera, 0.5f, Quaternion.AngleAxis(90f, Vector3.up)));

                yield return(InterpRotation(camera, 0.5f, Quaternion.identity));
            }

            if (moveGaze)
            {
                var gazeProvider = CoreServices.InputSystem.EyeGazeProvider;

                gazeProvider.UpdateEyeTrackingStatus(null, true);
                gazeProvider.UpdateEyeGaze(null, new Ray(Vector3.zero, Vector3.forward), DateTime.UtcNow);

                yield return(InterpGaze(gazeProvider, 0.5f, new Vector3(-1f, 0f, 1f).normalized));

                yield return(InterpGaze(gazeProvider, 0.5f, new Vector3(1f, 0f, 1f).normalized));

                yield return(InterpGaze(gazeProvider, 0.5f, Vector3.forward));
            }
        }
コード例 #3
0
        public IEnumerator ConstrainRotationFixToWorld()
        {
            TestUtilities.PlayspaceToOriginLookingForward();

            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            testObject.transform.position   = Vector3.forward;
            var manipHandler = testObject.AddComponent <ObjectManipulator>();

            manipHandler.HostTransform           = testObject.transform;
            manipHandler.SmoothingActive         = false;
            manipHandler.ManipulationType        = ManipulationHandFlags.OneHanded;
            manipHandler.OneHandRotationModeNear = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint;

            var rotConstraint = manipHandler.EnsureComponent <FixedRotationToWorldConstraint>();

            rotConstraint.TargetTransform = manipHandler.HostTransform;

            // Face user first
            const int numHandSteps = 1;
            TestHand  hand         = new TestHand(Handedness.Right);

            yield return(hand.Show(new Vector3(0.05f, -0.1f, 0.45f)));

            yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(null);

            // rotate the hand
            yield return(hand.SetRotation(Quaternion.Euler(45, 45, 45), numHandSteps));

            yield return(null);

            Assert.AreEqual(Quaternion.identity, testObject.transform.rotation);

            // move the hand
            yield return(hand.Move(Vector3.right * 0.2f, numHandSteps));

            yield return(null);

            Assert.AreEqual(Quaternion.identity, testObject.transform.rotation);

            // rotate the head
            CameraCache.Main.transform.Rotate(new Vector3(0, 10, 0));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.AreEqual(Quaternion.identity, testObject.transform.rotation);
        }
コード例 #4
0
        public IEnumerator TestTeleportStrafe()
        {
            var iss = PlayModeTestUtilities.GetInputSimulationService();

            // Create a floor and make sure it's below the camera
            var floor = GameObject.CreatePrimitive(PrimitiveType.Cube);

            floor.transform.position = -0.5f * Vector3.up;

            // Bring out the right hand and set it to the teleport gesture
            TestUtilities.PlayspaceToOriginLookingForward();
            Vector3 initialPosition = MixedRealityPlayspace.Position;

            TestHand rightHand = new TestHand(Handedness.Right);

            // Make sure the hand is in front of the camera
            yield return(rightHand.Show(Vector3.forward * 0.6f));

            rightHand.SetRotation(Quaternion.identity);

            TeleportPointer teleportPointer = rightHand.GetPointer <TeleportPointer>();

            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition - Vector3.forward * teleportPointer.strafeAmount, "Did not strafe to the expected position");

            teleportPointer.checkForFloorOnStrafe   = true;
            teleportPointer.adjustHeightOnStrafe    = true;
            teleportPointer.strafeAmount            = 1.0f;
            teleportPointer.maxHeightChangeOnStrafe = 0.5f;

            TestUtilities.PlayspaceToOriginLookingForward();
            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition, "Performed an invalid strafe");

            var floor2 = GameObject.CreatePrimitive(PrimitiveType.Cube);

            floor2.transform.position = new Vector3(0, -0.25f, -1.0f);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            TestUtilities.PlayspaceToOriginLookingForward();
            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition + new Vector3(0, 0.25f, -teleportPointer.strafeAmount), "Height did not change on strafe");

            floor2.transform.position = new Vector3(0, -0.75f, -1.0f);
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            TestUtilities.PlayspaceToOriginLookingForward();
            teleportPointer.PerformStrafe();
            TestUtilities.AssertAboutEqual(MixedRealityPlayspace.Position, initialPosition + new Vector3(0, -0.25f, -teleportPointer.strafeAmount), "Height did not change on strafe");
        }
コード例 #5
0
        public IEnumerator TestTeleportLayers()
        {
            var iss = PlayModeTestUtilities.GetInputSimulationService();

            // Create a floor and make sure it's below the camera
            var floor = GameObject.CreatePrimitive(PrimitiveType.Plane);

            floor.transform.position = -0.5f * Vector3.up;

            // Bring out the right hand and set it to the teleport gesture
            TestUtilities.PlayspaceToOriginLookingForward();
            float initialForwardPosition = MixedRealityPlayspace.Position.z;

            TestHand rightHand = new TestHand(Handedness.Right);

            // Make sure the hand is in front of the camera
            yield return(rightHand.Show(Vector3.forward * 0.6f));

            rightHand.SetRotation(Quaternion.identity);

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.TeleportStart));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            TeleportPointer teleportPointer = rightHand.GetPointer <TeleportPointer>();

            teleportPointer.PrioritizedLayerMasksOverride = new LayerMask[1] {
                UnityEngine.Physics.AllLayers ^ (1 << LayerMask.NameToLayer("UI"))
            };

            floor.layer = LayerMask.NameToLayer("Default");
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.AreEqual(Physics.TeleportSurfaceResult.Valid, teleportPointer.TeleportSurfaceResult);

            floor.layer = LayerMask.NameToLayer("Ignore Raycast");
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.AreEqual(Physics.TeleportSurfaceResult.Invalid, teleportPointer.TeleportSurfaceResult);

            floor.layer = LayerMask.NameToLayer("UI");
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            Assert.AreEqual(Physics.TeleportSurfaceResult.None, teleportPointer.TeleportSurfaceResult);
        }
コード例 #6
0
        public IEnumerator TestOverlap()
        {
            // Instantiate our test GameObject with solver.
            var testObjects = InstantiateTestSolver <Overlap>();

            testObjects.handler.TrackedTargetType = TrackedObjectType.HandJoint;
            var targetTransform = testObjects.target.transform;

            TestUtilities.AssertAboutEqual(targetTransform.position, Vector3.zero, "Overlap not at original position");
            TestUtilities.AssertAboutEqual(targetTransform.rotation, Quaternion.identity, "Overlap not at original rotation");

            // Test that the solver flies to the position of the left hand
            var handPosition = Vector3.forward - Vector3.right;
            var handRotation = Quaternion.LookRotation(handPosition);
            var leftHand     = new TestHand(Handedness.Left);

            yield return(leftHand.Show(handPosition));

            yield return(leftHand.SetRotation(handRotation));

            yield return(WaitForFrames(2));

            var hand = PlayModeTestUtilities.GetInputSimulationService().GetHandDevice(Handedness.Left);

            Assert.IsNotNull(hand);
            Assert.IsTrue(hand.TryGetJoint(TrackedHandJoint.Palm, out MixedRealityPose pose));

            TestUtilities.AssertAboutEqual(targetTransform.position, pose.Position, "Overlap solver is not at the same position as the left hand.");
            Assert.IsTrue(Quaternion.Angle(targetTransform.rotation, pose.Rotation) < 2.0f);

            // Make sure the solver did not move when hand was hidden
            yield return(leftHand.Hide());

            yield return(WaitForFrames(2));

            TestUtilities.AssertAboutEqual(targetTransform.position, pose.Position, "Overlap solver moved when the hand was hidden.");
            Assert.IsTrue(Quaternion.Angle(targetTransform.rotation, pose.Rotation) < 2.0f);
        }
コード例 #7
0
        public IEnumerator SpherePointerSectorAngle()
        {
            var rightHand = new TestHand(Handedness.Right);

            // Show hand far enough from the test collider
            Vector3 idlePos = new Vector3(0.05f, 0, 1.0f);

            yield return(rightHand.Show(idlePos));

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.OpenSteadyGrabPoint));

            var pointer = rightHand.GetPointer <SpherePointer>();

            pointer.NearObjectSectorAngle = 180.0f;
            pointer.PullbackDistance      = 0.0f;
            // Orient the right hand so the grab axis is approximately aligned with the z axis

            Vector3 margin           = new Vector3(0, 0, 0.001f);
            Vector3 nearObjectMargin = new Vector3(0, 0, 0.001f + (pointer.NearObjectSmoothingFactor + 1) * pointer.NearObjectRadius);

            Assert.IsNotNull(pointer, "Expected to find SpherePointer in the hand controller");
            Vector3 nearObjectPos         = new Vector3(0.05f, 0, colliderSurfaceZ - pointer.NearObjectRadius);
            Vector3 interactionEnabledPos = new Vector3(0.05f, 0, colliderSurfaceZ - pointer.SphereCastRadius);

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Move hand closer to the collider to enable IsNearObject
            yield return(rightHand.MoveTo(nearObjectPos - margin, numFramesPerMove));

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            yield return(rightHand.MoveTo(nearObjectPos + margin, numFramesPerMove));

            Assert.True(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Rotate hand but maintain IsNearObject
            yield return(rightHand.SetRotation(Quaternion.Euler(0, 90, 0), numFramesPerMove));

            Assert.True(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Rotate hand 200 degrees and lose IsNearObject
            yield return(rightHand.SetRotation(Quaternion.Euler(0, 200, 0), numFramesPerMove));

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Rotate hand back to original orientation
            yield return(rightHand.SetRotation(Quaternion.Euler(0, 0, 0), numFramesPerMove));

            Assert.True(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Move hand closer to the collider to enable IsInteractionEnabled
            yield return(rightHand.MoveTo(interactionEnabledPos - margin, numFramesPerMove));

            Assert.True(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);
            yield return(rightHand.MoveTo(interactionEnabledPos + margin, numFramesPerMove));

            Assert.True(pointer.IsNearObject);
            Assert.True(pointer.IsInteractionEnabled);

            // Move hand back out to disable IsInteractionEnabled
            yield return(rightHand.MoveTo(interactionEnabledPos - margin, numFramesPerMove));

            Assert.True(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            // Move hand back out to disable IsNearObject
            yield return(rightHand.MoveTo(nearObjectPos + margin, numFramesPerMove));

            Assert.True(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);
            yield return(rightHand.MoveTo(nearObjectPos - nearObjectMargin, numFramesPerMove));

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);

            yield return(rightHand.MoveTo(idlePos, numFramesPerMove));

            Assert.False(pointer.IsNearObject);
            Assert.False(pointer.IsInteractionEnabled);
        }
コード例 #8
0
        public IEnumerator TestTeleport()
        {
            var iss = PlayModeTestUtilities.GetInputSimulationService();

            // Create a floor and make sure it's below the camera
            var floor = GameObject.CreatePrimitive(PrimitiveType.Plane);

            floor.transform.position = -0.5f * Vector3.up;

            // Test Right Hand Teleport
            TestUtilities.PlayspaceToOriginLookingForward();
            float initialForwardPosition = MixedRealityPlayspace.Position.z;

            TestHand leftHand  = new TestHand(Handedness.Left);
            TestHand rightHand = new TestHand(Handedness.Right);

            // Make sure the hand is in front of the camera
            yield return(rightHand.Show(Vector3.forward * 0.6f));

            rightHand.SetRotation(Quaternion.identity);

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.TeleportStart));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.TeleportEnd));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            // We should have teleported in the forward direction after the teleport
            Assert.IsTrue(MixedRealityPlayspace.Position.z > initialForwardPosition);
            rightHand.Hide();

            // Test Left Hand Teleport
            TestUtilities.PlayspaceToOriginLookingForward();

            // Make sure the hand is in front of the camera
            yield return(leftHand.Show(Vector3.forward * 0.6f));

            yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.TeleportStart));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.TeleportEnd));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            // We should have teleported in the forward direction after the teleport
            Assert.IsTrue(MixedRealityPlayspace.Position.z > initialForwardPosition);
            leftHand.Hide();
        }
コード例 #9
0
        public IEnumerator ConstrainByNumberOfHands()
        {
            TestUtilities.PlayspaceToArbitraryPose();

            // set up cube with manipulation handler
            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            Vector3 originalPosition = TestUtilities.PositionRelativeToPlayspace(Vector3.forward);

            testObject.transform.position = originalPosition;
            Quaternion originalRotation = Quaternion.identity;

            testObject.transform.rotation = originalRotation;
            var manipHandler = testObject.AddComponent <ObjectManipulator>();

            manipHandler.HostTransform          = testObject.transform;
            manipHandler.SmoothingFar           = false;
            manipHandler.OneHandRotationModeFar = ObjectManipulator.RotateInOneHandType.RotateAboutObjectCenter;

            // add an xyz rotate constraint for one handed so we can only move
            var rotateConstraint = manipHandler.EnsureComponent <RotationAxisConstraint>();

            rotateConstraint.UseLocalSpaceForConstraint = false;
            rotateConstraint.ConstraintOnRotation       = AxisFlags.XAxis | AxisFlags.YAxis | AxisFlags.ZAxis;
            rotateConstraint.HandType = ManipulationHandFlags.OneHanded;

            // add an xyz move constraint for two handed so we can only rotate
            var moveConstraint = manipHandler.EnsureComponent <MoveAxisConstraint>();

            moveConstraint.UseLocalSpaceForConstraint = false;
            moveConstraint.ConstraintOnMovement       = AxisFlags.XAxis | AxisFlags.YAxis | AxisFlags.ZAxis;
            moveConstraint.HandType = ManipulationHandFlags.TwoHanded;

            yield return(new WaitForFixedUpdate());

            yield return(null);

            const int numHandSteps = 10;

            TestHand leftHand  = new TestHand(Handedness.Left);
            TestHand rightHand = new TestHand(Handedness.Right);

            yield return(leftHand.Show(TestUtilities.PositionRelativeToPlayspace(new Vector3(-0.05f, -0.1f, 0.45f))));

            yield return(rightHand.Show(TestUtilities.PositionRelativeToPlayspace(new Vector3(0.05f, -0.1f, 0.45f))));

            // rotate and move left hand
            yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(leftHand.SetRotation(Quaternion.Euler(45, 45, 45), numHandSteps));

            yield return(null);

            TestUtilities.AssertAboutEqual(originalRotation, testObject.transform.rotation, "Rotation should be equal for one handed interaction");

            Vector3 worldLeftUp = TestUtilities.DirectionRelativeToPlayspace(Vector3.left + Vector3.up);

            yield return(leftHand.Move(worldLeftUp * 0.2f, numHandSteps));

            yield return(null);

            TestUtilities.AssertNotAboutEqual(originalPosition, testObject.transform.position, "Position should not be equal for one handed interaction");

            // return hand to original pose
            yield return(leftHand.SetRotation(Quaternion.identity, numHandSteps));

            yield return(leftHand.Move(-worldLeftUp * 0.2f, numHandSteps));

            yield return(null);

            // grab with both hands and move/rotate
            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(leftHand.Move(worldLeftUp * 0.2f, numHandSteps));

            yield return(null);

            TestUtilities.AssertNotAboutEqual(originalRotation, testObject.transform.rotation, "Rotation should not be equal for two handed interaction");
            TestUtilities.AssertAboutEqual(originalPosition, testObject.transform.position, "Position should be equal for two handed interaction");
        }
コード例 #10
0
        public IEnumerator ConstrainRotationAxisLocalSpace()
        {
            TestUtilities.PlayspaceToArbitraryPose();

            // set up cube with manipulation handler
            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            testObject.transform.position   = TestUtilities.PositionRelativeToPlayspace(new Vector3(0f, 0f, 1f));
            Quaternion initialObjectRotation = Quaternion.Euler(-30, -30, -30);

            testObject.transform.rotation = initialObjectRotation;
            var manipHandler = testObject.AddComponent <ObjectManipulator>();

            manipHandler.HostTransform          = testObject.transform;
            manipHandler.SmoothingFar           = false;
            manipHandler.ManipulationType       = ManipulationHandFlags.OneHanded;
            manipHandler.OneHandRotationModeFar = ObjectManipulator.RotateInOneHandType.RotateAboutObjectCenter;

            var constraint = manipHandler.EnsureComponent <RotationAxisConstraint>();

            constraint.UseLocalSpaceForConstraint = true;

            yield return(new WaitForFixedUpdate());

            yield return(null);

            const int  numHandSteps = 1;
            Quaternion inverse      = Quaternion.Inverse(initialObjectRotation);

            // Hand pointing at middle of cube
            Vector3  initialHandPosition = TestUtilities.PositionRelativeToPlayspace(new Vector3(0.044f, -0.1f, 0.45f));
            TestHand hand = new TestHand(Handedness.Right);

            yield return(hand.Show(initialHandPosition));

            var rotateTo = Quaternion.Euler(45, 45, 45);

            yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            // Constrain x axis
            constraint.ConstraintOnRotation = AxisFlags.XAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreEqual(0, (inverse * testObject.transform.rotation).eulerAngles.x, 0.01f);
            Assert.AreNotEqual(0, (inverse * testObject.transform.rotation).eulerAngles.y);
            Assert.AreNotEqual(0, (inverse * testObject.transform.rotation).eulerAngles.z);

            yield return(hand.SetRotation(initialObjectRotation, numHandSteps));

            yield return(null);

            // Constrain y axis
            constraint.ConstraintOnRotation = AxisFlags.YAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreNotEqual(0, (inverse * testObject.transform.rotation).eulerAngles.x);
            Assert.AreEqual(0, (inverse * testObject.transform.rotation).eulerAngles.y, 0.01f);
            Assert.AreNotEqual(0, (inverse * testObject.transform.rotation).eulerAngles.z);

            yield return(hand.SetRotation(initialObjectRotation, numHandSteps));

            yield return(null);

            // Constrain z axis
            constraint.ConstraintOnRotation = AxisFlags.ZAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreNotEqual(0, (inverse * testObject.transform.rotation).eulerAngles.x);
            Assert.AreNotEqual(0, (inverse * testObject.transform.rotation).eulerAngles.y);
            Assert.AreEqual(0, (inverse * testObject.transform.rotation).eulerAngles.z, 0.01f);

            yield return(hand.SetRotation(initialObjectRotation, numHandSteps));

            yield return(null);

            // Constrain two axes
            constraint.ConstraintOnRotation = AxisFlags.XAxis | AxisFlags.ZAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreEqual(0, (inverse * testObject.transform.rotation).eulerAngles.x, 0.01f);
            Assert.AreNotEqual(0, (inverse * testObject.transform.rotation).eulerAngles.y);
            Assert.AreEqual(0, (inverse * testObject.transform.rotation).eulerAngles.z, 0.01f);
        }
コード例 #11
0
            /// <summary>
            /// Manipulates the given testObject in a number of ways and records the output here
            /// </summary>
            /// <param name="testObject">An unrotated primitive cube at (0, 0, 1) with scale (0.2, 0.2, 0,2)</param>
            public IEnumerator RecordTransformValues(GameObject testObject)
            {
                TestUtilities.PlayspaceToOriginLookingForward();

                float      testRotation   = 45;
                Quaternion testQuaternion = Quaternion.Euler(testRotation, testRotation, testRotation);

                Vector3  leftHandNearPos  = new Vector3(-0.1f, 0, 1);
                Vector3  rightHandNearPos = new Vector3(0.1f, 0, 1);
                Vector3  leftHandFarPos   = new Vector3(-0.06f, -0.1f, 0.5f);
                Vector3  rightHandFarPos  = new Vector3(0.06f, -0.1f, 0.5f);
                TestHand leftHand         = new TestHand(Handedness.Left);
                TestHand rightHand        = new TestHand(Handedness.Right);

                // One hand rotate near
                yield return(rightHand.MoveTo(rightHandNearPos, numSteps));

                yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

                yield return(rightHand.SetRotation(testQuaternion, numSteps));

                RecordTransform(testObject.transform, "one hand rotate near");

                // Two hand rotate/scale near
                yield return(rightHand.SetRotation(Quaternion.identity, numSteps));

                yield return(leftHand.MoveTo(leftHandNearPos, numSteps));

                yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

                yield return(rightHand.Move(new Vector3(0.2f, 0.2f, 0), numSteps));

                yield return(leftHand.Move(new Vector3(-0.2f, -0.2f, 0), numSteps));

                RecordTransform(testObject.transform, "two hand rotate/scale near");

                // Two hand rotate/scale far
                yield return(rightHand.MoveTo(rightHandNearPos, numSteps));

                yield return(leftHand.MoveTo(leftHandNearPos, numSteps));

                yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open));

                yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.Open));

                yield return(rightHand.MoveTo(rightHandFarPos, numSteps));

                yield return(leftHand.MoveTo(leftHandFarPos, numSteps));

                yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

                yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

                yield return(rightHand.Move(new Vector3(0.2f, 0.2f, 0), numSteps));

                yield return(leftHand.Move(new Vector3(-0.2f, -0.2f, 0), numSteps));

                RecordTransform(testObject.transform, "two hand rotate/scale far");

                // One hand rotate near
                yield return(rightHand.MoveTo(rightHandFarPos, numSteps));

                yield return(leftHand.MoveTo(leftHandFarPos, numSteps));

                yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.Open));

                yield return(leftHand.Hide());

                MixedRealityPlayspace.PerformTransformation(
                    p =>
                {
                    p.position         = MixedRealityPlayspace.Position;
                    Vector3 rotatedFwd = Quaternion.AngleAxis(testRotation, Vector3.up) * Vector3.forward;
                    p.LookAt(rotatedFwd);
                });
                yield return(null);

                Vector3 newHandPosition = Quaternion.AngleAxis(testRotation, Vector3.up) * rightHandFarPos;

                yield return(rightHand.MoveTo(newHandPosition, numSteps));

                RecordTransform(testObject.transform, "one hand rotate far");

                yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.Open));

                yield return(rightHand.Hide());
            }
コード例 #12
0
        public IEnumerator ManipulationHandlerOneHandRotateWithConstraint()
        {
            // set up cube with manipulation handler
            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            Vector3 initialObjectPosition = new Vector3(0f, 0f, 1f);

            testObject.transform.position = initialObjectPosition;
            var manipHandler = testObject.AddComponent <ManipulationHandler>();

            manipHandler.HostTransform          = testObject.transform;
            manipHandler.SmoothingActive        = false;
            manipHandler.ManipulationType       = ManipulationHandler.HandMovementType.OneHandedOnly;
            manipHandler.OneHandRotationModeFar = ManipulationHandler.RotateInOneHandType.RotateAboutGrabPoint;
            manipHandler.ReleaseBehavior        = 0;
            manipHandler.AllowFarManipulation   = false;

            // add near interaction grabbable to be able to grab the cube with the simulated articulated hand
            testObject.AddComponent <NearInteractionGrabbable>();

            yield return(new WaitForFixedUpdate());

            yield return(null);

            TestHand hand = new TestHand(Handedness.Right);

            yield return(hand.Show(initialObjectPosition));

            yield return(null);

            // grab the object
            yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            yield return(new WaitForFixedUpdate());

            yield return(null);

            float      testRotation   = 45;
            const int  numRotSteps    = 10;
            Quaternion testQuaternion = Quaternion.Euler(testRotation, testRotation, testRotation);

            // rotate without constraint
            manipHandler.ConstraintOnRotation = RotationConstraintType.None;
            yield return(hand.SetRotation(testQuaternion, numRotSteps));

            float diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.Euler(testRotation, testRotation, testRotation));

            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "object didn't rotate with hand");

            yield return(hand.SetRotation(Quaternion.identity, numRotSteps));

            diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.identity);
            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "object didn't rotate with hand");

            // rotate with x axis only
            manipHandler.ConstraintOnRotation = RotationConstraintType.XAxisOnly;
            yield return(hand.SetRotation(testQuaternion, numRotSteps));

            diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.Euler(testRotation, 0, 0));
            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "constraint on x axis did not lock axis correctly");

            yield return(hand.SetRotation(Quaternion.identity, numRotSteps));

            diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.identity);
            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "constraint on x axis did not lock axis correctly");

            // rotate with y axis only
            manipHandler.ConstraintOnRotation = RotationConstraintType.YAxisOnly;
            yield return(hand.SetRotation(testQuaternion, numRotSteps));

            diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.Euler(0, testRotation, 0));
            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "constraint on Y axis did not lock axis correctly");

            yield return(hand.SetRotation(Quaternion.identity, numRotSteps));

            diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.identity);
            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "constraint on Y axis did not lock axis correctly");

            // rotate with z axis only
            manipHandler.ConstraintOnRotation = RotationConstraintType.ZAxisOnly;
            yield return(hand.SetRotation(testQuaternion, numRotSteps));

            diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.Euler(0, 0, testRotation));
            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "constraint on Z axis did not lock axis correctly");

            yield return(hand.SetRotation(Quaternion.identity, numRotSteps));

            diffAngle = Quaternion.Angle(testObject.transform.rotation, Quaternion.identity);
            Assert.IsTrue(Mathf.Approximately(diffAngle, 0.0f), "constraint on Z axis did not lock axis correctly");

            yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Open));

            yield return(hand.Hide());
        }
コード例 #13
0
        public IEnumerator ConstrainRotationAxisWorldSpace()
        {
            TestUtilities.PlayspaceToOriginLookingForward();

            // set up cube with manipulation handler
            var testObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            testObject.transform.localScale = Vector3.one * 0.2f;
            testObject.transform.position   = new Vector3(0f, 0f, 1f);
            var manipHandler = testObject.AddComponent <ObjectManipulator>();

            manipHandler.HostTransform          = testObject.transform;
            manipHandler.SmoothingActive        = false;
            manipHandler.ManipulationType       = ObjectManipulator.HandMovementType.OneHanded;
            manipHandler.OneHandRotationModeFar = ObjectManipulator.RotateInOneHandType.RotateAboutObjectCenter;

            var constraint = manipHandler.EnsureComponent <RotationAxisConstraint>();

            constraint.UseLocalSpaceForConstraint = false;

            yield return(new WaitForFixedUpdate());

            yield return(null);

            const int numHandSteps = 1;

            // Hand pointing at middle of cube
            TestHand hand = new TestHand(Handedness.Right);

            yield return(hand.Show(new Vector3(0.044f, -0.1f, 0.45f)));

            var rotateTo = Quaternion.Euler(45, 45, 45);

            yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

            // Constrain x axis
            constraint.ConstraintOnRotation = AxisFlags.XAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreEqual(0, testObject.transform.rotation.eulerAngles.x, 0.01f);
            Assert.AreNotEqual(0, testObject.transform.rotation.eulerAngles.y);
            Assert.AreNotEqual(0, testObject.transform.rotation.eulerAngles.z);

            yield return(hand.SetRotation(Quaternion.identity, numHandSteps));

            yield return(null);

            // Constrain y axis
            constraint.ConstraintOnRotation = AxisFlags.YAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreNotEqual(0, testObject.transform.rotation.eulerAngles.x);
            Assert.AreEqual(0, testObject.transform.rotation.eulerAngles.y, 0.01f);
            Assert.AreNotEqual(0, testObject.transform.rotation.eulerAngles.z);

            yield return(hand.SetRotation(Quaternion.identity, numHandSteps));

            yield return(null);

            // Constrain z axis
            constraint.ConstraintOnRotation = AxisFlags.ZAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreNotEqual(0, testObject.transform.rotation.eulerAngles.x);
            Assert.AreNotEqual(0, testObject.transform.rotation.eulerAngles.y);
            Assert.AreEqual(0, testObject.transform.rotation.eulerAngles.z, 0.01f);

            yield return(hand.SetRotation(Quaternion.identity, numHandSteps));

            yield return(null);

            // Constrain two axes
            constraint.ConstraintOnRotation = AxisFlags.XAxis | AxisFlags.ZAxis;

            yield return(hand.SetRotation(rotateTo, numHandSteps));

            yield return(null);

            Assert.AreEqual(0, testObject.transform.rotation.eulerAngles.x, 0.01f);
            Assert.AreNotEqual(0, testObject.transform.rotation.eulerAngles.y);
            Assert.AreEqual(0, testObject.transform.rotation.eulerAngles.z, 0.01f);
        }
コード例 #14
0
        public IEnumerator TestTeleportAndContentOffset()
        {
            var             iss = PlayModeTestUtilities.GetInputSimulationService();
            ExperienceScale originalExperienceScale;
            float           originalProfileContentOffset;

            float contentOffset = 1.3f;

            // MRTK has already been created by SetUp prior to calling this,
            // we have to shut it down to re-init with the custom input profile which
            // has our contentOffset value set
            PlayModeTestUtilities.TearDown();
            yield return(null);

            // Initialize a profile with the appropriate contentOffset
            var profile = TestUtilities.GetDefaultMixedRealityProfile <MixedRealityToolkitConfigurationProfile>();

            originalProfileContentOffset = profile.ExperienceSettingsProfile.ContentOffset;
            originalExperienceScale      = profile.ExperienceSettingsProfile.TargetExperienceScale;

            profile.ExperienceSettingsProfile.ContentOffset         = contentOffset;
            profile.ExperienceSettingsProfile.TargetExperienceScale = ExperienceScale.Room;

            PlayModeTestUtilities.Setup(profile);

            yield return(new WaitForSeconds(0.5f));

            // Ensure that the SceneContent object is contentOffset units above the origin
            Assert.AreEqual(GameObject.Find("MixedRealitySceneContent").transform.position.y, contentOffset, 0.005f);

            // Create a floor and make sure it's below the camera
            var floor = GameObject.CreatePrimitive(PrimitiveType.Plane);

            floor.transform.position = -0.5f * Vector3.up;

            // Test Right Hand Teleport
            TestUtilities.PlayspaceToOriginLookingForward();
            float initialForwardPosition = MixedRealityPlayspace.Position.z;

            TestHand leftHand  = new TestHand(Handedness.Left);
            TestHand rightHand = new TestHand(Handedness.Right);

            // Make sure the hand is in front of the camera
            yield return(rightHand.Show(Vector3.forward * 0.6f));

            rightHand.SetRotation(Quaternion.identity);

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.TeleportStart));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            yield return(rightHand.SetGesture(ArticulatedHandPose.GestureId.TeleportEnd));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            // We should have teleported in the forward direction after the teleport
            Assert.IsTrue(MixedRealityPlayspace.Position.z > initialForwardPosition);
            rightHand.Hide();

            // Test Left Hand Teleport
            TestUtilities.PlayspaceToOriginLookingForward();

            // Make sure the hand is in front of the camera
            yield return(leftHand.Show(Vector3.forward * 0.6f));

            yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.TeleportStart));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            yield return(leftHand.SetGesture(ArticulatedHandPose.GestureId.TeleportEnd));

            // Wait for the hand to animate
            yield return(PlayModeTestUtilities.WaitForInputSystemUpdate());

            yield return(new WaitForSeconds(1.0f / iss.InputSimulationProfile.HandGestureAnimationSpeed + 0.1f));

            // We should have teleported in the forward direction after the teleport
            Assert.IsTrue(MixedRealityPlayspace.Position.z > initialForwardPosition);

            // Reset the profile's settings to it's original value
            profile.ExperienceSettingsProfile.TargetExperienceScale = originalExperienceScale;
            profile.ExperienceSettingsProfile.ContentOffset         = originalProfileContentOffset;

            leftHand.Hide();
        }