using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SharpGLTF.Schema2;
using MODELINST = SharpGLTF.Runtime.MonoGameModelInstance;
namespace SharpGLTF.Runtime
{
///
/// Helper class for rendering models.
///
public class ModelDrawingContext
{
#region lifecycle
public ModelDrawingContext(GraphicsDevice graphics)
{
_Device = graphics;
_Device.DepthStencilState = DepthStencilState.Default;
_View = Matrix.Invert(Matrix.Identity);
_Projection = SceneUtils.CreatePerspectiveFieldOfView(_FieldOfView, _Device.Viewport.AspectRatio, _NearPlane);
// _DistanceComparer = MODELINST.GetDistanceComparer(-_View.Translation);
}
#endregion
#region data
private GraphicsDevice _Device;
private readonly Stack<_GraphicsState> _PreserveState = new Stack<_GraphicsState>();
private float _FieldOfView = MathHelper.PiOver4;
private float _NearPlane = 1f;
private Matrix _View, _Projection;
private IComparer _DistanceComparer;
private static readonly HashSet _SceneEffects = new HashSet();
private static readonly List _SceneInstances = new List();
#endregion
#region properties
public float FieldOfView
{
get => _FieldOfView;
set => _FieldOfView = value;
}
public float NearPlane
{
get => _NearPlane;
set => _NearPlane = value;
}
#endregion
#region API
protected void PushState()
{
var state = new _GraphicsState(_Device);
_PreserveState.Push(state);
}
protected void PopState()
{
var state = _PreserveState.Pop();
state.Apply(_Device);
}
public Matrix GetProjectionMatrix()
{
return _Projection;
}
public Matrix GetViewMatrix()
{
return _View;
}
public void SetProjectionMatrix(Matrix projectionMatrix)
{
_Projection = projectionMatrix;
}
public void SetCamera(Matrix cameraMatrix)
{
_View = Matrix.Invert(cameraMatrix);
_Projection = SceneUtils.CreatePerspectiveFieldOfView(_FieldOfView, _Device.Viewport.AspectRatio, _NearPlane);
// _DistanceComparer = MODELINST.GetDistanceComparer(-_View.Translation);
}
#endregion
}
///
/// Preserves all the monogame states that might be
/// modified when rendering a model.
///
readonly struct _GraphicsState
{
public _GraphicsState(GraphicsDevice graphics)
{
_Rasterizer = graphics.RasterizerState;
_Blend = graphics.BlendState;
_Sampler0 = graphics.SamplerStates[0];
_Sampler1 = graphics.SamplerStates[1];
}
private readonly RasterizerState _Rasterizer;
private readonly BlendState _Blend;
private readonly SamplerState _Sampler0;
private readonly SamplerState _Sampler1;
public void Apply(GraphicsDevice graphics)
{
graphics.RasterizerState = _Rasterizer;
graphics.BlendState = _Blend;
graphics.SamplerStates[0] = _Sampler0;
graphics.SamplerStates[1] = _Sampler1;
}
}
}