public IEnumerator TestFollowStuckBehind()
        {
            // Instantiate our test GameObject with solver.
            var testObjects  = InstantiateTestSolver <Follow>();
            var followSolver = (Follow)testObjects.solver;

            followSolver.MoveToDefaultDistanceLerpTime = 0;
            testObjects.handler.TrackedTargetType      = TrackedObjectType.Head;
            var targetTransform = testObjects.target.transform;

            // variables and lambdas to test direction remains within bounds
            Vector3 toTarget() => targetTransform.position - CameraCache.Main.transform.position;

            // Test without rotation
            TestUtilities.PlayspaceToOriginLookingForward();

            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.Greater(Vector3.Dot(CameraCache.Main.transform.forward, toTarget()), 0, "Follow behind the player");

            // Test y axis rotation
            MixedRealityPlayspace.PerformTransformation(p => p.Rotate(Vector3.up, 180));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.Greater(Vector3.Dot(CameraCache.Main.transform.forward, toTarget()), 0, "Follow behind the player");
        }
示例#2
0
        /// <summary>
        /// Instantiates a bounding box at 0, 0, -1.5f
        /// box is at scale .5, .5, .5
        /// Target is set to its child if targetIsChild is true
        /// </summary>
        private BoundingBox InstantiateSceneAndDefaultBbox(GameObject target = null)
        {
            GameObject bboxGameObject;

            if (target != null)
            {
                bboxGameObject = new GameObject();
            }
            else
            {
                bboxGameObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
            }
            bboxGameObject.transform.position   = boundingBoxStartCenter;
            bboxGameObject.transform.localScale = boundingBoxStartScale;
            BoundingBox bbox = bboxGameObject.AddComponent <BoundingBox>();

            if (target != null)
            {
                target.transform.parent        = bboxGameObject.transform;
                target.transform.localScale    = Vector3.one;
                target.transform.localPosition = Vector3.zero;
                bbox.Target = target;
            }

            MixedRealityPlayspace.PerformTransformation(
                p =>
            {
                p.position = Vector3.zero;
                p.LookAt(bboxGameObject.transform.position);
            });

            bbox.Active = true;

            return(bbox);
        }
示例#3
0
        public IEnumerator TestTapToPlaceOnClickHead()
        {
            TestUtilities.PlayspaceToOriginLookingForward();

            // Create a cube with Tap to Place attached and Head (default) as the TrackedTargetType
            var tapToPlaceObj = InstantiateTestSolver <TapToPlace>();

            tapToPlaceObj.target.transform.position = Vector3.forward;
            TapToPlace tapToPlace = tapToPlaceObj.solver as TapToPlace;

            // Set hand position
            Vector3 handStartPosition = new Vector3(0, -0.1f, 0.6f);
            var     leftHand          = new TestHand(Handedness.Left);

            yield return(leftHand.Show(handStartPosition));

            // Select Tap to Place Obj
            yield return(leftHand.Click());

            // Make sure the object is being placed
            Assert.True(tapToPlace.IsBeingPlaced);

            // Move the playspace to simulate head movement
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.left * 1.5f;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Make sure the target obj has followed the head
            Assert.AreEqual(CameraCache.Main.transform.position.x, tapToPlaceObj.target.transform.position.x, "The tap to place object position.x does not match the camera position.x");

            // Tap to place has a 0.5 sec timer between clicks to make sure a double click does not get registered
            // We need to wait at least 0.5 secs until another click is called or tap to place will ignore the action
            yield return(new WaitForSeconds(0.5f));

            // Click object to stop placement
            yield return(leftHand.Click());

            // Make sure the object is not being placed after the click
            Assert.False(tapToPlace.IsBeingPlaced);

            // Move the playspace to simulate head movement again
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.right;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Make sure the target obj is NOT following the head
            Assert.AreNotEqual(CameraCache.Main.transform.position.x, tapToPlaceObj.target.transform.position.x, "The tap to place object position.x matches camera position.x, when it should not");
        }
 /// <summary>
 /// Creates a playspace and moves it into a default position.
 /// </summary>
 public static void InitializePlayspace()
 {
     MixedRealityPlayspace.PerformTransformation(
         p =>
     {
         p.position = new Vector3(1.0f, 1.5f, -2.0f);
         p.LookAt(Vector3.zero);
     });
 }
 /// <summary>
 /// Force the playspace camera into the specified position and orientation.
 /// </summary>
 /// <param name="position">World space position for the playspace.</param>
 /// <param name="rotation">World space orientation for the playspace.</param>
 /// <remarks>
 /// Note that this has no effect on the camera's local space transform, but
 /// will change the camera's world space position. If and only if the camera's
 /// local transform is identity with the camera's world transform equal the playspace's.
 /// </remarks>
 public static void PlayspaceToPositionAndRotation(Vector3 position, Quaternion rotation)
 {
     MixedRealityPlayspace.PerformTransformation(
         p =>
     {
         p.position = position;
         p.rotation = rotation;
     });
 }
 /// <summary>
 /// Forces the playspace camera to face forward.
 /// </summary>
 public static void PlayspaceToOriginLookingForward()
 {
     // Move the camera to origin looking at +z to more easily see the a target at 0,0,0
     MixedRealityPlayspace.PerformTransformation(
         p =>
     {
         p.position = Vector3.zero;
         p.LookAt(Vector3.forward);
     });
 }
        public IEnumerator SetTarget()
        {
            // create cube without control
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.transform.position = boundingBoxStartCenter;

            MixedRealityPlayspace.PerformTransformation(
                p =>
            {
                p.position = Vector3.zero;
                p.LookAt(cube.transform.position);
            });

            cube.transform.localScale = boundingBoxStartScale;

            // create another gameobject with boundscontrol attached
            var         emptyGameObject = new GameObject("empty");
            BoundingBox bbox            = emptyGameObject.AddComponent <BoundingBox>();

            // set target to cube
            bbox.Target = cube;
            bbox.Active = true;

            // front right corner is corner 3
            var frontRightCornerPos = cube.transform.Find("rigRoot/corner_3").position;

            // grab corner and scale object
            Vector3  initialHandPosition = new Vector3(0, 0, 0.5f);
            int      numSteps            = 30;
            var      delta = new Vector3(0.1f, 0.1f, 0f);
            TestHand hand  = new TestHand(Handedness.Right);

            yield return(hand.Show(initialHandPosition));

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

            yield return(hand.MoveTo(frontRightCornerPos, numSteps));

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

            yield return(hand.MoveTo(frontRightCornerPos + delta, numSteps));

            var     endBounds      = cube.GetComponent <BoxCollider>().bounds;
            Vector3 expectedCenter = new Vector3(0.033f, 0.033f, 1.467f);
            Vector3 expectedSize   = Vector3.one * .567f;

            TestUtilities.AssertAboutEqual(endBounds.center, expectedCenter, "endBounds incorrect center");
            TestUtilities.AssertAboutEqual(endBounds.size, expectedSize, "endBounds incorrect size");

            Object.Destroy(emptyGameObject);
            Object.Destroy(cube);
            // Wait for a frame to give Unity a change to actually destroy the object
            yield return(null);
        }
