/Rendering/Cameras/IsoPerspectiveCamera.cs
C# | 292 lines | 185 code | 30 blank | 77 comment | 2 complexity | 499a73a8321c17cdfa4a821ab2d867ed MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.IO;
- using Delta.Engine;
- using Delta.Utilities;
- using Delta.Utilities.Datatypes;
- using NUnit.Framework;
-
- namespace Delta.Rendering.Cameras
- {
- /// <summary>
- /// 3D Iso perspective camera which works as LookAtCamera and has its target
- /// but the different is that it has iso-perspective projection.
- /// </summary>
- public class IsoPerspectiveCamera : BaseCamera
- {
- #region Constants
- /// <summary>
- /// The current version of the implementation of this Camera class.
- /// </summary>
- private const int ImplementationVersion = 1;
- #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(100.0f / distance);
- }
- }
- }
- #endregion
-
- #region LookDirection (Public)
- /// <summary>
- /// The look direction.
- /// </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
-
- #region cameraShake (Private)
- /// <summary>
- /// The shake value
- /// </summary>
- private Vector cameraShake;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create iso perspective camera
- /// </summary>
- /// <param name="setPosition">Set position</param>
- public IsoPerspectiveCamera(Vector setPosition)
- : base(setPosition)
- {
- lookDirection = new Vector(1, 1, -1);
- // Set some default values
- Distance = 1f;
- cameraShake = Vector.Zero;
- }
- #endregion
-
- #region Shake (Public)
- /// <summary>
- /// Shake
- /// </summary>
- /// <param name="amount">The amount.</param>
- public void Shake(float amount)
- {
- cameraShake.Z = amount;
- }
- #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
- 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);
-
- // We currently only support our version, if more versions are added,
- // we need to do different loading code depending on the version here.
- 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;
- } // switch
- }
- #endregion
-
- #region Methods (Private)
-
- #region UpdateViewMatrix
- /// <summary>
- /// Update view matrix
- /// </summary>
- protected override void UpdateViewMatrix()
- {
- // isometric uses a simple look at view.
- viewMatrix = Matrix.CreateLookAt(Position + cameraShake, Target,
- Vector.UnitZ);
- Matrix.Multiply(ref viewMatrix, ref scale, ref viewMatrix);
- }
- #endregion
-
- #region InternalRun
- /// <summary>
- /// Updates the camera
- /// </summary>
- protected override void InternalRun()
- {
-
- // slowly decrease the camera shaking value unti we reach zero.
- cameraShake.Z = (cameraShake.Z > 0)
- ? +
- cameraShake.Z - Time.Delta * 4f
- : 0f;
-
- base.InternalRun();
- }
- #endregion
-
- #endregion
-
- /// <summary>
- /// Tests
- /// </summary>
- internal class IsoPerspectiveTests
- {
- #region TestSaveAndLoad (LongRunning)
- /// <summary>
- /// Test save and load functionality of the Graph class
- /// </summary>
- [Test, Category("LongRunning")]
- public void TestSaveAndLoad()
- {
- // Creation of the graph
- IsoPerspectiveCamera isoPerspectiveCamera =
- new IsoPerspectiveCamera(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,
- // IsoPerspectiveCamera
- scale = Matrix.CreateScale(0.3f, 1.4f, 0.58f),
- };
-
- // Saving
- MemoryStream savedStream = new MemoryStream();
- BinaryWriter writer = new BinaryWriter(savedStream);
- isoPerspectiveCamera.Save(writer);
- writer.Flush();
- writer = null;
-
- // Loading
- savedStream.Position = 0;
- BinaryReader reader = new BinaryReader(savedStream);
- IsoPerspectiveCamera loadedCamera =
- new IsoPerspectiveCamera(Vector.Zero);
- loadedCamera.Load(reader);
-
- // Checking
- // BaseCamera values
- Assert.Equal(loadedCamera.LookDirection,
- isoPerspectiveCamera.LookDirection);
- Assert.Equal(loadedCamera.Target, isoPerspectiveCamera.Target);
- Assert.Equal(loadedCamera.Rotation, isoPerspectiveCamera.Rotation);
- Assert.Equal(loadedCamera.FieldOfView,
- isoPerspectiveCamera.FieldOfView);
- Assert.Equal(loadedCamera.FarPlane, isoPerspectiveCamera.FarPlane);
- Assert.Equal(loadedCamera.NearPlane, isoPerspectiveCamera.NearPlane);
- Assert.Equal(loadedCamera.AlwaysNeedsUpdate,
- isoPerspectiveCamera.AlwaysNeedsUpdate);
- Assert.Equal(loadedCamera.IsLocked, isoPerspectiveCamera.IsLocked);
- // IsoPerspectiveCamera values
- Assert.Equal(loadedCamera.scale, isoPerspectiveCamera.scale);
- }
- #endregion
- }
- }
- }