using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace BansheeEngine
{
///
/// Primary class for holding geometry. Stores data in the form of a vertex buffers and optionally index buffer,
/// which may be bound to the pipeline for drawing. May contain multiple sub-meshes.
///
public class Mesh : Resource
{
///
/// Constructor for internal use by the runtime.
///
private Mesh()
{ }
///
/// Creates a new mesh with enough space to hold the a number of primitives using the specified layout. All indices
/// will be part of a single sub-mesh.
///
/// Number of vertices in the mesh.
/// Number of indices in the mesh.
/// Determines how should the provided indices be interpreted by the pipeline. Default option
/// is a triangle list, where three indices represent a single triangle.
/// Optimizes performance depending on planned usage of the mesh.
/// Controls how are vertices organized in the vertex buffer and what data they contain.
/// Size of indices, use smaller size for better performance, however be careful not to go over
/// the number of vertices limited by the size.
public Mesh(int numVertices, int numIndices, MeshTopology topology = MeshTopology.TriangleList,
MeshUsage usage = MeshUsage.Default, VertexType vertex = VertexType.Position,
IndexType index = IndexType.Index32)
{
SubMesh[] subMeshes = {new SubMesh(0, numIndices, topology)};
Internal_CreateInstance(this, numVertices, numIndices, subMeshes, usage, vertex, index);
}
///
/// Creates a new mesh with enough space to hold the a number of primitives using the specified layout. Indices can
/// be references by multiple sub-meshes.
///
/// Number of vertices in the mesh.
/// Number of indices in the mesh.
/// Defines how are indices separated into sub-meshes, and how are those sub-meshes rendered.
/// Sub-meshes may be rendered independently.
/// Optimizes performance depending on planned usage of the mesh.
/// Controls how are vertices organized in the vertex buffer and what data they contain.
/// Size of indices, use smaller size for better performance, however be careful not to go over
/// the number of vertices limited by the size.
public Mesh(int numVertices, int numIndices, SubMesh[] subMeshes, MeshUsage usage = MeshUsage.Default,
VertexType vertex = VertexType.Position, IndexType index = IndexType.Index32)
{
Internal_CreateInstance(this, numVertices, numIndices, subMeshes, usage, vertex, index);
}
///
/// Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
/// by the mesh data exactly. Mesh will have no sub-meshes.
///
/// Vertex and index data to initialize the mesh with.
/// Determines how should the provided indices be interpreted by the pipeline. Default option
/// is a triangle list, where three indices represent a single triangle.
/// Optimizes performance depending on planned usage of the mesh.
public Mesh(MeshData data, MeshTopology topology = MeshTopology.TriangleList, MeshUsage usage = MeshUsage.Default)
{
int numIndices = 0;
IntPtr dataPtr = IntPtr.Zero;
if (data != null)
{
numIndices = data.IndexCount;
dataPtr = data.GetCachedPtr();
}
SubMesh[] subMeshes = { new SubMesh(0, numIndices, topology) };
Internal_CreateInstanceMeshData(this, dataPtr, subMeshes, usage);
}
///
/// Creates a new mesh from an existing mesh data. Created mesh will match the vertex and index buffers described
/// by the mesh data exactly. Mesh will have specified the sub-meshes.
///
/// Vertex and index data to initialize the mesh with.
/// Defines how are indices separated into sub-meshes, and how are those sub-meshes rendered.
/// Sub-meshes may be rendered independently.
/// Optimizes performance depending on planned usage of the mesh.
public Mesh(MeshData data, SubMesh[] subMeshes, MeshUsage usage = MeshUsage.Default)
{
IntPtr dataPtr = IntPtr.Zero;
if (data != null)
dataPtr = data.GetCachedPtr();
Internal_CreateInstanceMeshData(this, dataPtr, subMeshes, usage);
}
///
/// Returns the number of sub-meshes contained in the mesh.
///
public int SubMeshCount
{
get { return Internal_GetSubMeshCount(mCachedPtr); }
}
///
/// Returns all sub-meshes contained in the mesh.
///
public SubMesh[] SubMeshes
{
get { return Internal_GetSubMeshes(mCachedPtr); }
}
///
/// Returns local bounds of the geometry contained in the vertex buffers for all sub-meshes.
///
public Bounds Bounds
{
get
{
AABox box;
Sphere sphere;
Internal_GetBounds(mCachedPtr, out box, out sphere);
return new Bounds(box, sphere);
}
}
///
/// Returns the vertex and index data contained in the mesh. Mesh must have been created with a
/// flag.
///
/// Vertex and index data contained in the mesh
public MeshData GetMeshData()
{
return Internal_GetMeshData(mCachedPtr);
}
///
/// Updates the vertex and index data contained in the mesh.
///
/// Vertex and index data. Data must match mesh vertex/index counts, vertex layout and index
/// format.
public void SetMeshData(MeshData data)
{
IntPtr dataPtr = IntPtr.Zero;
if (data != null)
dataPtr = data.GetCachedPtr();
Internal_SetMeshData(mCachedPtr, dataPtr);
}
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_CreateInstance(Mesh instance, int numVertices,
int numIndices, SubMesh[] subMeshes, MeshUsage usage, VertexType vertex, IndexType index);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_CreateInstanceMeshData(Mesh instance, IntPtr data, SubMesh[] subMeshes,
MeshUsage usage);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern SubMesh[] Internal_GetSubMeshes(IntPtr thisPtr);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern int Internal_GetSubMeshCount(IntPtr thisPtr);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_GetBounds(IntPtr thisPtr, out AABox box, out Sphere sphere);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern MeshData Internal_GetMeshData(IntPtr thisPtr);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_SetMeshData(IntPtr thisPtr, IntPtr value);
}
///
/// Data about a sub-mesh range and the type of primitives contained in the range.
///
[StructLayout(LayoutKind.Sequential)]
public struct SubMesh // Note: Must match C++ class SubMesh
{
public SubMesh(int indexOffset, int indexCount, MeshTopology topology = MeshTopology.TriangleList)
{
IndexOffset = indexOffset;
IndexCount = indexCount;
Topology = topology;
}
public int IndexOffset;
public int IndexCount;
public MeshTopology Topology;
}
///
/// Determines how are mesh indices interpreted by the renderer.
///
public enum MeshTopology // Note: Must match C++ class MeshTopology
{
PointList = 1,
LineList = 2,
LineStrip = 3,
TriangleList = 4,
TriangleStrip = 5,
TriangleFan = 6
}
///
/// Planned usage for the mesh that allow various optimizations.
///
public enum MeshUsage // Note: Must match C++ enum MeshUsage
{
///
/// Specify for a mesh that is not often updated from the CPU.
///
Default = 0x1,
///
/// Specify for a mesh that is often updated from the CPU.
///
Dynamic = 0x2,
///
/// All mesh data will also be cached in CPU memory allowing the mesh data to be read.
///
CPUCached = 0x1000
}
}