示例#8
0
        public IEnumerator TestFollowOrientation()
        {
            // Instantiate our test GameObject with solver.
            var testObjects  = InstantiateTestSolver <Follow>();
            var followSolver = (Follow)testObjects.solver;

            followSolver.MoveToDefaultDistanceLerpTime = 0;
            testObjects.handler.TrackedTargetType      = TrackedObjectType.Head;
            var targetTransform = testObjects.target.transform;

            // Test orientation deadzone
            followSolver.OrientToControllerDeadzoneDegrees = 70;
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.back;
                p.LookAt(Vector3.forward);
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.AreEqual(targetTransform.rotation, Quaternion.identity, "Target rotated before we moved beyond the deadzone");

            MixedRealityPlayspace.PerformTransformation(p => p.RotateAround(Vector3.zero, Vector3.up, 45));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.AreEqual(targetTransform.rotation, Quaternion.identity, "Target rotated before we moved beyond the deadzone");

            MixedRealityPlayspace.PerformTransformation(p => p.RotateAround(Vector3.zero, Vector3.up, 45));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.AreNotEqual(targetTransform.rotation, Quaternion.identity, "Target did not rotate after we moved beyond the deadzone");

            // Test FaceUserDefinedTargetTransform
            var hand = new TestHand(Handedness.Right);

            yield return(hand.Show(Vector3.forward + Vector3.right));

            testObjects.handler.TrackedTargetType       = TrackedObjectType.HandJoint;
            followSolver.FaceUserDefinedTargetTransform = true;
            followSolver.TargetToFace = CameraCache.Main.transform;

            Assert.AreEqual(Quaternion.LookRotation(targetTransform.position - CameraCache.Main.transform.position), targetTransform.rotation);

            yield return(hand.MoveTo(Vector3.forward + Vector3.left, 1));

            yield return(null);

            Assert.AreEqual(Quaternion.LookRotation(targetTransform.position - CameraCache.Main.transform.position), targetTransform.rotation);
        }
