MonoGame/カメラを作る

提供: MonoBook
移動: 案内検索

カメラクラスを作っておくと捗る。

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
 
namespace Draw3D
{
    public class Camera : GameComponent
    {
        public Camera(Game game) : base(game)
        {
            _aspectRatio = game.GraphicsDevice.Viewport.AspectRatio;
 
            UpdateProjection();
            UpdateView();
 
            this.Enabled = true;
        }
 
        /// <summary>
        /// カメラの位置
        /// </summary>
        public Vector3 Position = new Vector3(0, 10, 10);
 
        /// <summary>
        /// カメラの焦点
        /// </summary>
        public Vector3 Target = Vector3.Zero;
 
        /// <summary>
        /// カメラの向き
        /// </summary>
        /// <value>The direction.</value>
        public Vector3 Direction
        {
            get
            {
                return Vector3.Normalize(this.Position - this.Target);
            }
            set
            {
                var norm = Vector3.Normalize(value);
                this.Target = this.Position + norm;
            }
        }
 
        /// <summary>
        /// カメラの上(傾き)
        /// フライトシミュレーターなどは飛行機が傾けばカメラも傾くアレ。
        /// ラジアンではなく度で指定する。
        /// </summary>
        public float Angle = 0;
 
        /// <summary>
        /// この距離より近いオブジェクトが描画されなくなる。
        /// </summary>
        /// <value>The near plane distance.</value>
        public float NearPlaneDistance { 
            get { return _nearPlaneDistance; } 
            set { _nearPlaneDistance = value; UpdateProjection(); } 
        }
 
        private float _nearPlaneDistance = 0.1f;
 
        /// <summary>
        /// この距離より遠いオブジェクトが描画されなくなる。
        /// </summary>
        /// <value>The far plane distance.</value>
        public float FarPlaneDistance {
            get { return _farPlaneDistance; } 
            set { _farPlaneDistance = value; UpdateProjection(); } 
        }
 
        private float _farPlaneDistance = 10000f;
 
        /// <summary>
        /// カメラの視野角(1〜179)
        /// 肉眼は46度くらいらしい(諸説ある)。
        /// 超広角レンズ、または魚眼レンズ - 最大180度の画角(それよりさらに広いものもある)
        /// 広角レンズ - 一般に 100度から60度
        /// 標準レンズ - 一般に 50度から 25度
        /// 望遠レンズ - 一般に 15度から 10度
        /// 超望遠レンズ - 一般に 8度から 1度
        /// </summary>
        /// <value>The field of view.</value>
        public float FieldOfView { 
            get { return _fieldOfView; } 
            set 
            {
                if (value <= 0)
                {
                    _fieldOfView = 0.01f;
                }
                else if (180 <= value)
                {
                    _fieldOfView = 179.99f;
                }
                else
                {
                    _fieldOfView = value;
                }
                UpdateProjection();
            }
        }
 
        private float _fieldOfView = 46;
 
        /// <summary>
        /// カメラのアスペクト比
        /// </summary>
        /// <value>The aspect ratio.</value>
        public float AspectRatio { 
            get { return _aspectRatio; } 
            set { _aspectRatio = value; UpdateProjection(); }
        }
 
        private float _aspectRatio;
 
        // --------------------------------
 
        public Matrix View { get { return _view; } }
 
        private Matrix _view;
 
        public Matrix Projection { get { return _projection; } }
 
        private Matrix _projection;
 
        public Matrix ViewProjection { get { return _view * _projection; } }
 
 
        private void UpdateProjection()
        {
            //var viewport = this.Game.GraphicsDevice.Viewport;
            //_projection = Matrix.CreateOrthographicOffCenter(
            //    (viewport.Width / -2) * _aspectRatio,
            //    (viewport.Width / +2) * _aspectRatio,
            //    (viewport.Height / -2),
            //    (viewport.Height / +2),
            //    _nearPlaneDistance,
            //    _farPlaneDistance);
 
            var fieldOfViewRadian = MathHelper.ToRadians(_fieldOfView);
 
            _projection = Matrix.CreatePerspectiveFieldOfView(
                fieldOfViewRadian,
                _aspectRatio,
                _nearPlaneDistance,
                _farPlaneDistance);
        }
 
        private void UpdateView()
        {
            var radian = MathHelper.ToRadians(this.Angle);
            var rotate = Matrix.CreateRotationZ(radian);
            var upVector = Vector3.Transform(Vector3.Up, rotate);
            _view = Matrix.CreateLookAt(this.Position, Target, upVector);
        }
 
        public override void Update(GameTime gameTime)
        {
            if (this.Enabled)
            {
                this.UpdateView();
            }
            base.Update(gameTime);
        }
    }
}