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)); }
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)); } }
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); }
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"); }
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); }
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); }
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); }
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(); }
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"); }
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); }
/// <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()); }
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()); }
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); }
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(); }