Replaced the old VS templates with ones that offer more flexiblity. Started replacing the Content Project for the samples with our custom project type. Inlcuded a basic not yet working AssimpImporter.
159 lines
7.3 KiB
C#
159 lines
7.3 KiB
C#
#region Using Statements
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Collections;
|
|
using System.Runtime.InteropServices;
|
|
using ANX.Framework.Content.Pipeline.Helpers;
|
|
|
|
#endregion
|
|
|
|
// This file is part of the ANX.Framework created by the
|
|
// "ANX.Framework developer group" and released under the Ms-PL license.
|
|
// For details see: http://anxframework.codeplex.com/license
|
|
|
|
namespace ANX.Framework.Content.Pipeline.Processors
|
|
{
|
|
public class VertexBufferContent : ContentItem
|
|
{
|
|
public VertexBufferContent()
|
|
: this(0)
|
|
{
|
|
|
|
}
|
|
|
|
public VertexBufferContent(int size)
|
|
{
|
|
VertexData = new byte[size];
|
|
}
|
|
|
|
public byte[] VertexData
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public VertexDeclarationContent VertexDeclaration
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the size of the specified type, in bytes.
|
|
/// </summary>
|
|
/// <param name="type"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="System.ArgumentNullException"></exception>
|
|
/// <exception cref="System.NotSupportedException"></exception>
|
|
public static int SizeOf(Type type)
|
|
{
|
|
if (type == null)
|
|
throw new ArgumentNullException("type");
|
|
|
|
if (!type.IsValueType)
|
|
throw new NotSupportedException("The type of a value that should be used for a VertexBuffer should be a struct.");
|
|
|
|
return Marshal.SizeOf(type);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes additional data into the vertex buffer. Writing begins at the specified byte offset, and each value is spaced according to the specified stride value (in bytes).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method automatically grows the vertex buffer if an attempt is made to write past the buffer end. Write throws NotSupportedException
|
|
/// if the specified data type cannot be packed into a vertex buffer. For example, if data is not a valid value type.
|
|
///
|
|
/// Use this method to interleave vertex data channels into a single buffer. This can be done by passing the total vertex size as the stride and suitable smaller offsets for each channel.
|
|
/// You can also concatenate entire vertex buffers by passing the length of the vertex as the offset, 1 as the stride, and the vertex data as the data parameter.
|
|
/// </remarks>
|
|
/// <typeparam name="T">Type being written.</typeparam>
|
|
/// <param name="offset">Offset to begin writing at.</param>
|
|
/// <param name="stride">Stride of the data being written (in bytes).</param>
|
|
/// <param name="data">Enumerated collection of data.</param>
|
|
/// <exception cref="System.ArgumentNullException"></exception>
|
|
/// <exception cref="System.ArgumentOutOfRangeException"></exception>
|
|
/// <exception cref="System.NotSupportedException"></exception>
|
|
public void Write<T>(int offset, int stride, IEnumerable<T> data) where T : struct
|
|
{
|
|
this.Write(offset, stride, typeof(T), data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes additional data into the vertex buffer. Writing begins at the specified byte offset, and each value is spaced according to the specified stride value (in bytes).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method automatically grows the vertex buffer if an attempt is made to write past the buffer end. Write throws NotSupportedException
|
|
/// if the specified data type cannot be packed into a vertex buffer. For example, if data is not a valid value type.
|
|
///
|
|
/// Use this method to interleave vertex data channels into a single buffer. This can be done by passing the total vertex size as the stride and suitable smaller offsets for each channel.
|
|
/// You can also concatenate entire vertex buffers by passing the length of the vertex as the offset, 1 as the stride, and the vertex data as the data parameter.
|
|
/// </remarks>
|
|
/// <param name="offset"></param>
|
|
/// <param name="stride"></param>
|
|
/// <param name="dataType"></param>
|
|
/// <param name="data"></param>
|
|
/// <exception cref="System.ArgumentNullException"></exception>
|
|
/// <exception cref="System.ArgumentException"></exception>
|
|
/// <exception cref="System.ArgumentOutOfRangeException"></exception>
|
|
/// <exception cref="System.NotSupportedException"></exception>
|
|
public void Write(int offset, int stride, Type dataType, IEnumerable data)
|
|
{
|
|
if (offset < 0)
|
|
throw new ArgumentOutOfRangeException("offset");
|
|
|
|
if (dataType == null)
|
|
throw new ArgumentNullException("dataType");
|
|
|
|
//TODO: support the second documented use case.
|
|
int elementSize = SizeOf(dataType);
|
|
//Make sure we don't intercopy the data if we write it. Having a bigger stride is no problem, in that case we write what we can and then skip all unused bytes to get to the next stride.
|
|
if (stride < elementSize)
|
|
throw new ArgumentOutOfRangeException("stride");
|
|
|
|
if (data == null)
|
|
throw new ArgumentNullException("data");
|
|
|
|
List<object> dataList = new List<object>();
|
|
foreach (var obj in data)
|
|
{
|
|
//obj should not be able to be null, because we tested with SizeOf if it is a ValueType.
|
|
if (!dataType.IsAssignableFrom(obj.GetType()))
|
|
throw new ArgumentException(string.Format("data contains elements that are not compatible with \"{0}\"", dataType.Name));
|
|
|
|
dataList.Add(obj);
|
|
}
|
|
|
|
//regrow the array if the data would write over the boundaries.
|
|
int dataLength = dataList.Count * stride;
|
|
int vertexOffset = offset / stride * stride;
|
|
if (vertexOffset + dataLength > VertexData.Length)
|
|
{
|
|
byte[] newVertexData = new byte[vertexOffset + dataLength];
|
|
Array.Copy(VertexData, newVertexData, VertexData.Length);
|
|
|
|
this.VertexData = newVertexData;
|
|
}
|
|
|
|
//Copy the data over, the content of dataList is guaranteed to be a value type by the SizeOf check earlier.
|
|
for (int i = 0; i < dataList.Count; i++)
|
|
{
|
|
//We have to copy every element separately to support the first documented use case where someone passed a stride that is much bigger than the real data to write only data into the vertex buffer for
|
|
//a single vertex channel, even though the data in the vertex buffer must be arranged per vertex and not per vertex channel.
|
|
var dataHandle = GCHandle.Alloc(dataList[i], GCHandleType.Pinned);
|
|
try
|
|
{
|
|
Marshal.Copy(dataHandle.AddrOfPinnedObject(), VertexData, offset + i * stride, elementSize);
|
|
}
|
|
finally
|
|
{
|
|
dataHandle.Free();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|