示例#9
0
        public IEnumerator TestFollowDirection()
        {
            // Instantiate our test GameObject with solver.
            var testObjects  = InstantiateTestSolver <Follow>();
            var followSolver = (Follow)testObjects.solver;

            followSolver.MoveToDefaultDistanceLerpTime = 0;
            testObjects.handler.TrackedTargetType      = TrackedObjectType.Head;
            var targetTransform = testObjects.target.transform;

            // variables and lambdas to test direction remains within bounds
            var maxXAngle = followSolver.MaxViewHorizontalDegrees / 2;
            var maxYAngle = followSolver.MaxViewVerticalDegrees / 2;

            Vector3 directionToHead() => CameraCache.Main.transform.position - targetTransform.position;
            float xAngle() => (Mathf.Acos(Vector3.Dot(directionToHead(), targetTransform.right)) * Mathf.Rad2Deg) - 90;
            float yAngle() => 90 - (Mathf.Acos(Vector3.Dot(directionToHead(), targetTransform.up)) * Mathf.Rad2Deg);

            // Test without rotation
            TestUtilities.PlayspaceToOriginLookingForward();

            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.LessOrEqual(Mathf.Abs(xAngle()), maxXAngle, "Follow exceeded the max horizontal angular bounds");
            Assert.LessOrEqual(Mathf.Abs(yAngle()), maxYAngle, "Follow exceeded the max vertical angular bounds");

            // Test y axis rotation
            MixedRealityPlayspace.PerformTransformation(p => p.Rotate(Vector3.up, 45));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.LessOrEqual(Mathf.Abs(xAngle()), maxXAngle, "Follow exceeded the max horizontal angular bounds");
            Assert.LessOrEqual(Mathf.Abs(yAngle()), maxYAngle, "Follow exceeded the max vertical angular bounds");

            // Test x axis rotation
            MixedRealityPlayspace.PerformTransformation(p => p.Rotate(Vector3.right, 45));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.LessOrEqual(Mathf.Abs(xAngle()), maxXAngle, "Follow exceeded the max horizontal angular bounds");
            Assert.LessOrEqual(Mathf.Abs(yAngle()), maxYAngle, "Follow exceeded the max vertical angular bounds");

            // Test translation
            MixedRealityPlayspace.PerformTransformation(p => p.Translate(Vector3.back, Space.World));
            yield return(new WaitForFixedUpdate());

            yield return(null);

            Assert.LessOrEqual(Mathf.Abs(xAngle()), maxXAngle, "Follow exceeded the max horizontal angular bounds");
            Assert.LessOrEqual(Mathf.Abs(yAngle()), maxYAngle, "Follow exceeded the max vertical angular bounds");
        }
示例#10
0
        public IEnumerator ZoomRotatedSlate()
        {
            // Configuring camera and hands to interact with rotated slate
            InstantiateFromPrefab(Vector3.right, Quaternion.LookRotation(Vector3.right));
            MixedRealityPlayspace.PerformTransformation(p => p.Rotate(Vector3.up, 90));
            yield return(null);

            // Right hand pinches slate
            TestHand handRight = new TestHand(Handedness.Right);

            yield return(handRight.Show(panZoom.transform.position + Vector3.forward * -0.1f + Vector3.right * -0.3f));

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

            // Left hand pinches slate
            TestHand handLeft = new TestHand(Handedness.Left);

            yield return(handLeft.Show(panZoom.transform.position + Vector3.forward * 0.1f + Vector3.right * -0.3f));

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

            // Use both hands to zoom in
            yield return(handRight.Move(new Vector3(0f, 0f, -0.1f), 5));

            yield return(handLeft.Move(new Vector3(0f, 0f, 0.1f), 5));

            Assert.AreEqual(0.6, panZoom.CurrentScale, 0.1, "Rotated slate did not zoom in using near interaction");

            // Reset slate and hands configuration
            panZoom.Reset();
            yield return(handRight.SetGesture(ArticulatedHandPose.GestureId.Open));

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

            yield return(null);

            // Both hands touch slate
            yield return(handRight.MoveTo(panZoom.transform.position + Vector3.forward * -0.1f));

            yield return(handLeft.MoveTo(panZoom.transform.position + Vector3.forward * 0.1f));

            yield return(null);

            // Use both hands to zoom in
            yield return(handRight.Move(new Vector3(0f, 0f, -0.1f), 5));

            yield return(handLeft.Move(new Vector3(0f, 0f, 0.1f), 5));

            Assert.AreEqual(0.6, panZoom.CurrentScale, 0.1, "Rotated slate did not zoom in using far interaction");

            yield return(handRight.Hide());

            yield return(handLeft.Hide());
        }
示例#11
0
        public IEnumerator TestTapToPlaceCodeConfigurability()
        {
            TestUtilities.PlayspaceToOriginLookingForward();

            // Create a cube with Tap to Place attached
            var tapToPlaceObj = InstantiateTestSolver <TapToPlace>();

            tapToPlaceObj.target.transform.position = Vector3.forward;
            TapToPlace tapToPlace = tapToPlaceObj.solver as TapToPlace;

            // Start Placing the object immediately
            tapToPlace.AutoStart = true;

            Vector3 handStartPosition = new Vector3(0, -0.1f, 0.6f);
            var     leftHand          = new TestHand(Handedness.Left);

            yield return(leftHand.Show(handStartPosition));

            // Make sure the object is being placed after setting AutoStart
            Assert.True(tapToPlace.IsBeingPlaced);

            // Move the playspace to simulate head movement
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.left * 1.5f;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Make sure the target obj is following the head
            Assert.AreEqual(CameraCache.Main.transform.position.x, tapToPlaceObj.target.transform.position.x, "The tap to place object position.x does not match the camera position.x");

            // Stop the placement via code instead of click from the hand
            tapToPlace.StopPlacement();

            Assert.False(tapToPlace.IsBeingPlaced);

            // Move the playspace to simulate head movement again
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.right;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Make sure the target obj is NOT following the head
            Assert.AreNotEqual(CameraCache.Main.transform.position.x, tapToPlaceObj.target.transform.position.x, "The tap to place object position.x matches the camera position.x, when it should not");
        }
