using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.ComponentModel; namespace FSO.Common.Rendering.Framework.Camera { /// <summary> /// A basic camera for the game. /// </summary> [DisplayName("BasicCamera")] public class BasicCamera : ICamera { public float NearPlane { get; set; } public float FarPlane { get; set; } public float AspectRatioMultiplier { get; set; } protected Vector3 m_Position; protected Vector3 m_Target; protected Vector3 m_Up; protected GraphicsDevice m_Device; /// <summary> /// Creates a new BasicCamera instance. Assumes projection is full screen! /// </summary> /// <param name="device">A GraphicsDevice instance used for rendering.</param> /// <param name="Position">Camera's initial position.</param> /// <param name="Target">Camera's initial target.</param> /// <param name="Up">Camera's initial up vector.</param> public BasicCamera(GraphicsDevice device, Vector3 Position, Vector3 Target, Vector3 Up) { m_Device = device; AspectRatioMultiplier = 1.0f; NearPlane = 1.0f; FarPlane = 800.0f; m_Position = Position; m_Target = Target; m_Up = Up; m_ViewDirty = true; /** * Assume the projection is full screen, center origin */ ProjectionOrigin = new Vector2( m_Device.Viewport.Width / 2.0f, m_Device.Viewport.Height / 2.0f ); } protected Vector2 m_ProjectionOrigin = Vector2.Zero; /// <summary> /// Gets or sets this BasicCamera's projection origin. /// </summary> public Vector2 ProjectionOrigin { get { return m_ProjectionOrigin; } set { m_ProjectionOrigin = value; m_ProjectionDirty = true; } } protected Matrix m_Projection; protected bool m_ProjectionDirty; public void ProjectionDirty() { m_ProjectionDirty = true; } /// <summary> /// Gets this camera's projection. /// </summary> [Browsable(false)] public Matrix Projection { get { if (m_ProjectionDirty) { CalculateProjection(); m_ProjectionDirty = false; } return m_Projection; } } private float _FOV = (float)Math.PI / 4f; public float FOV { get { return _FOV; } set { _FOV = value; ProjectionDirty(); } } protected virtual void CalculateProjection() { var device = m_Device; var aspect = device.Viewport.AspectRatio * AspectRatioMultiplier; var ratioX = m_ProjectionOrigin.X / device.Viewport.Width; var ratioY = m_ProjectionOrigin.Y / device.Viewport.Height; var projectionX = 0.0f - (1.0f * ratioX); var projectionY = (1.0f * ratioY); m_Projection = Matrix.CreatePerspectiveFieldOfView(FOV, aspect, NearPlane, FarPlane); /*m_Projection = Matrix.CreatePerspectiveOffCenter( projectionX, projectionX + 1.0f, ((projectionY-1.0f) / aspect), (projectionY) / aspect, NearPlane, FarPlane );*/ m_Projection = Matrix.CreateScale(Zoom, Zoom, 1.0f) * m_Projection; } protected virtual void CalculateView() { var translate = Matrix.CreateTranslation(m_Translation); var position = Vector3.Transform(m_Position, translate); var target = Vector3.Transform(m_Target, translate); m_View = Matrix.CreateLookAt(position, target, m_Up); } protected bool m_ViewDirty = false; protected Matrix m_View = Matrix.Identity; [Browsable(false)] public Matrix View { get { if (m_ViewDirty) { m_ViewDirty = false; CalculateView(); } return m_View; } } protected float m_Zoom = 1.0f; /// <summary> /// Gets or sets this BasicCamera's zoom level. /// </summary> public float Zoom { get { return m_Zoom; } set { m_Zoom = value; m_ViewDirty = true; m_ProjectionDirty = true; } } protected Vector3 m_Translation; /// <summary> /// Gets or sets this BasicCamera's translation. /// </summary> public Vector3 Translation { get { return m_Translation; } set { m_Translation = value; m_ViewDirty = true; } } /// <summary> /// Gets or sets this BasicCamera's position. /// </summary> public Vector3 Position { get { return m_Position; } set { m_Position = value; m_ViewDirty = true; } } /// <summary> /// Gets or sets this BasicCamera's target. /// </summary> public Vector3 Target { get { return m_Target; } set { m_Target = value; m_ViewDirty = true; } } /// <summary> /// Gets or sets this BasicCamera's up vector. /// </summary> public Vector3 Up { get { return m_Up; } set { m_Up = value; m_ViewDirty = true; } } public bool DrawCamera = false; public void Draw(GraphicsDevice device) { /* device.RasterizerState.PointSize = 30.0f; device.VertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements); var effect = new BasicEffect(device); effect.World = Matrix.Identity; effect.View = View; effect.Projection = Projection; effect.VertexColorEnabled = true; foreach (var pass in effect.Techniques[0].Passes) { pass.Apply(); var vertex = new VertexPositionColor(Position, Color.Green); var vertexList = new VertexPositionColor[1] { vertex }; device.DrawUserPrimitives(PrimitiveType.PointList, vertexList, 0, 1); vertex.Color = Color.Red; vertex.Position = Target; device.DrawUserPrimitives(PrimitiveType.PointList, vertexList, 0, 1); } * XNA4 no longer has support for point primitives. */ } } }