#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2016 Ethan Lee and the MonoGame Team
*
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
#endregion
namespace Microsoft.Xna.Framework.Graphics
{
public class VertexDeclaration : GraphicsResource
{
#region Public Properties
public int VertexStride
{
get;
private set;
}
#endregion
#region Internal Variables
internal VertexElement[] elements;
#endregion
#region Public Constructors
public VertexDeclaration(
params VertexElement[] elements
) : this(GetVertexStride(elements), elements) {
}
public VertexDeclaration(
int vertexStride,
params VertexElement[] elements
) {
if ((elements == null) || (elements.Length == 0))
{
throw new ArgumentNullException("elements", "Elements cannot be empty");
}
this.elements = (VertexElement[]) elements.Clone();
VertexStride = vertexStride;
}
#endregion
#region Public Methods
public VertexElement[] GetVertexElements()
{
return (VertexElement[]) elements.Clone();
}
#endregion
#region Internal Static Methods
///
/// Returns the VertexDeclaration for Type.
///
/// A value type which implements the IVertexType interface.
/// The VertexDeclaration.
///
/// Prefer to use VertexDeclarationCache when the declaration lookup
/// can be performed with a templated type.
///
internal static VertexDeclaration FromType(Type vertexType)
{
if (vertexType == null)
{
throw new ArgumentNullException("vertexType", "Cannot be null");
}
if (!vertexType.IsValueType)
{
throw new ArgumentException("vertexType", "Must be value type");
}
IVertexType type = Activator.CreateInstance(vertexType) as IVertexType;
if (type == null)
{
throw new ArgumentException("vertexData does not inherit IVertexType");
}
VertexDeclaration vertexDeclaration = type.VertexDeclaration;
if (vertexDeclaration == null)
{
throw new ArgumentException("vertexType's VertexDeclaration cannot be null");
}
return vertexDeclaration;
}
#endregion
#region Private Static VertexElement Methods
private static int GetVertexStride(VertexElement[] elements)
{
int max = 0;
for (int i = 0; i < elements.Length; i += 1)
{
int start = elements[i].Offset + GetTypeSize(elements[i].VertexElementFormat);
if (max < start)
{
max = start;
}
}
return max;
}
private static int GetTypeSize(VertexElementFormat elementFormat)
{
switch (elementFormat)
{
case VertexElementFormat.Single:
return 4;
case VertexElementFormat.Vector2:
return 8;
case VertexElementFormat.Vector3:
return 12;
case VertexElementFormat.Vector4:
return 16;
case VertexElementFormat.Color:
return 4;
case VertexElementFormat.Byte4:
return 4;
case VertexElementFormat.Short2:
return 4;
case VertexElementFormat.Short4:
return 8;
case VertexElementFormat.NormalizedShort2:
return 4;
case VertexElementFormat.NormalizedShort4:
return 8;
case VertexElementFormat.HalfVector2:
return 4;
case VertexElementFormat.HalfVector4:
return 8;
}
return 0;
}
#endregion
}
}