示例#12
0
        public IEnumerator TestSolverSwap()
        {
            // Reset view to origin
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.zero;
                p.LookAt(Vector3.forward);
            });

            // Instantiate and setup RadialView to place object in the view center.
            var        testObjects      = InstantiateTestSolver <RadialView>();
            RadialView radialViewSolver = (RadialView)testObjects.solver;

            radialViewSolver.MinDistance    = 2.0f;
            radialViewSolver.MaxDistance    = 2.0f;
            radialViewSolver.MinViewDegrees = 0.0f;
            radialViewSolver.MaxViewDegrees = 0.0f;

            // Let RadialView update the target object
            yield return(WaitForFrames(2));

            // Make sure Radial View is placing object in center of View, so we can later check that a solver swap actually moved the target object.
            TestUtilities.AssertAboutEqual(testObjects.target.transform.position, Vector3.forward * 2.0f, "RadialView does not place object in center of view");

            // Disable the old solver
            radialViewSolver.enabled = false;

            // Add a another solver during runtime, give him a specific location to check whether the new solver updates the target object.
            Orbital orbitalSolver = AddSolverComponent <Orbital>(testObjects.target);

            orbitalSolver.WorldOffset = Vector3.zero;
            orbitalSolver.LocalOffset = Vector3.down * 2.0f;

            // Let Orbital update the target object
            yield return(WaitForFrames(2));

            // Make sure Orbital is now updating the target object
            TestUtilities.AssertAboutEqual(testObjects.target.transform.position, Vector3.down * 2.0f, "Orbital solver did not place object below origin");

            // Swap solvers once again during runtime
            radialViewSolver.enabled = true;
            orbitalSolver.enabled    = false;

            // Let RadialView update the target object
            yield return(WaitForFrames(2));

            // Make sure Radial View is now updating the target object once again.
            TestUtilities.AssertAboutEqual(testObjects.target.transform.position, Vector3.forward * 2.0f, "RadialView solver did not place object in center of view");
        }
        public IEnumerator TestEyeTrackingTargetColliderOnParent()
        {
            // Eye tracking configuration profile should set eye based gaze
            var profile = AssetDatabase.LoadAssetAtPath(eyeTrackingConfigurationProfilePath, typeof(MixedRealityToolkitConfigurationProfile)) as MixedRealityToolkitConfigurationProfile;

            MixedRealityToolkit.Instance.ResetConfiguration(profile);

            // Reset view to origin
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.zero;
                p.LookAt(Vector3.forward);
            });

            // Build a target to collide against
            var parentOfTargetObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

            parentOfTargetObject.name = "ParentOfTargetObject";
            parentOfTargetObject.AddComponent <BoxCollider>();
            parentOfTargetObject.transform.localScale = new Vector3(25.0f, 25.0f, 0.2f);
            parentOfTargetObject.transform.Rotate(Vector3.up, 180.0f); // Rotate parentOfTargetObject so forward faces camera
            parentOfTargetObject.transform.position = Vector3.forward * 10.0f;

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

            childOfTargetObject.name = "childOfTargetObject";
            var eyeTrackingTargetComponent = childOfTargetObject.AddComponent <EyeTrackingTarget>();

            childOfTargetObject.transform.localScale = new Vector3(20.0f, 20.0f, 0.1f);
            childOfTargetObject.transform.SetParent(parentOfTargetObject.transform);

            //We need to simulate an eye in the direction of the parent object
            var inputSimulationService = PlayModeTestUtilities.GetInputSimulationService();

            //We don't need any other input just eye gaze
            inputSimulationService.UserInputEnabled      = false;
            inputSimulationService.EyeGazeSimulationMode = EyeGazeSimulationMode.CameraForwardAxis;

            yield return(null);

            var isEyeGazeActive = InputRayUtils.TryGetEyeGazeRay(out var eyegazeRay);

            Assert.True(isEyeGazeActive);
            yield return(null);

            Assert.True(EyeTrackingTarget.LookedAtTarget != null);
            Assert.True(EyeTrackingTarget.LookedAtEyeTarget.name == "childOfTargetObject");
        }
 /// <summary>
 /// Creates a playspace and moves it into a default position.
 /// </summary>
 public static void InitializePlayspace()
 {
     if (MixedRealityPlayspace.Transform.parent == null)
     {
         GameObject gameObject = new GameObject("MRTKPlayspaceTestParent");
         MixedRealityPlayspace.Transform.parent = gameObject.transform;
         gameObject.transform.position          = ArbitraryParentPose.position;
         gameObject.transform.rotation          = ArbitraryParentPose.rotation;
     }
     MixedRealityPlayspace.PerformTransformation(
         p =>
     {
         p.position = new Vector3(1.0f, 1.5f, -2.0f);
         p.LookAt(Vector3.zero);
     });
 }
        public IEnumerator Test01_WhizzySphere()
        {
            TestUtilities.InitializeMixedRealityToolkitAndCreateScenes(true);

            MixedRealityPlayspace.PerformTransformation(
                p =>
            {
                p.position = new Vector3(1.0f, 1.5f, -2.0f);
                p.LookAt(Vector3.zero);
            });

            var testLight = new GameObject("TestLight");
            var light     = testLight.AddComponent <Light>();

            light.type = LightType.Directional;
            testLight.transform.position = new Vector3(-2.5f, 3.0f, -1.2f);
            testLight.transform.LookAt(Vector3.zero);

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

            testObject.transform.localScale = Vector3.one * 0.1f;

            var stopwatch = new System.Diagnostics.Stopwatch();

            stopwatch.Start();
            while (stopwatch.Elapsed.TotalSeconds < 10.0f)
            {
                float t   = (float)stopwatch.Elapsed.TotalSeconds;
                var   pi2 = 2.0f * Mathf.PI;

                var a = 0.5f * t;
                var b = 0.75f * t;
                var c = 0.9f * t;
                testObject.transform.position = new Vector3(
                    Mathf.Sin((a + 0.0f) * pi2),
                    Mathf.Sin((b + 0.333f) * pi2),
                    Mathf.Sin((c + 0.666f) * pi2)
                    );
                yield return(new WaitForFixedUpdate());
            }
            stopwatch.Stop();

            GameObject.Destroy(testLight);
            GameObject.Destroy(testObject);
            // Wait for a frame to give Unity a change to actually destroy the object
            yield return(null);
        }
