using System.Collections.Specialized; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace MonoGame.Extended.Graphics.Effects { /// /// An that uses the standard chain of matrix transformations to represent a 3D object on a 2D /// monitor. /// /// /// public abstract class MatrixChainEffect : Effect, IMatrixChainEffect { /// /// The bitmask for use with indicating wether , , or has changed in the last frame. /// protected static int DirtyWorldViewProjectionBitMask = BitVector32.CreateMask(); /// /// The bitmask for use with indicating wether to use a default projection matrix or a custom projection matrix. /// protected static int UseDefaultProjectionBitMask = BitVector32.CreateMask(DirtyWorldViewProjectionBitMask); /// /// The dirty flags associated with this . /// protected BitVector32 Flags; private Matrix _projection = Matrix.Identity; private Matrix _view = Matrix.Identity; private Matrix _world = Matrix.Identity; private EffectParameter _matrixParameter; /// /// Gets or sets the model-to-world . /// /// /// The model-to-world . /// public Matrix World { get { return _world; } set { SetWorld(ref value); } } /// /// Gets or sets the world-to-view . /// /// /// The world-to-view . /// public Matrix View { get { return _view; } set { SetView(ref value); } } /// /// Gets or sets the view-to-projection . /// /// /// The view-to-projection . /// public Matrix Projection { get { return _projection; } set { SetProjection(ref value); } } /// /// Initializes a new instance of the class. /// /// The graphics device. /// The effect code. protected MatrixChainEffect(GraphicsDevice graphicsDevice, byte[] byteCode) : base(graphicsDevice, byteCode) { Initialize(); } /// /// Initializes a new instance of the class. /// /// The clone source. protected MatrixChainEffect(Effect cloneSource) : base(cloneSource) { Initialize(); } private void Initialize() { Flags[UseDefaultProjectionBitMask] = true; _matrixParameter = Parameters["WorldViewProjection"]; } /// /// Sets the model-to-world . /// /// The model-to-world . public void SetWorld(ref Matrix world) { _world = world; Flags[DirtyWorldViewProjectionBitMask] = true; } /// /// Sets the world-to-view . /// /// The world-to-view . public void SetView(ref Matrix view) { _view = view; Flags[DirtyWorldViewProjectionBitMask] = true; } /// /// Sets the view-to-projection . /// /// The view-to-projection . public void SetProjection(ref Matrix projection) { _projection = projection; Flags[DirtyWorldViewProjectionBitMask] = true; Flags[UseDefaultProjectionBitMask] = false; } /// /// Computes derived parameter values immediately before applying the effect. /// protected override void OnApply() { base.OnApply(); // ReSharper disable once InvertIf if (Flags[DirtyWorldViewProjectionBitMask] || Flags[UseDefaultProjectionBitMask]) { if (Flags[UseDefaultProjectionBitMask]) { var viewport = GraphicsDevice.Viewport; _projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, -1); } Matrix worldViewProjection; Matrix.Multiply(ref _world, ref _view, out worldViewProjection); Matrix.Multiply(ref worldViewProjection, ref _projection, out worldViewProjection); _matrixParameter.SetValue(worldViewProjection); Flags[DirtyWorldViewProjectionBitMask] = false; } } } }