#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion #if UNITTEST using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using NUnit.Framework; namespace Nuclex.Graphics { /// Unit tests for the camera class [TestFixture] internal class CameraTest { /// Verifies that the constructor of the camera class is working [Test] public void TestConstructor() { new Camera(Matrix.Identity, Matrix.Identity); } /// /// Tests the LookAt() method of the camera class from the world's center /// [Test] public void TestLookAtFromWorldCenter() { Camera testCamera = new Camera(Matrix.Identity, Matrix.Identity); testCamera.LookAt(Vector3.UnitX); // Look to the right Vector3 leftPoint = -Vector3.UnitX; Vector3 transformed = Vector3.Transform(leftPoint, testCamera.View); // The point should be behind the camera Assert.Greater(transformed.Z, 0.0f); } /// /// Tests the LookAt() method of the camera class from an arbitrary position /// [Test] public void TestLookAtFromArbitraryPosition() { Camera testCamera = new Camera(Matrix.Identity, Matrix.Identity); testCamera.MoveTo(new Vector3(100.0f, 200.0f, 300.0f)); testCamera.LookAt(Vector3.Zero); // Look to the right Vector3 leftPoint = new Vector3(99.0f, 200.0f, 300.0f); Vector3 behindPoint = new Vector3(100.0f, 200.0f, 299.0f); Vector3 transformedLeft = Vector3.Transform(leftPoint, testCamera.View); Vector3 transformedBehind = Vector3.Transform(behindPoint, testCamera.View); // The left point should be in front of the camera Assert.Less(transformedLeft.Z, 0.0f); // The behind point should be right of the camera Assert.Greater(transformedBehind.X, 0.0f); } #if false // GeoAssertHelper /// /// Tests whether the position of a camera can be retrieved again /// [Test] public void TestPositionRetrieval() { Camera testCamera = new Camera( Matrix.CreateLookAt( new Vector3(1.2f, 3.4f, 5.6f), Vector3.One, Vector3.Up ), Matrix.Identity ); GeoAssertHelper.AreAlmostEqual( new Vector3(1.2f, 3.4f, 5.6f), testCamera.Position, 10 ); } /// /// Tests whether the position of a camera can be retrieved again /// [Test] public void TestPositionChanging() { Camera testCamera = new Camera(Matrix.Identity, Matrix.Identity); testCamera.Position = new Vector3(6.5f, 4.3f, 2.1f); GeoAssertHelper.AreAlmostEqual( new Vector3(6.5f, 4.3f, 2.1f), testCamera.Position, 10 ); } #endif /// /// Verifies that the default orthographic camera is constructed as expected /// [Test] public void TestDefaultOrthographic() { Camera defaultCamera = Camera.CreateDefaultOrthographic(); Assert.AreEqual(Vector3.Zero, defaultCamera.Position); // The point should end up in front of the camera Vector3 leftPoint = -Vector3.UnitZ; Vector3 transformed = Vector3.Transform(leftPoint, defaultCamera.View); Assert.Less(transformed.Z, 0.0f); } /// /// Verifies that the HandleControls() method of the camera is working /// [Test] public void TestHandleControls() { Camera camera = Camera.CreateDefaultOrthographic(); camera.HandleControls(OneSecondGameTime); // We can't make assumptions about which keys the user held down while // the unit test ran, so we just verify it's not blowing up. } /// /// Tests whether the camera can be moved forward using the keyboard /// [Test] public void TestKeyboardForwardMovement() { Camera camera = handleControlsOnDefaultCamera(Keys.W); Camera defaultOrthographic = Camera.CreateDefaultOrthographic(); Assert.AreEqual(defaultOrthographic.Position.X, camera.Position.X); Assert.AreEqual(defaultOrthographic.Position.Y, camera.Position.Y); Assert.Greater(defaultOrthographic.Position.Z, camera.Position.Z); } /// /// Tests whether the camera can be moved backward using the keyboard /// [Test] public void TestKeyboardBackwardMovement() { Camera camera = handleControlsOnDefaultCamera(Keys.S); Camera defaultOrthographic = Camera.CreateDefaultOrthographic(); Assert.AreEqual(defaultOrthographic.Position.X, camera.Position.X); Assert.AreEqual(defaultOrthographic.Position.Y, camera.Position.Y); Assert.Less(defaultOrthographic.Position.Z, camera.Position.Z); } /// /// Tests whether the camera can be moved to the left using the keyboard /// [Test] public void TestKeyboardLeftMovement() { Camera camera = handleControlsOnDefaultCamera(Keys.A); Camera defaultOrthographic = Camera.CreateDefaultOrthographic(); Assert.Greater(defaultOrthographic.Position.X, camera.Position.X); Assert.AreEqual(defaultOrthographic.Position.Y, camera.Position.Y); Assert.AreEqual(defaultOrthographic.Position.Z, camera.Position.Z); } /// /// Tests whether the camera can be moved to the right using the keyboard /// [Test] public void TestKeyboardRightMovement() { Camera camera = handleControlsOnDefaultCamera(Keys.D); Camera defaultOrthographic = Camera.CreateDefaultOrthographic(); Assert.Less(defaultOrthographic.Position.X, camera.Position.X); Assert.AreEqual(defaultOrthographic.Position.Y, camera.Position.Y); Assert.AreEqual(defaultOrthographic.Position.Z, camera.Position.Z); } /// /// Tests whether the camera can be moved up using the keyboard /// [Test] public void TestKeyboardUpMovement() { Camera camera = handleControlsOnDefaultCamera(Keys.R); Camera defaultOrthographic = Camera.CreateDefaultOrthographic(); Assert.AreEqual(defaultOrthographic.Position.X, camera.Position.X); Assert.Less(defaultOrthographic.Position.Y, camera.Position.Y); Assert.AreEqual(defaultOrthographic.Position.Z, camera.Position.Z); } /// /// Tests whether the camera can be moved up using the keyboard /// [Test] public void TestKeyboardDownMovement() { Camera camera = handleControlsOnDefaultCamera(Keys.F); Camera defaultOrthographic = Camera.CreateDefaultOrthographic(); Assert.AreEqual(defaultOrthographic.Position.X, camera.Position.X); Assert.Greater(defaultOrthographic.Position.Y, camera.Position.Y); Assert.AreEqual(defaultOrthographic.Position.Z, camera.Position.Z); } /// /// Tests whether the camera can be rotated upwards using the keyboard /// [Test] public void TestKeyboardUpRotation() { Camera camera = handleControlsOnDefaultCamera(Keys.NumPad2); Assert.That(camera.Forward.X, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Y, Is.GreaterThan(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated downwards using the keyboard /// [Test] public void TestKeyboardDownRotation() { Camera camera = handleControlsOnDefaultCamera(Keys.NumPad8); Assert.That(camera.Forward.X, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Y, Is.LessThan(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated to the left using the keyboard /// [Test] public void TestKeyboardLeftRotation() { Camera camera = handleControlsOnDefaultCamera(Keys.NumPad4); Assert.That(camera.Forward.X, Is.LessThan(0.0f)); Assert.That(camera.Forward.Y, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated to the right using the keyboard /// [Test] public void TestKeyboardRightRotation() { Camera camera = handleControlsOnDefaultCamera(Keys.NumPad6); Assert.That(camera.Forward.X, Is.GreaterThan(0.0f)); Assert.That(camera.Forward.Y, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated clockwise using the keyboard /// [Test] public void TestKeyboardClockwiseRotation() { Camera camera = handleControlsOnDefaultCamera(Keys.NumPad9); Assert.That(camera.Up.X, Is.GreaterThan(0.0f)); Assert.That(camera.Up.Y, Is.LessThan(1.0f)); Assert.That(camera.Up.Z, Is.EqualTo(0.0f)); } /// /// Tests whether the camera can be rotated counter-clockwise using the keyboard /// [Test] public void TestKeyboardCounterClockwiseRotation() { Camera camera = handleControlsOnDefaultCamera(Keys.NumPad7); Assert.That(camera.Right.X, Is.LessThan(1.0f)); Assert.That(camera.Right.Y, Is.GreaterThan(0.0f)); Assert.That(camera.Right.Z, Is.EqualTo(0.0f)); } /// /// Tests whether the camera can be rotated upwards using the game pad /// [Test] public void TestGamePadUpRotation() { Camera camera = handleControlsOnDefaultCamera( new GamePadDPad( ButtonState.Released, // up ButtonState.Pressed, // down ButtonState.Released, // left ButtonState.Released // right ) ); Assert.That(camera.Forward.X, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Y, Is.GreaterThan(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated downwards using the game pad /// [Test] public void TestGamePadDownRotation() { Camera camera = handleControlsOnDefaultCamera( new GamePadDPad( ButtonState.Pressed, // up ButtonState.Released, // down ButtonState.Released, // left ButtonState.Released // right ) ); Assert.That(camera.Forward.X, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Y, Is.LessThan(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated to the left using the game pad /// [Test] public void TestGamePadLeftRotation() { Camera camera = handleControlsOnDefaultCamera( new GamePadDPad( ButtonState.Released, // up ButtonState.Released, // down ButtonState.Pressed, // left ButtonState.Released // right ) ); Assert.That(camera.Forward.X, Is.LessThan(0.0f)); Assert.That(camera.Forward.Y, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated to the left using the game pad /// [Test] public void TestGamePadRightRotation() { Camera camera = handleControlsOnDefaultCamera( new GamePadDPad( ButtonState.Released, // up ButtonState.Released, // down ButtonState.Released, // left ButtonState.Pressed // right ) ); Assert.That(camera.Forward.X, Is.GreaterThan(0.0f)); Assert.That(camera.Forward.Y, Is.EqualTo(0.0f)); Assert.That(camera.Forward.Z, Is.GreaterThan(-1.0f)); } /// /// Tests whether the camera can be rotated clockwise using the game pad /// [Test] public void TestGamePadClockwiseRotation() { Camera camera = handleControlsOnDefaultCamera( new GamePadButtons(Buttons.RightShoulder) ); Assert.That(camera.Up.X, Is.GreaterThan(0.0f)); Assert.That(camera.Up.Y, Is.LessThan(1.0f)); Assert.That(camera.Up.Z, Is.EqualTo(0.0f)); } /// /// Tests whether the camera can be rotated counter-clockwise using the game pad /// [Test] public void TestGamePadCounterClockwiseRotation() { Camera camera = handleControlsOnDefaultCamera( new GamePadButtons(Buttons.LeftShoulder) ); Assert.That(camera.Right.X, Is.LessThan(1.0f)); Assert.That(camera.Right.Y, Is.GreaterThan(0.0f)); Assert.That(camera.Right.Z, Is.EqualTo(0.0f)); } /// /// Creates a default orthographic camera and lets it respond as if /// the specified keys were pressed /// /// Keys that will be reported to the camera as pressed /// The camera after it has responded to the provided controls private Camera handleControlsOnDefaultCamera(params Keys[] keys) { return handleControlsOnDefaultCamera( new KeyboardState(keys), new GamePadState() ); } /// /// Creates a default orthographic camera and lets it respond as if /// the game pad's directional pad was in the specified state /// /// State of the game pad's directional pad /// The camera after it has responded to the provided controls private Camera handleControlsOnDefaultCamera(GamePadDPad directionalPad) { return handleControlsOnDefaultCamera( new KeyboardState(), new GamePadState( new GamePadThumbSticks(), new GamePadTriggers(), new GamePadButtons(), directionalPad ) ); } /// /// Creates a default orthographic camera and lets it respond as if /// the game pad's buttons were in the specified state /// /// State of the game pad's buttons /// The camera after it has responded to the provided controls private Camera handleControlsOnDefaultCamera(GamePadButtons buttons) { return handleControlsOnDefaultCamera( new KeyboardState(), new GamePadState( new GamePadThumbSticks(), new GamePadTriggers(), buttons, new GamePadDPad() ) ); } /// /// Creates a default orthographic camera and lets it respond to the provided /// controls once with a 1 second update. /// /// /// Keyboard state that will be reported to the camera /// /// /// GamePad state that will be reported to the camera /// /// The camera after it has responded to the provided controls private Camera handleControlsOnDefaultCamera( KeyboardState keyboardState, GamePadState gamePadState ) { Camera camera = Camera.CreateDefaultOrthographic(); camera.HandleControls(OneSecondGameTime, keyboardState, gamePadState); return camera; } /// A GameTime instance in which one second has passed private static GameTime OneSecondGameTime { get { return new GameTime( TimeSpan.FromSeconds(500), TimeSpan.FromSeconds(1) ); } } } } // namespace Nuclex.Graphics #endif // UNITTEST