示例#16
0
        public IEnumerator TestDirectionalIndicator()
        {
            // Reset view to origin
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.zero;
                p.LookAt(Vector3.forward);
            });

            const float ANGLE_THRESHOLD = 30.0f;

            var directionTarget = GameObject.CreatePrimitive(PrimitiveType.Cylinder);

            directionTarget.transform.position = 10.0f * Vector3.right;

            // Instantiate our test gameobject with solver.
            var testObjects = InstantiateTestSolver <DirectionalIndicator>();

            var indicatorSolver = testObjects.solver as DirectionalIndicator;

            indicatorSolver.DirectionalTarget = directionTarget.transform;

            var indicatorMesh = indicatorSolver.GetComponent <Renderer>();

            // Test that solver points to the right and is visible
            yield return(WaitForFrames(2));

            Assert.LessOrEqual(Vector3.Angle(indicatorSolver.transform.up, directionTarget.transform.position.normalized), ANGLE_THRESHOLD);
            Assert.IsTrue(indicatorMesh.enabled);

            directionTarget.transform.position = -10.0f * Vector3.right;

            // Test that solver points to the left now and is visible
            yield return(WaitForFrames(2));

            Assert.LessOrEqual(Vector3.Angle(indicatorSolver.transform.up, directionTarget.transform.position.normalized), ANGLE_THRESHOLD);
            Assert.IsTrue(indicatorMesh.enabled);

            // Test that the solver is invisible
            directionTarget.transform.position = 5.0f * Vector3.forward;

            yield return(WaitForFrames(2));

            Assert.IsFalse(indicatorMesh.enabled);
        }
        /// <summary>
        /// Instantiates a bounds control at boundsControlStartCenter
        /// box is at scale boundsControlStartScale
        /// </summary>
        private BoundsControl InstantiateSceneAndDefaultBbox()
        {
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.transform.position = boundsControlStartCenter;
            BoundsControl bbox = cube.AddComponent <BoundsControl>();

            MixedRealityPlayspace.PerformTransformation(
                p =>
            {
                p.position = Vector3.zero;
                p.LookAt(cube.transform.position);
            });

            bbox.transform.localScale = boundsControlStartScale;
            bbox.Active = true;

            return(bbox);
        }
示例#18
0
        /// <summary>
        /// Instantiates a bounding box at 0, 0, -1.5f
        /// box is at scale .5, .5, .5
        /// </summary>
        private BoundingBox InstantiateSceneAndDefaultBbox()
        {
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube.transform.position = Vector3.forward * 1.5f;
            BoundingBox bbox = cube.AddComponent <BoundingBox>();

            MixedRealityPlayspace.PerformTransformation(
                p =>
            {
                p.position = Vector3.zero;
                p.LookAt(cube.transform.position);
            });

            bbox.transform.localScale *= 0.5f;
            bbox.Active = true;

            return(bbox);
        }
        public IEnumerator TestEyeTrackingTarget()
        {
            // Eye tracking configuration profile should set eye based gaze
            var profile = AssetDatabase.LoadAssetAtPath(eyeTrackingConfigurationProfilePath, typeof(MixedRealityToolkitConfigurationProfile)) as MixedRealityToolkitConfigurationProfile;

            MixedRealityToolkit.Instance.ResetConfiguration(profile);

            // Reset view to origin
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.zero;
                p.LookAt(Vector3.forward);
            });

            string targetName = "eyetrackingTargetObject";

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

            eyetrackingTargetObject.name = targetName;
            var eyeTrackingTargetComponent = eyetrackingTargetObject.AddComponent <EyeTrackingTarget>();

            eyetrackingTargetObject.transform.position = Vector3.forward;

            // We need to simulate an eye in the direction of the parent object
            var inputSimulationService = PlayModeTestUtilities.GetInputSimulationService();

            // We don't need any other input just eye gaze
            inputSimulationService.UserInputEnabled      = false;
            inputSimulationService.EyeGazeSimulationMode = EyeGazeSimulationMode.CameraForwardAxis;

            yield return(null);

            var isEyeGazeActive = InputRayUtils.TryGetEyeGazeRay(out var eyegazeRay);

            Assert.True(isEyeGazeActive);
            yield return(null);

            Assert.True(EyeTrackingTarget.LookedAtTarget != null);
            Assert.True(EyeTrackingTarget.LookedAtEyeTarget.name == targetName);
        }
