/// <summary> /// Creates a plane as a submesh of the given mesh /// </summary> private static void _createPlane( Mesh mesh ) { SubMesh sub = mesh.CreateSubMesh(); float[] vertices = new float[ 32 ] { -100, -100, 0, // pos 0,0,1, // normal 0,1, // texcoord 100, -100, 0, 0,0,1, 1,1, 100, 100, 0, 0,0,1, 1,0, -100, 100, 0 , 0,0,1, 0,0 }; mesh.SharedVertexData = new VertexData(); mesh.SharedVertexData.vertexCount = 4; VertexDeclaration decl = mesh.SharedVertexData.vertexDeclaration; VertexBufferBinding binding = mesh.SharedVertexData.vertexBufferBinding; int offset = 0; decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 ); offset += VertexElement.GetTypeSize( VertexElementType.Float2 ); HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl, 4, BufferUsage.StaticWriteOnly ); binding.SetBinding( 0, vbuf ); vbuf.WriteData( 0, vbuf.Size, vertices, true ); sub.useSharedVertices = true; HardwareIndexBuffer ibuf = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, 6, BufferUsage.StaticWriteOnly ); short[] faces = new short[ 6 ] { 0, 1, 2, 0, 2, 3 }; sub.IndexData.indexBuffer = ibuf; sub.IndexData.indexCount = 6; sub.IndexData.indexStart = 0; ibuf.WriteData( 0, ibuf.Size, faces, true ); mesh.BoundingBox = new AxisAlignedBox( new Vector3( -100, -100, 0 ), new Vector3( 100, 100, 0 ) ); mesh.BoundingSphereRadius = Utility.Sqrt( 100 * 100 + 100 * 100 ); }
private void _loadManual( Mesh mesh, MeshBuildParams mbp ) { SubMesh subMesh = mesh.CreateSubMesh(); // Set up vertex data // Use a single shared buffer mesh.SharedVertexData = new VertexData(); VertexData vertexData = mesh.SharedVertexData; // Set up Vertex Declaration VertexDeclaration decl = vertexData.vertexDeclaration; int currOffset = 0; // add position data // We always need positions decl.AddElement( 0, currOffset, VertexElementType.Float3, VertexElementSemantic.Position ); currOffset += VertexElement.GetTypeSize( VertexElementType.Float3 ); // normals are optional if ( mbp.Normals ) { decl.AddElement( 0, currOffset, VertexElementType.Float3, VertexElementSemantic.Normal ); currOffset += VertexElement.GetTypeSize( VertexElementType.Float3 ); } // add texture coords for ( ushort i = 0; i < mbp.TexCoordSetCount; i++ ) { decl.AddElement( 0, currOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, i ); currOffset += VertexElement.GetTypeSize( VertexElementType.Float2 ); } vertexData.vertexCount = ( mbp.XSegments + 1 ) * ( mbp.YSegments + 1 ); // create a new vertex buffer (based on current API) HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl.Clone( 0 ), vertexData.vertexCount, mbp.VertexBufferUsage, mbp.VertexShadowBuffer ); // get a reference to the vertex buffer binding VertexBufferBinding binding = vertexData.vertexBufferBinding; // bind the first vertex buffer binding.SetBinding( 0, vbuf ); // transform the plane based on its plane def Matrix4 translate = Matrix4.Identity; Matrix4 transform = Matrix4.Zero; Matrix4 rotation = Matrix4.Identity; Matrix3 rot3x3 = Matrix3.Zero; Vector3 xAxis, yAxis, zAxis; zAxis = mbp.Plane.Normal; zAxis.Normalize(); yAxis = mbp.UpVector; yAxis.Normalize(); xAxis = yAxis.Cross( zAxis ); if ( xAxis.Length == 0 ) { throw new AxiomException( "The up vector for a plane cannot be parallel to the planes normal." ); } rot3x3.FromAxes( xAxis, yAxis, zAxis ); rotation = rot3x3; // set up transform from origin translate.Translation = mbp.Plane.Normal * -mbp.Plane.D; transform = translate * rotation; float xSpace = mbp.Width / mbp.XSegments; float ySpace = mbp.Height / mbp.YSegments; float halfWidth = mbp.Width / 2; float halfHeight = mbp.Height / 2; float xTexCoord = ( 1.0f * mbp.XTile ) / mbp.XSegments; float yTexCoord = ( 1.0f * mbp.YTile ) / mbp.YSegments; Vector3 vec = Vector3.Zero; Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; float maxSquaredLength = 0; bool firstTime = true; // generate vertex data switch ( mbp.Type ) { case MeshBuildType.Plane: _generatePlaneVertexData( vbuf, mbp.YSegments, mbp.XSegments, xSpace, halfWidth, ySpace, halfHeight, transform, firstTime, mbp.Normals, rotation, mbp.TexCoordSetCount, xTexCoord, yTexCoord, subMesh, ref min, ref max, ref maxSquaredLength ); break; case MeshBuildType.CurvedPlane: _generateCurvedPlaneVertexData( vbuf, mbp.YSegments, mbp.XSegments, xSpace, halfWidth, ySpace, halfHeight, transform, firstTime, mbp.Normals, rotation, mbp.Curvature, mbp.TexCoordSetCount, xTexCoord, yTexCoord, subMesh, ref min, ref max, ref maxSquaredLength ); break; case MeshBuildType.CurvedIllusionPlane: _generateCurvedIllusionPlaneVertexData( vbuf, mbp.YSegments, mbp.XSegments, xSpace, halfWidth, ySpace, halfHeight, transform, firstTime, mbp.Normals, mbp.Orientation, mbp.Curvature, xTexCoord, yTexCoord, mbp.TexCoordSetCount, ref min, ref max, ref maxSquaredLength ); break; default: throw new Exception( "" ); } // generate face list _tesselate2DMesh( subMesh, mbp.XSegments + 1, mbp.YSegments + 1, false, mbp.IndexBufferUsage, mbp.IndexShadowBuffer ); // generate bounds for the mesh mesh.BoundingBox = new AxisAlignedBox( min, max ); mesh.BoundingSphereRadius = Utility.Sqrt( maxSquaredLength ); }
public static Mesh CopyMesh(Mesh mesh) { Mesh newMesh = new Mesh(mesh.Name); if (mesh.Skeleton != null) newMesh.NotifySkeleton(mesh.Skeleton); newMesh.SetVertexBufferPolicy(mesh.VertexBufferUsage, mesh.UseVertexShadowBuffer); newMesh.SetIndexBufferPolicy(mesh.IndexBufferUsage, mesh.UseIndexShadowBuffer); // this sets bounding radius as well newMesh.BoundingBox = mesh.BoundingBox; MeshUtility meshUtility = new MeshUtility(); for (int i = 0; i < mesh.SubMeshCount; ++i) meshUtility.AddSubmeshData(mesh.GetSubMesh(i)); // This should be done after we finish with the lod stuff newMesh.AutoBuildEdgeLists = true; newMesh.BuildEdgeList(); foreach (AttachmentPoint ap in mesh.AttachmentPoints) newMesh.AttachmentPoints.Add(new AttachmentPoint(ap)); for (int i = 0; i < mesh.SubMeshCount; ++i) { SubMesh srcSubMesh = mesh.GetSubMesh(i); SubMesh dstSubMesh = newMesh.CreateSubMesh(srcSubMesh.Name); CopySubMesh(dstSubMesh, srcSubMesh, meshUtility.subMeshDataMap[srcSubMesh.Name]); } if (mesh.SharedVertexData != null) { newMesh.SharedVertexData = new VertexData(); CopyVertexData(newMesh.SharedVertexData, mesh.SharedVertexData, meshUtility.sharedSubMeshData.VertexIdMap); CopyBoneAssignments(newMesh, mesh, meshUtility.sharedSubMeshData.VertexIdMap); } // newMesh.CompileBoneAssignments(); return newMesh; }
/// <summary> /// /// </summary> private void PrepareClonedMesh() { // create a new mesh based on the original, only with different BufferUsage flags (inside PrepareVertexData) clonedMesh = MeshManager.Instance.CreateManual(MESH_NAME); clonedMesh.BoundingBox = (AxisAlignedBox)originalMesh.BoundingBox.Clone(); clonedMesh.BoundingSphereRadius = originalMesh.BoundingSphereRadius; // clone the actual data clonedMesh.SharedVertexData = PrepareVertexData(originalMesh.SharedVertexData); // clone each sub mesh for(int i = 0; i < originalMesh.SubMeshCount; i++) { SubMesh orgSub = originalMesh.GetSubMesh(i); SubMesh newSub = clonedMesh.CreateSubMesh(string.Format("ClonedSubMesh#{0}", i)); if(orgSub.IsMaterialInitialized) { newSub.MaterialName = orgSub.MaterialName; } // prepare new vertex data newSub.useSharedVertices = orgSub.useSharedVertices; newSub.vertexData = PrepareVertexData(orgSub.vertexData); // use existing index buffer as is since it wont be modified anyway newSub.indexData.indexBuffer = orgSub.indexData.indexBuffer; newSub.indexData.indexStart = orgSub.indexData.indexStart; newSub.indexData.indexCount = orgSub.indexData.indexCount; } }
public WaterMesh( String meshName, float planeSize, int cmplx ) { // najak R-F // Assign Fields to the Initializer values this.meshName = meshName; this.size = planeSize; this.cmplx = cmplx; // Number of Rows/Columns in the Water Grid representation cmplxAdj = (float)System.Math.Pow( ( cmplx / 64f ), 1.4f ) * 2; numFaces = 2 * (int)System.Math.Pow( cmplx, 2 ); // Each square is split into 2 triangles. numVertices = (int)System.Math.Pow( ( cmplx + 1 ), 2 ); // Vertex grid is (Complexity+1) squared // Allocate and initialize space for calculated Normals vNorms = new Vector3[ cmplx + 1, cmplx + 1 ]; // vertex Normals for each grid point fNorms = new Vector3[ cmplx, cmplx, 2 ]; // face Normals for each triangle // Create mesh and submesh to represent the Water mesh = (Mesh)MeshManager.Instance.CreateManual( meshName, ResourceGroupManager.DefaultResourceGroupName, null ); subMesh = mesh.CreateSubMesh(); subMesh.useSharedVertices = false; // Construct metadata to describe the buffers associated with the water submesh subMesh.vertexData = new VertexData(); subMesh.vertexData.vertexStart = 0; subMesh.vertexData.vertexCount = numVertices; // Define local variables to point to the VertexData Properties VertexDeclaration vdecl = subMesh.vertexData.vertexDeclaration; // najak: seems like metadata VertexBufferBinding vbind = subMesh.vertexData.vertexBufferBinding; // najak: pointer to actual buffer //najak: Set metadata to describe the three vertex buffers that will be accessed. vdecl.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position ); vdecl.AddElement( 1, 0, VertexElementType.Float3, VertexElementSemantic.Normal ); vdecl.AddElement( 2, 0, VertexElementType.Float2, VertexElementSemantic.TexCoords ); // Prepare buffer for positions - todo: first attempt, slow // Create the Position Vertex Buffer and Bind it index 0 - Write Only posVBuf = HwBufMgr.CreateVertexBuffer( vdecl.Clone(0), numVertices, BufferUsage.DynamicWriteOnly ); vbind.SetBinding( 0, posVBuf ); // Prepare buffer for normals - write only // Create the Normals Buffer and Bind it to index 1 - Write only normVBuf = HwBufMgr.CreateVertexBuffer( vdecl.Clone(1), numVertices, BufferUsage.DynamicWriteOnly ); vbind.SetBinding( 1, normVBuf ); // Prepare Texture Coordinates buffer (static, written only once) // Creates a 2D buffer of 2D coordinates: (Complexity X Complexity), pairs. // Each pair indicates the normalized coordinates of the texture to map to. // (0,1.00), (0.02, 1.00), (0.04, 1.00), ... (1.00,1.00) // (0,0.98), (0.02, 0.98), (0.04, 1.00), ... (1.00,0.98) // ... // (0,0.00), (0.02, 0.00), (0.04, 0.00), ... (1.00,0.00) // This construct is simple and is used to calculate the Texture map. // Todo: Write directly to the buffer, when Axiom supports this in safe manner float[ , , ] tcBufDat = new float[ cmplx + 1, cmplx + 1, 2 ]; for ( int i = 0; i <= cmplx; i++ ) { // 2D column iterator for texture map for ( int j = 0; j <= cmplx; j++ ) { // 2D row iterator for texture map // Define the normalized(0..1) X/Y-coordinates for this element of the 2D grid tcBufDat[ i, j, 0 ] = (float)i / cmplx; tcBufDat[ i, j, 1 ] = 1.0f - ( (float)j / ( cmplx ) ); } } // Now Create the actual hardware buffer to contain the Texture Coordinate 2d map. // and Bind it to buffer index 2 tcVBuf = HwBufMgr.CreateVertexBuffer( vdecl.Clone(2), numVertices, BufferUsage.StaticWriteOnly ); tcVBuf.WriteData( 0, tcVBuf.Size, tcBufDat, true ); vbind.SetBinding( 2, tcVBuf ); // Create a Graphics Buffer on non-shared vertex indices (3 points for each triangle). // Since the water grid consist of [Complexity x Complexity] squares, each square is // split into 2 right triangles 45-90-45. That is how the water mesh is constructed. // Therefore the number of faces = 2 * Complexity * Complexity ushort[ , , ] idxBuf = new ushort[ cmplx, cmplx, 6 ]; for ( int i = 0; i < cmplx; i++ ) { // iterate the rows for ( int j = 0; j < cmplx; j++ ) { // iterate the columns // Define 4 corners of each grid ushort p0 = (ushort)( i * ( cmplx + 1 ) + j ); // top left point on square ushort p1 = (ushort)( i * ( cmplx + 1 ) + j + 1 ); // top right ushort p2 = (ushort)( ( i + 1 ) * ( cmplx + 1 ) + j ); // bottom left ushort p3 = (ushort)( ( i + 1 ) * ( cmplx + 1 ) + j + 1 ); // bottom right // Split Square Grid element into 2 adjacent triangles. idxBuf[ i, j, 0 ] = p2; idxBuf[ i, j, 1 ] = p1; idxBuf[ i, j, 2 ] = p0; // top-left triangle idxBuf[ i, j, 3 ] = p2; idxBuf[ i, j, 4 ] = p3; idxBuf[ i, j, 5 ] = p1; // bottom-right triangle } } // Copy Index Buffer to the Hardware Index Buffer HardwareIndexBuffer hdwrIdxBuf = HwBufMgr.CreateIndexBuffer( IndexType.Size16, 3 * numFaces, BufferUsage.StaticWriteOnly, true ); hdwrIdxBuf.WriteData( 0, numFaces * 3 * 2, idxBuf, true ); // Set index buffer for this submesh subMesh.indexData.indexBuffer = hdwrIdxBuf; subMesh.indexData.indexStart = 0; subMesh.indexData.indexCount = 3 * numFaces; //Prepare Vertex Position Buffers (Note: make 3, since each frame is function of previous two) vBufs = new Vector3[ 3 ][ , ]; for ( int b = 0; b < 3; b++ ) { vBufs[ b ] = new Vector3[ cmplx + 1, cmplx + 1 ]; for ( int y = 0; y <= cmplx; y++ ) { for ( int x = 0; x <= cmplx; x++ ) { vBufs[ b ][ y, x ].x = (float)( x ) / (float)( cmplx ) * (float)size; vBufs[ b ][ y, x ].y = 0; vBufs[ b ][ y, x ].z = (float)( y ) / (float)( cmplx ) * (float)size; } } } curBufNum = 0; vBuf = vBufs[ curBufNum ]; posVBuf.WriteData( 0, posVBuf.Size, vBufs[ 0 ], true ); AxisAlignedBox meshBounds = new AxisAlignedBox( new Vector3( 0, 0, 0 ), new Vector3( size, 0, size ) ); mesh.BoundingBox = meshBounds; // mesh->_setBounds(meshBounds); // najak: can't find _setBounds() mesh.Load(); mesh.Touch(); } // end WaterMesh Constructor
private static void _createSphere( Mesh mesh ) { // sphere creation code taken from the DeferredShading sample, originally from the [Ogre] wiki var pSphereVertex = mesh.CreateSubMesh(); const int NUM_SEGMENTS = 16; const int NUM_RINGS = 16; const float SPHERE_RADIUS = 50.0f; mesh.SharedVertexData = new VertexData(); var vertexData = mesh.SharedVertexData; // define the vertex format var vertexDecl = vertexData.vertexDeclaration; var offset = 0; // positions vertexDecl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); // normals vertexDecl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); // two dimensional texture coordinates vertexDecl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 ); offset += VertexElement.GetTypeSize( VertexElementType.Float2 ); // allocate the vertex buffer vertexData.vertexCount = ( NUM_RINGS + 1 )*( NUM_SEGMENTS + 1 ); var vBuf = HardwareBufferManager.Instance.CreateVertexBuffer( vertexDecl.Clone( 0 ), vertexData.vertexCount, BufferUsage.StaticWriteOnly, false ); var binding = vertexData.vertexBufferBinding; binding.SetBinding( 0, vBuf ); // allocate index buffer pSphereVertex.IndexData.indexCount = 6*NUM_RINGS*( NUM_SEGMENTS + 1 ); pSphereVertex.IndexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, pSphereVertex.IndexData. indexCount, BufferUsage.StaticWriteOnly, false ); var iBuf = pSphereVertex.IndexData.indexBuffer; #if !AXIOM_SAFE_ONLY unsafe #endif { var iVertex = 0; var pVertex = vBuf.Lock( BufferLocking.Discard ).ToFloatPointer(); var iIndices = 0; var pIndices = iBuf.Lock( BufferLocking.Discard ).ToUShortPointer(); float fDeltaRingAngle = ( Utility.PI/NUM_RINGS ); float fDeltaSegAngle = ( 2*Utility.PI/NUM_SEGMENTS ); ushort wVerticeIndex = 0; // Generate the group of rings for the sphere for ( var ring = 0; ring <= NUM_RINGS; ring++ ) { float r0 = SPHERE_RADIUS*Utility.Sin( ring*fDeltaRingAngle ); float y0 = SPHERE_RADIUS*Utility.Cos( ring*fDeltaRingAngle ); // Generate the group of segments for the current ring for ( var seg = 0; seg <= NUM_SEGMENTS; seg++ ) { float x0 = r0*Utility.Sin( seg*fDeltaSegAngle ); float z0 = r0*Utility.Cos( seg*fDeltaSegAngle ); // Add one vertex to the strip which makes up the sphere pVertex[ iVertex++ ] = x0; pVertex[ iVertex++ ] = y0; pVertex[ iVertex++ ] = z0; var vNormal = new Vector3( x0, y0, z0 ).ToNormalized(); pVertex[ iVertex++ ] = vNormal.x; pVertex[ iVertex++ ] = vNormal.y; pVertex[ iVertex++ ] = vNormal.z; pVertex[ iVertex++ ] = (float)seg/(float)NUM_SEGMENTS; pVertex[ iVertex++ ] = (float)ring/(float)NUM_RINGS; if ( ring != NUM_RINGS ) { // each vertex (except the last) has six indicies pointing to it pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + NUM_SEGMENTS + 1 ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + NUM_SEGMENTS ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + NUM_SEGMENTS + 1 ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex + 1 ); pIndices[ iIndices++ ] = (ushort)( wVerticeIndex ); wVerticeIndex++; } } ; // end for seg } // end for ring } // Unlock vBuf.Unlock(); iBuf.Unlock(); // Generate face list pSphereVertex.useSharedVertices = true; // the original code was missing this line: mesh.BoundingBox = new AxisAlignedBox( new Vector3( -SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS ), new Vector3( SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS ) ); mesh.BoundingSphereRadius = SPHERE_RADIUS; }
private static void _createCube( Mesh mesh ) { var sub = mesh.CreateSubMesh(); const int NUM_VERTICES = 4*6; // 4 vertices per side * 6 sides const int NUM_ENTRIES_PER_VERTEX = 8; const int NUM_VERTEX_ENTRIES = NUM_VERTICES*NUM_ENTRIES_PER_VERTEX; const int NUM_INDICES = 3*2*6; // 3 indices per face * 2 faces per side * 6 sides const float CUBE_SIZE = 100.0f; const float CUBE_HALF_SIZE = CUBE_SIZE/2.0f; // Create 4 vertices per side instead of 6 that are shared for the whole cube. // The reason for this is with only 6 vertices the normals will look bad // since each vertex can "point" in a different direction depending on the face it is included in. var vertices = new float[NUM_VERTEX_ENTRIES] { // front side -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, // pos 0, 0, 1, // normal 0, 1, // texcoord CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 0, 1, 1, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 0, 1, 1, 0, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 0, 1, 0, 0, // back side CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 0, 1, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 1, 1, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 1, 0, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 0, -1, 0, 0, // left side -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -1, 0, 0, 0, 1, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -1, 0, 0, 1, 1, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -1, 0, 0, 1, 0, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -1, 0, 0, 0, 0, // right side CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 1, 0, 0, 0, 1, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 1, 0, 0, 1, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 1, 0, 0, 1, 0, CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 1, 0, 0, 0, 0, // up side -CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 1, 0, 0, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, 1, 0, 1, 1, CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 1, 0, 1, 0, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, 1, 0, 0, 0, // down side -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, -1, 0, 0, 1, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, 0, -1, 0, 1, 1, CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, -1, 0, 1, 0, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE, 0, -1, 0, 0, 0 }; mesh.SharedVertexData = new VertexData(); mesh.SharedVertexData.vertexCount = NUM_VERTICES; var decl = mesh.SharedVertexData.vertexDeclaration; var bind = mesh.SharedVertexData.vertexBufferBinding; var offset = 0; decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ); offset += VertexElement.GetTypeSize( VertexElementType.Float3 ); decl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 ); offset += VertexElement.GetTypeSize( VertexElementType.Float2 ); var vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( decl, NUM_VERTICES, BufferUsage.StaticWriteOnly ); bind.SetBinding( 0, vbuf ); vbuf.WriteData( 0, vbuf.Size, vertices, true ); sub.useSharedVertices = true; var ibuf = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, NUM_INDICES, BufferUsage.StaticWriteOnly ); var faces = new short[NUM_INDICES] { // front 0, 1, 2, 0, 2, 3, // back 4, 5, 6, 4, 6, 7, // left 8, 9, 10, 8, 10, 11, // right 12, 13, 14, 12, 14, 15, // up 16, 17, 18, 16, 18, 19, // down 20, 21, 22, 20, 22, 23 }; sub.IndexData.indexBuffer = ibuf; sub.IndexData.indexCount = NUM_INDICES; sub.IndexData.indexStart = 0; ibuf.WriteData( 0, ibuf.Size, faces, true ); mesh.BoundingBox = new AxisAlignedBox( new Vector3( -CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE ), new Vector3( CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE ) ); mesh.BoundingSphereRadius = CUBE_HALF_SIZE; }