using System;
using Chernobyl.Collections.Generic.Event;
using Chernobyl.Dependency;
using Chernobyl.Graphics.Drawing;
using Chernobyl.Graphics.Polygon.Buffers;
using Chernobyl.Mathematics.Geometry;
using Chernobyl.Mathematics.Movement;
using Microsoft.Xna.Framework.Graphics;
namespace Chernobyl.Graphics.Xna.Controllers
{
///
/// The XNA implementation of an .
///
public class XnaRender : DrawableTransform, IRender
{
///
/// Constructor.
///
/// The services class whose services will be
/// injected into the render objects
/// The primitive type of the render object.
/// The used by the created
/// object to control drawing.
/// The used by the created
/// to control transformations.
/// The used by the created
/// to control shape related functionality.
public XnaRender(IEventCollection services, Chernobyl.Graphics.Drawing.PrimitiveType primitiveType,
IDrawable drawable, ITransform decoratedTransform, IShape shape)
{
_drawableImplementer = drawable;
_drawableImplementer.DecoratoringDrawable = this;
_decoratedTransform = decoratedTransform;
_shapeImplementer = shape;
PrimitiveType = primitiveType;
DrawMethod = NoOpDraw;
services.Inject(this);
}
///
/// Calls draw on the children objects. Overload to add you own implementation.
///
public override uint Draw()
{
DrawMethod();
return base.Draw();
}
///
/// The method that draws the mesh
///
public Action DrawMethod { get; set; }
///
/// Draws a mesh with indices specified.
///
public void DrawWithIndices()
{
SceneWorldMatrix.Value = WorldMatrix;
VertexBuffer vertexBuffer = Mesh.XnaVertexBuffer;
GraphicsDevice.DrawIndexedPrimitives(XnaPrimitiveType, 0, 0, (int)Mesh.Count, 0, Utility.GetPrimitiveCount(XnaPrimitiveType, Mesh.Count));
}
///
/// Draws a mesh without indices specified.
///
public void DrawWithoutIndices()
{
SceneWorldMatrix.Value = WorldMatrix;
VertexBuffer vertexBuffer = Mesh.XnaVertexBuffer;
GraphicsDevice.DrawPrimitives(XnaPrimitiveType, 0, Utility.GetPrimitiveCount(XnaPrimitiveType, Mesh.Count));
}
///
/// A no-op (no operation) draw method that does nothing. This
/// is the default DrawMethod used by this draw.
///
public void NoOpDraw() {}
///
/// The mesh element buffer used to draw the data.
///
public IXnaMesh Mesh
{
get { return _mesh; }
set
{
_mesh = value;
RevaluateDrawMethod();
}
}
///
/// The index buffer used to draw the data.
///
public IBuffer IndexBuffer
{
get { return _indexBuffer; }
set
{
_indexBuffer = value;
RevaluateDrawMethod();
}
}
///
/// The primitive type being drawn.
///
public Chernobyl.Graphics.Drawing.PrimitiveType PrimitiveType
{
get { return Utility.ToChernobylPrimitiveType(XnaPrimitiveType); }
set { XnaPrimitiveType = Utility.ToXnaPrimitiveType(value); }
}
///
/// The graphics devices used by this draw.
///
[Inject]
public GraphicsDevice GraphicsDevice
{
get { return _graphicsDevice; }
set
{
_graphicsDevice = value;
RevaluateDrawMethod();
}
}
///
/// The world matrix used to set our transformation on.
///
[Inject]
public IWorldMatrixParameter SceneWorldMatrix
{
get { return _sceneWorldMatrix; }
set
{
_sceneWorldMatrix = value;
RevaluateDrawMethod();
}
}
///
/// The largest width of the object in the object's X axis.
///
public float Width
{
get { return _shapeImplementer.Width; }
}
///
/// The largest height of the object in the object's Y axis.
///
public float Height
{
get { return _shapeImplementer.Height; }
}
///
/// The largest depth of the object in the object's Z axis.
///
public float Depth
{
get { return _shapeImplementer.Depth; }
}
///
/// True if this is convex, false if it is concave
/// or has 0 (such as a point). A
/// is convex if for every pair of points within
/// the object, every point on the straight line segment that joins them
/// is also within the object. A concave is the
/// opposite of this.
///
public bool IsConvex
{
get { return _shapeImplementer.IsConvex; }
}
///
/// The amount of space taken up by an object on a flat plane in
/// square metres (m^2).
///
public float Area
{
get { return _shapeImplementer.Area; }
}
///
/// The amount of 3D space this object consumes in cubic metres (m^3).
/// If this object is 2D, then the value of this property is zero.
///
public float Volume
{
get { return _shapeImplementer.Volume; }
}
///
/// The length of the path that surrounds a shape specified in metres (m).
/// In the case of a closed curve such as a circle, this value represents
/// the circumference of the object.
///
public float Perimeter
{
get { return _shapeImplementer.Perimeter; }
}
///
/// The minimum number of coordinates needed to specify each point
/// within this object. For example: a point has 0 dimensions, a
/// line has 1 dimension, a circle or rectangle has 2 dimensions, a
/// cube or sphere has 3 dimensions, and a moving cube or sphere has 4.
///
public uint Dimensions
{
get { return _shapeImplementer.Dimensions; }
}
///
/// The drawable that implements the drawing of this object.
///
protected override IDrawable DrawableImplementer { get { return _drawableImplementer; } }
///
/// The transform that provides this transforms capabilities.
///
protected override ITransform DecoratedTransform { get { return _decoratedTransform; } }
///
/// The that implements the width and height
/// capabilities of this type.
///
protected IShape GeometryImplementer { get { return _shapeImplementer; } }
///
/// Checks the draw method to ensure that is the correct draw method
/// given whether the IndexBuffer and Mesh exist.
///
void RevaluateDrawMethod()
{
if (Mesh != null && GraphicsDevice != null && SceneWorldMatrix != null)
{
if (IndexBuffer != null)
DrawMethod = DrawWithIndices;
else
DrawMethod = DrawWithoutIndices;
}
else
DrawMethod = NoOpDraw;
}
///
/// The XNA primitive type.
///
Microsoft.Xna.Framework.Graphics.PrimitiveType XnaPrimitiveType { get; set; }
///
/// The backing field to .
///
IXnaMesh _mesh;
///
/// The backing field to .
///
IBuffer _indexBuffer;
///
/// The backing field to
///
GraphicsDevice _graphicsDevice;
///
/// The backing field to .
///
IWorldMatrixParameter _sceneWorldMatrix;
///
/// The backing field to .
///
IDrawable _drawableImplementer;
///
/// The backing field to .
///
ITransform _decoratedTransform;
///
/// The backing field to .
///
IShape _shapeImplementer;
}
}