示例#20
0
        public IEnumerator ManipulationHandlerOneHandMoveNear()
        {
            // 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;

            // 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);

            const int numCircleSteps = 10;
            const int numHandSteps   = 3;

            Vector3  initialHandPosition = new Vector3(0, 0, 0.5f);
            Vector3  initialGrabPosition = new Vector3(-0.1f, -0.1f, 1f); // grab the left bottom corner of the cube
            TestHand hand = new TestHand(Handedness.Right);

            // do this test for every one hand rotation mode
            foreach (ManipulationHandler.RotateInOneHandType type in Enum.GetValues(typeof(ManipulationHandler.RotateInOneHandType)))
            {
                manipHandler.OneHandRotationModeNear = type;

                TestUtilities.PlayspaceToOriginLookingForward();

                yield return(hand.Show(initialHandPosition));

                var pointer = hand.GetPointer <SpherePointer>();
                Assert.IsNotNull(pointer);

                yield return(hand.MoveTo(initialGrabPosition, numHandSteps));

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

                // save relative pos grab point to object
                Vector3 initialOffsetGrabToObjPivot = pointer.Position - testObject.transform.position;
                Vector3 initialGrabPointInObject    = testObject.transform.InverseTransformPoint(manipHandler.GetPointerGrabPoint(pointer.PointerId));

                // full circle
                const int degreeStep = 360 / numCircleSteps;

                // rotating the pointer in a circle around "the user"
                for (int i = 1; i <= numCircleSteps; ++i)
                {
                    // rotate main camera (user)
                    MixedRealityPlayspace.PerformTransformation(
                        p =>
                    {
                        p.position         = MixedRealityPlayspace.Position;
                        Vector3 rotatedFwd = Quaternion.AngleAxis(degreeStep * i, Vector3.up) * Vector3.forward;
                        p.LookAt(rotatedFwd);
                    });

                    yield return(null);

                    // move hand with the camera
                    Vector3 newHandPosition = Quaternion.AngleAxis(degreeStep * i, Vector3.up) * initialGrabPosition;
                    yield return(hand.MoveTo(newHandPosition, numHandSteps));

                    if (type == ManipulationHandler.RotateInOneHandType.RotateAboutObjectCenter)
                    {
                        // make sure that the offset between hand and object centre hasn't changed while rotating
                        Vector3 offsetRotated = pointer.Position - testObject.transform.position;
                        TestUtilities.AssertAboutEqual(offsetRotated, initialOffsetGrabToObjPivot, $"Object offset changed during rotation using {type}");
                    }
                    else
                    {
                        // make sure that the offset between grab point and object pivot hasn't changed while rotating
                        Vector3 grabPoint     = manipHandler.GetPointerGrabPoint(pointer.PointerId);
                        Vector3 cornerRotated = testObject.transform.TransformPoint(initialGrabPointInObject);
                        TestUtilities.AssertAboutEqual(cornerRotated, grabPoint, $"Grab point on object changed during rotation using {type}");
                    }
                }

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

                yield return(hand.Hide());
            }
        }
