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 } }