/Rendering/Cameras/IsometricCamera.cs
C# | 309 lines | 201 code | 29 blank | 79 comment | 3 complexity | 3bca0f1809aee0ff9686213752405e59 MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.IO;
- using Delta.Engine;
- using Delta.InputSystem;
- using Delta.Utilities;
- using Delta.Utilities.Datatypes;
- using Delta.Utilities.Helpers;
- using NUnit.Framework;
-
- namespace Delta.Rendering.Cameras
- {
- /// <summary>
- /// 3D isometric perspective camera which works as LookAtCamera and has its
- /// target but the different is that it has isometric projection.
- /// </summary>
- public class IsometricCamera : BaseCamera
- {
- #region Constants
- /// <summary>
- /// The current version of the implementation of this Camera class.
- /// </summary>
- private const int ImplementationVersion = 1;
-
- /// <summary>
- /// The Move speed Per Second.
- /// </summary>
- private const float MPS = 100.0f;
- #endregion
-
- #region Position (Public)
- /// <summary>
- /// The camera position
- /// </summary>
- public override Vector Position
- {
- get
- {
- return position;
- }
- set
- {
- position = value;
- Target = position + (lookDirection * distance);
- }
- }
- #endregion
-
- #region Target (Public)
- /// <summary>
- /// The camera target position.
- /// </summary>
- public override Vector Target
- {
- get
- {
- return target;
- }
- set
- {
- target = value;
- position = target - (lookDirection * distance);
- }
- }
- #endregion
-
- #region Distance (Public)
- /// <summary>
- /// The distance between target position and camera position.
- /// </summary>
- public override float Distance
- {
- get
- {
- return distance;
- }
- set
- {
- // The effect of the distance is invariant for the IsometricCamera
- // because it uses orthographics projection so we actually "fake"
- // the behavior of zooming/unzooming by scaling the whole world
-
- // only positive values are accepted for distance!
- if (value > 0.0f)
- {
- distance = value;
-
- // update the camera position
- position = target - (lookDirection * distance);
-
- // the larger the distance, the lower the scaling
- // + some additional adjustment
- scale = Matrix.CreateScale(distance);
- }
- }
- }
- #endregion
-
- #region LookDirection (Public)
- /// <summary>
- /// override the look direction to prevent the set accessor is making
- /// bad stuff. An isometric camera always have the same lookdirection,
- /// which is set in the constructor.
- /// </summary>
- public override Vector LookDirection
- {
- get
- {
- return lookDirection;
- }
- set
- {
- }
- }
- #endregion
-
- #region Private
-
- #region scale (Private)
- /// <summary>
- /// Scaling that emulates the Distance property for the isometric camera
- /// </summary>
- private Matrix scale;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create isometric camera
- /// </summary>
- /// <param name="setPosition">Camera initial position.</param>
- public IsometricCamera(Vector setPosition)
- : base(setPosition)
- {
- lookDirection = new Vector(1, 1, -1);
- // Set some default values
- Distance = 1f;
- }
- #endregion
-
- #region Zoom (Public)
- /// <summary>
- /// Zoom in or out. if respectFPS is set to true, Time.Delta will be taken
- /// into account. E.g.: set this to true for hold-able buttons.
- /// </summary>
- /// <param name="zoomIn">if set to <c>true</c> [zoom in].</param>
- public void Zoom(bool zoomIn)
- {
- if (IsLocked)
- {
- return;
- }
- float zoomSpeed = MathHelper.Max(Distance, 0.1f) * 0.1f *
- MPS * (Time.Delta * 10f);
- // Limit zoomSpeed, else we get into millions too quickly
- zoomSpeed = MathHelper.Min(zoomSpeed, 10 * Time.Delta);
- Distance += zoomIn
- ? -zoomSpeed
- : zoomSpeed;
- }
- #endregion
-
- #region UpdateProjectionMatrix (Public)
- /// <summary>
- /// Update projection matrix
- /// </summary>
- public override void UpdateProjectionMatrix()
- {
- // isometric uses an orthographic projection.
- float halfWidth = Application.Window.ViewportPixelWidth;
- float halfHeight = Application.Window.ViewportPixelHeight;
- projectionMatrix = Matrix.CreateOrthographic(-halfWidth, halfWidth,
- halfHeight, -halfHeight, NearPlane, FarPlane);
- }
- #endregion
-
- #region Save (Public)
- /// <summary>
- /// Override saving data from BinaryStream.
- /// </summary>
- /// <param name="dataWriter">Binary writer used for writing data.</param>
- public override void Save(BinaryWriter dataWriter)
- {
- base.Save(dataWriter);
-
- // Save the implementation version first
- dataWriter.Write(ImplementationVersion);
-
- // just need to save the scale matrix here
- scale.Save(dataWriter);
- }
- #endregion
-
- #region Load (Public)
- /// <summary>
- /// Override loading data from BinaryStream.
- /// </summary>
- /// <param name="reader">Binary reader used for reading data.</param>
- public override void Load(BinaryReader reader)
- {
- base.Load(reader);
-
- // First read the implementation version
- int version = reader.ReadInt32();
- switch (version)
- {
- // Version 1
- case 1:
- // Need just to read the scale matrix here
- scale.Load(reader);
- break;
-
- default:
- Log.InvalidVersionWarning(GetType().Name + ": " + Name,
- version, ImplementationVersion);
- break;
- }
- }
- #endregion
-
- #region Methods (Private)
-
- #region SetupInputCommands
- /// <summary>
- /// Setup the connection between input commands and camera movement.
- /// </summary>
- protected override void SetupInputCommands()
- {
- #region Zoom
- Input.Commands[Command.CameraZoomIn].Add(delegate
- {
- Zoom(true);
- });
- Input.Commands[Command.CameraZoomOut].Add(delegate
- {
- Zoom(false);
- });
- #endregion
- }
- #endregion
-
- #region UpdateViewMatrix
- protected override void UpdateViewMatrix()
- {
- base.UpdateViewMatrix();
- }
- #endregion
-
- #endregion
-
- /// <summary>
- /// Tests
- /// </summary>
- internal class IsometricCameraTests
- {
- #region TestSaveAndLoad (LongRunning)
- /// <summary>
- /// Test save and load functionality of the Graph class
- /// </summary>
- [Test, Category("LongRunning")]
- public void TestSaveAndLoad()
- {
- // Creation of the graph
- IsometricCamera isoCamera = new IsometricCamera(new Vector(3, -6, 8))
- {
- // BaseCamera
- LookDirection = new Vector(-1, 2, -1),
- Target = new Vector(3, 4, 1),
- Rotation = new Vector(3, 1, 0),
- FieldOfView = 65,
- FarPlane = 205,
- NearPlane = 0.15f,
- AlwaysNeedsUpdate = true,
- IsLocked = true,
- // IsometricCamera
- scale = Matrix.CreateScale(0.3f, 1.4f, 0.58f),
- };
-
- // Saving
- MemoryStream savedStream = new MemoryStream();
- BinaryWriter writer = new BinaryWriter(savedStream);
- isoCamera.Save(writer);
- writer.Flush();
- writer = null;
-
- // Loading
- savedStream.Position = 0;
- BinaryReader reader = new BinaryReader(savedStream);
- IsometricCamera loadedCamera = new IsometricCamera(Vector.Zero);
- loadedCamera.Load(reader);
-
- // Checking
- // BaseCamera values
- Assert.Equal(loadedCamera.LookDirection, isoCamera.LookDirection);
- Assert.Equal(loadedCamera.Target, isoCamera.Target);
- Assert.Equal(loadedCamera.Rotation, isoCamera.Rotation);
- Assert.Equal(loadedCamera.FieldOfView, isoCamera.FieldOfView);
- Assert.Equal(loadedCamera.FarPlane, isoCamera.FarPlane);
- Assert.Equal(loadedCamera.NearPlane, isoCamera.NearPlane);
- Assert.Equal(loadedCamera.AlwaysNeedsUpdate,
- isoCamera.AlwaysNeedsUpdate);
- Assert.Equal(loadedCamera.IsLocked, isoCamera.IsLocked);
- // IsometricCamera values
- Assert.Equal(loadedCamera.scale, isoCamera.scale);
- }
- #endregion
- }
- }
- }