示例#21
0
        public IEnumerator ManipulationHandlerOneHandMoveFar()
        {
            // 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;

            // 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);

            const int numCircleSteps = 10;
            const int numHandSteps   = 3;

            Vector3 initialHandPosition = new Vector3(0.04f, -0.18f, 0.3f); // grab point on the lower center part of the cube

            TestHand hand = new TestHand(Handedness.Right);

            // do this test for every one hand rotation mode
            foreach (ManipulationHandler.RotateInOneHandType type in Enum.GetValues(typeof(ManipulationHandler.RotateInOneHandType)))
            {
                // TODO: grab point is moving in this test and has to be covered by a different test
                if (type == ManipulationHandler.RotateInOneHandType.MaintainOriginalRotation)
                {
                    continue;
                }

                manipHandler.OneHandRotationModeFar = type;

                TestUtilities.PlayspaceToOriginLookingForward();

                yield return(hand.Show(initialHandPosition));

                yield return(null);

                // pinch and let go of the object again to make sure that any rotation adjustment we're doing is applied
                // at the beginning of our test and doesn't interfere with our grab position on the cubes surface while we're moving around
                yield return(hand.SetGesture(ArticulatedHandPose.GestureId.Pinch));

                yield return(new WaitForFixedUpdate());

                yield return(null);

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

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


                // save relative pos grab point to object - for far interaction we need to check the grab point where the pointer ray hits the manipulated object
                InputSimulationService    simulationService = PlayModeTestUtilities.GetInputSimulationService();
                IMixedRealityController[] inputControllers  = simulationService.GetActiveControllers();
                // assume hand is first controller and pointer for this test
                IMixedRealityController handController = inputControllers[0];
                IMixedRealityPointer    handPointer    = handController.InputSource.Pointers[0];
                Vector3 initialGrabPosition            = handPointer.Result.Details.Point;
                Vector3 initialOffsetGrabToObjPivot    = MixedRealityPlayspace.InverseTransformPoint(initialGrabPosition) - MixedRealityPlayspace.InverseTransformPoint(testObject.transform.position);

                // full circle
                const int degreeStep = 360 / numCircleSteps;

                // rotating the pointer in a circle around "the user"
                for (int i = 1; i <= numCircleSteps; ++i)
                {
                    // rotate main camera (user)
                    MixedRealityPlayspace.PerformTransformation(
                        p =>
                    {
                        p.position         = MixedRealityPlayspace.Position;
                        Vector3 rotatedFwd = Quaternion.AngleAxis(degreeStep * i, Vector3.up) * Vector3.forward;
                        p.LookAt(rotatedFwd);
                    });

                    yield return(null);

                    // move hand with the camera
                    Vector3 newHandPosition = Quaternion.AngleAxis(degreeStep * i, Vector3.up) * initialHandPosition;
                    yield return(hand.MoveTo(newHandPosition, numHandSteps));

                    yield return(new WaitForFixedUpdate());

                    yield return(null);


                    // make sure that the offset between grab point and object pivot hasn't changed while rotating
                    Vector3 newGrabPosition = handPointer.Result.Details.Point;
                    Vector3 offsetRotated   = MixedRealityPlayspace.InverseTransformPoint(newGrabPosition) - MixedRealityPlayspace.InverseTransformPoint(testObject.transform.position);
                    TestUtilities.AssertAboutEqual(offsetRotated, initialOffsetGrabToObjPivot, "Grab point on object changed during rotation");
                }

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

                yield return(hand.Hide());
            }
        }
示例#22
0
        public IEnumerator TestFollowDistance()
        {
            // Reset view to origin
            TestUtilities.PlayspaceToOriginLookingForward();

            // Instantiate our test GameObject with solver.
            var testObjects  = InstantiateTestSolver <Follow>();
            var followSolver = (Follow)testObjects.solver;

            followSolver.MoveToDefaultDistanceLerpTime = 0;
            testObjects.handler.TrackedTargetType      = TrackedObjectType.Head;
            var targetTransform = testObjects.target.transform;

            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Test distance remains within min/max bounds
            float distanceToHead = Vector3.Distance(targetTransform.position, CameraCache.Main.transform.position);

            Assert.LessOrEqual(distanceToHead, followSolver.MaxDistance, "Follow exceeded max distance");
            Assert.GreaterOrEqual(distanceToHead, followSolver.MinDistance, "Follow subceeded min distance");

            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.back * 2;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            distanceToHead = Vector3.Distance(targetTransform.position, CameraCache.Main.transform.position);
            Assert.LessOrEqual(distanceToHead, followSolver.MaxDistance, "Follow exceeded max distance");
            Assert.GreaterOrEqual(distanceToHead, followSolver.MinDistance, "Follow subceeded min distance");

            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.forward * 4;
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            distanceToHead = Vector3.Distance(targetTransform.position, CameraCache.Main.transform.position);
            Assert.LessOrEqual(distanceToHead, followSolver.MaxDistance, "Follow exceeded max distance");
            Assert.GreaterOrEqual(distanceToHead, followSolver.MinDistance, "Follow subceeded min distance");

            // Test VerticalMaxDistance
            followSolver.VerticalMaxDistance = 0.1f;
            targetTransform.position         = Vector3.forward;
            targetTransform.rotation         = Quaternion.identity;
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.zero;
                p.LookAt(Vector3.forward);
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.LookAt(Vector3.forward + Vector3.up);
            });

            yield return(new WaitForFixedUpdate());

            yield return(null);

            float yDistance = targetTransform.position.y - CameraCache.Main.transform.position.y;

            Assert.AreEqual(followSolver.VerticalMaxDistance, yDistance);

            followSolver.VerticalMaxDistance = 0f;
        }
示例#23
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());
            }
