/Rendering/Cameras/FreeCamera.cs
C# | 467 lines | 283 code | 44 blank | 140 comment | 19 complexity | 9d2f174c66c2ac7023f14df6f48fe835 MD5 | raw file
Possible License(s): Apache-2.0
- using System.IO;
- using Delta.Engine;
- using Delta.InputSystem;
- using Delta.InputSystem.Devices;
- using Delta.Utilities;
- using Delta.Utilities.Datatypes;
- using NUnit.Framework;
-
- namespace Delta.Rendering.Cameras
- {
- /// <summary>
- /// Free camera. This camera is useful to look around in the game scene.
- /// Move and rotate the camera as you want with any input device. Not really
- /// used much in games, but useful for debugging or observing.
- /// </summary>
- public class FreeCamera : BaseCamera
- {
- #region Constants
- /// <summary>
- /// The current version of the implementation of this Camera class.
- /// </summary>
- private const int ImplementationVersion = 1;
-
- /// <summary>
- /// The default move speed per second.
- /// </summary>
- private const float MPS = 100.0f;
-
- /// <summary>
- /// Speed multiplier for mouse control
- /// </summary>
- private const float MouseSpeedFactor = 2.75f;
-
- /// <summary>
- /// Speed multiplier for keyboard control
- /// </summary>
- private const float KeyboardSpeedFactor = 1.0f;
-
- /// <summary>
- /// Limit for looking downwards
- /// </summary>
- private const float MinPitchRotation = -90 + 1; //2;
-
- /// <summary>
- /// Limit for looking upwards
- /// </summary>
- private const float MaxPitchRotation = +90 - 1; //2;
-
- /// <summary>
- /// A default position which can be used if the current camera position
- /// value isn't known (in the constructor).
- /// </summary>
- public static readonly Vector DefaultLookAtCamPosition =
- new Vector(0.0f, -5.0f, 5.0f);
-
- /// <summary>
- /// A position to a default target twhich can be used if the current camera
- /// target position value isn't known (in the constructor).
- /// </summary>
- public static readonly Vector DefaultTargetPosition = Vector.Zero;
- #endregion
-
- #region Pitch (Public)
- /// <summary>
- /// Pitch
- /// </summary>
- public float Pitch
- {
- get;
- set;
- }
- #endregion
-
- #region Yaw (Public)
- /// <summary>
- /// Yaw
- /// </summary>
- public float Yaw
- {
- get;
- set;
- }
- #endregion
-
- #region Roll (Public)
- /// <summary>
- /// Roll
- /// </summary>
- public float Roll
- {
- get;
- set;
- }
- #endregion
-
- #region IsStopMoving (Public)
- /// <summary>
- /// Flag for preventing the camera from moving.
- /// </summary>
- public bool IsStopMoving
- {
- get;
- set;
- }
- #endregion
-
- #region MovementSpeed (Public)
- public float MovementSpeed
- {
- get;
- set;
- }
- #endregion
-
- #region Private
-
- #region rotationMatrix (Private)
- /// <summary>
- /// Rotation matrix, will be computed automatically by the (Internal)Run()
- /// method.
- /// </summary>
- private Matrix rotationMatrix;
- #endregion
-
- #region UpDirection (Private)
- /// <summary>
- /// Up direction
- /// </summary>
- private Vector UpDirection
- {
- get;
- set;
- }
- #endregion
-
- #region RightDirection (Private)
- /// <summary>
- /// Right direction
- /// </summary>
- private Vector RightDirection
- {
- get;
- set;
- }
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create free camera
- /// </summary>
- /// <param name="setPosition">Camera initial position.</param>
- public FreeCamera(Vector setPosition)
- : base(setPosition)
- {
- // Default look direction for this camera.
- LookDirection = Vector.UnitY;
- UpDirection = UpVector; // Vector.UnitZ;
- RightDirection = Vector.UnitX;
- MovementSpeed = 2.5f;
- }
- #endregion
-
- #region MoveUp (Public)
- /// <summary>
- /// Moves the camera up.
- /// </summary>
- /// <param name="moveVelocity">The move velocity.</param>
- public void MoveUp(float moveVelocity)
- {
- Position += UpDirection * moveVelocity;
- }
- #endregion
-
- #region MoveDown (Public)
- /// <summary>
- /// Move the camera down.
- /// </summary>
- /// <param name="moveVelocity">Move velocity.</param>
- public void MoveDown(float moveVelocity)
- {
- Position -= UpDirection * moveVelocity;
- }
- #endregion
-
- #region MoveRight (Public)
- /// <summary>
- /// Move the camera right.
- /// </summary>
- /// <param name="moveVelocity">Move velocity.</param>
- public void MoveRight(float moveVelocity)
- {
- Position += RightDirection * moveVelocity;
- }
- #endregion
-
- #region MoveLeft (Public)
- /// <summary>
- /// Move the camera left.
- /// </summary>
- /// <param name="moveVelocity">Move velocity.</param>
- public void MoveLeft(float moveVelocity)
- {
- Position -= RightDirection * moveVelocity;
- }
- #endregion
-
- #region MoveForward (Public)
- /// <summary>
- /// Move the camera forward.
- /// </summary>
- /// <param name="moveVelocity">Move velocity.</param>
- public void MoveForward(float moveVelocity)
- {
- Position += LookDirection * moveVelocity;
- }
- #endregion
-
- #region MoveBackward (Public)
- /// <summary>
- /// Move the camera backward.
- /// </summary>
- /// <param name="moveVelocity">Move velocity.</param>
- public void MoveBackward(float moveVelocity)
- {
- Position -= LookDirection * moveVelocity;
- }
- #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);
-
- // and then all required values
- dataWriter.Write(Pitch);
- dataWriter.Write(Yaw);
- dataWriter.Write(Roll);
-
- UpDirection.Save(dataWriter);
- RightDirection.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:
- // Now read just the saved values
- Pitch = reader.ReadSingle();
- Yaw = reader.ReadSingle();
- Roll = reader.ReadSingle();
-
- UpDirection = new Vector(reader);
- RightDirection = new Vector(reader);
- break;
-
- default:
- Log.InvalidVersionWarning(GetType().Name + ": " + Name,
- version, ImplementationVersion);
- break;
- } // switch
- }
- #endregion
-
- #region Methods (Private)
-
- #region UpdateViewMatrix
- /// <summary>
- /// Update the view matrix.
- /// </summary>
- protected override void UpdateViewMatrix()
- {
- // one !?
- viewMatrix = Matrix.CreateLookAt(Position, Position + LookDirection,
- //wtf? -UpDirection);
- UpDirection);
- }
- #endregion
-
- //too buggy: Point lastTouchPosition = Point.Zero;
-
- #region InternalRun
- /// <summary>
- /// Update the free camera.
- /// </summary>
- protected override void InternalRun()
- {
- //#if DISABLED
- // Skip Input if the camera is locked!
- if (IsLocked == false)
- {
- BaseTouch touch = Input.Touch;
- BaseMouse mouse = Input.Mouse;
- if (touch.IsConnected)
- {
- if (touch.TouchIsPressed)
- {
- /*tst
- // Just always rotate
- Roll += 5.0f;//5 degrees per frame MPS * relativePosition.X * MouseSpeedFactor;
- Pitch += 0.5f;//0.5 degrees per frame.
- */
- // * suxx
- // Only dragging is supported right now ^^
- //buggy?
- Point relativePosition = touch.Position - touch.LastFramePosition;
- //Point relativePosition = touch.Position - lastTouchPosition;
- if (relativePosition != Point.Zero)
- {
- if (IsStopMoving == false)
- {
- Roll +=
- //rotation.X -=
- MPS * relativePosition.X * MouseSpeedFactor;
- Pitch -=
- //rotation.Y +=
- MPS * relativePosition.Y * MouseSpeedFactor;
- } // if
- else
- {
- // If in stop moving mode, rotate light instead of camera
- Light.RotateDirection(relativePosition * MPS *
- MouseSpeedFactor);
- }
- } // if
- if (IsStopMoving == false)
- {
- // Zoom a little into the scene
- Position += LookDirection * MovementSpeed * Time.Delta;
- }
- // * /
- } // if
- //lastTouchPosition = touch.Position;
- } // if
- else if (mouse.LeftButtonIsPressed)
- {
- Point relativePosition = mouse.Position - mouse.LastFramePosition;
- if (relativePosition != Point.Zero)
- {
- if (IsStopMoving == false)
- {
- Roll +=
- //rotation.X -=
- MPS * relativePosition.X * MouseSpeedFactor;
- //rotation.Y +=
- Pitch -=
- MPS * relativePosition.Y * MouseSpeedFactor;
- } // if
- else
- {
- // If in stop moving mode, rotate light instead of camera
- Light.RotateDirection(
- relativePosition * MPS * MouseSpeedFactor);
- }
- } // if
- if (IsStopMoving == false)
- {
- // Zoom a little into the scene
- Position += LookDirection * MovementSpeed * Time.Delta;
- }
- } // else if
- } // if
- //#endif
- rotationMatrix = Matrix.Identity;
- Matrix xRotation = Matrix.CreateRotationX(Pitch);
- Matrix yRotation = Matrix.CreateRotationY(Yaw);
- Matrix zRotation = Matrix.CreateRotationZ(-Roll);
- Matrix.Multiply(ref xRotation, ref yRotation, ref rotationMatrix);
- Matrix.Multiply(ref rotationMatrix, ref zRotation, ref rotationMatrix);
-
- LookDirection = Vector.TransformNormal(Vector.UnitY, rotationMatrix);
- UpDirection = Vector.TransformNormal(UpVector, rotationMatrix);
- RightDirection = Vector.TransformNormal(Vector.UnitX, rotationMatrix);
-
- base.InternalRun();
- }
- #endregion
-
- #endregion
-
- /// <summary>
- /// Tests
- /// </summary>
- internal class FreeCameraTests
- {
- #region TestSaveAndLoad (LongRunning)
- /// <summary>
- /// Test save and load functionality of the Graph class
- /// </summary>
- [Test, Category("LongRunning")]
- public void TestSaveAndLoad()
- {
- // Creation of the graph
- FreeCamera freeCamera = new FreeCamera(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,
- // FreeCamera
- Pitch = 3,
- Yaw = 2,
- Roll = 0.5f,
- UpDirection = -Vector.UnitZ,
- RightDirection = -Vector.UnitX,
- };
-
- // Saving
- MemoryStream savedStream = new MemoryStream();
- BinaryWriter writer = new BinaryWriter(savedStream);
- freeCamera.Save(writer);
- writer.Flush();
- writer = null;
-
- // Loading
- savedStream.Position = 0;
- BinaryReader reader = new BinaryReader(savedStream);
- FreeCamera loadedCamera = new FreeCamera(Vector.Zero);
- loadedCamera.Load(reader);
-
- // Checking
- // BaseCamera values
- Assert.Equal(loadedCamera.LookDirection, freeCamera.LookDirection);
- Assert.Equal(loadedCamera.Target, freeCamera.Target);
- Assert.Equal(loadedCamera.Rotation, freeCamera.Rotation);
- Assert.Equal(loadedCamera.FieldOfView, freeCamera.FieldOfView);
- Assert.Equal(loadedCamera.FarPlane, freeCamera.FarPlane);
- Assert.Equal(loadedCamera.NearPlane, freeCamera.NearPlane);
- Assert.Equal(loadedCamera.AlwaysNeedsUpdate,
- freeCamera.AlwaysNeedsUpdate);
- Assert.Equal(loadedCamera.IsLocked, freeCamera.IsLocked);
- // FreeCamera values
- Assert.Equal(loadedCamera.Pitch, freeCamera.Pitch);
- Assert.Equal(loadedCamera.Yaw, freeCamera.Yaw);
- Assert.Equal(loadedCamera.Roll, freeCamera.Roll);
- Assert.Equal(loadedCamera.UpDirection, freeCamera.UpDirection);
- Assert.Equal(loadedCamera.RightDirection, freeCamera.RightDirection);
- }
- #endregion
- }
- }
- }