示例#24
0
        public IEnumerator TestSurfaceMagnetism()
        {
            // Reset view to origin
            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.zero;
                p.LookAt(Vector3.forward);
            });

            // Build wall to collide against
            var wall = GameObject.CreatePrimitive(PrimitiveType.Cube);

            wall.transform.localScale = new Vector3(25.0f, 25.0f, 0.2f);
            wall.transform.Rotate(Vector3.up, 180.0f); // Rotate wall so forward faces camera
            wall.transform.position = Vector3.forward * 10.0f;

            yield return(WaitForFrames(2));

            // Instantiate our test GameObject with solver.
            // Set layer to ignore raycast so solver doesn't raycast itself (i.e BoxCollider)
            var testObjects = InstantiateTestSolver <SurfaceMagnetism>();

            testObjects.target.layer = LayerMask.NameToLayer("Ignore Raycast");
            SurfaceMagnetism surfaceMag = testObjects.solver as SurfaceMagnetism;

            var targetTransform = testObjects.target.transform;
            var cameraTransform = CameraCache.Main.transform;

            yield return(WaitForFrames(2));

            // Confirm that the surfacemagnetic cube is about on the wall straight ahead
            Assert.LessOrEqual(Vector3.Distance(targetTransform.position, wall.transform.position), DistanceThreshold);

            // Rotate the camera
            Vector3 cameraDir = Vector3.forward + Vector3.right;

            MixedRealityPlayspace.PerformTransformation(p =>
            {
                p.position = Vector3.zero;
                p.LookAt(cameraDir);
            });

            // Calculate where our camera hits the wall
            RaycastHit hitInfo;

            Assert.IsTrue(UnityEngine.Physics.Raycast(Vector3.zero, cameraDir, out hitInfo), "Raycast from camera did not hit wall");

            // Let SurfaceMagnetism update
            yield return(WaitForFrames(2));

            // Confirm that the surfacemagnetic cube is on the wall with camera rotated
            Assert.LessOrEqual(Vector3.Distance(targetTransform.position, hitInfo.point), DistanceThreshold);

            // Default orientation mode is TrackedTarget, test object should be facing camera
            Assert.IsTrue(Mathf.Approximately(-1.0f, Vector3.Dot(targetTransform.forward.normalized, cameraTransform.forward.normalized)));

            // Change default orientation mode to surface normal
            surfaceMag.CurrentOrientationMode = SurfaceMagnetism.OrientationMode.SurfaceNormal;

            yield return(WaitForFrames(2));

            // Test object should now be facing into the wall (i.e Z axis)
            Assert.IsTrue(Mathf.Approximately(1.0f, Vector3.Dot(targetTransform.forward.normalized, Vector3.forward)));
        }
        public IEnumerator TestSimulatedGlobalSelectInputOnPrefab()
        {
            // Face the camera in the opposite direction so we don't focus on button
            MixedRealityPlayspace.PerformTransformation(
                p =>
            {
                p.position = Vector3.zero;
                p.LookAt(Vector3.back);
            });

            // Load interactable prefab
            GameObject   interactableObject;
            Interactable interactable;
            Transform    translateTargetObject;

            // Place out of the way of any pointers
            InstantiateDefaultInteractablePrefab(
                new Vector3(10f, 0.0f, 0.5f),
                new Vector3(-90f, 0f, 0f),
                out interactableObject,
                out interactable,
                out translateTargetObject);

            // Subscribe to interactable's on click so we know the click went through
            bool wasClicked = false;

            interactable.OnClick.AddListener(() => { wasClicked = true; });

            // Set interactable to global
            interactable.IsGlobal = true;

            Vector3 targetStartPosition = translateTargetObject.localPosition;

            yield return(null);

            // Find an input source to associate with the input event (doesn't matter which one)
            IMixedRealityInputSource defaultInputSource = MixedRealityToolkit.InputSystem.DetectedInputSources.FirstOrDefault();

            Assert.NotNull(defaultInputSource, "At least one input source must be present for this test to work.");

            // Add interactable as a global listener
            // This is only necessary if IsGlobal is being set manually. If it's set in the inspector, interactable will register itself in OnEnable automatically.
            MixedRealityToolkit.InputSystem.PushModalInputHandler(interactableObject);

            // Raise a select down input event, then wait for transition to take place
            MixedRealityToolkit.InputSystem.RaiseOnInputDown(defaultInputSource, Handedness.None, interactable.InputAction);
            // Wait for at least one frame explicitly to ensure the input goes through
            yield return(new WaitForFixedUpdate());

            float pressStartTime = Time.time;
            bool  wasTranslated  = false;

            while (Time.time < pressStartTime + buttonPressAnimationDelay)
            {   // If the transform is moved at any point during this interval, we were successful
                yield return(new WaitForFixedUpdate());

                wasTranslated |= targetStartPosition != translateTargetObject.localPosition;
            }

            // Raise a select up input event, then wait for transition to take place
            MixedRealityToolkit.InputSystem.RaiseOnInputUp(defaultInputSource, Handedness.Right, interactable.InputAction);
            // Wait for at least one frame explicitly to ensure the input goes through
            yield return(new WaitForFixedUpdate());

            yield return(new WaitForSeconds(buttonReleaseAnimationDelay));

            Assert.True(wasClicked, "Interactable was not clicked.");
            Assert.True(wasTranslated, "Transform target object was not translated by action.");
            Assert.False(interactable.HasFocus, "Interactable had focus");

            // Remove as global listener
            MixedRealityToolkit.InputSystem.PopModalInputHandler();
        }