How to: Create a Mesh

You can create a mesh in four basic ways:

  • By loading the mesh data from a file.

  • By cloning or optimizing an existing mesh.

  • By using a shape creation function and specifying the size and the number of triangles that will be used to create the shape.

  • By using the Mesh constructor.


Managed Direct3D mobile applications require Windows Mobile version 5.0 software for Pocket PCs and Smartphones. See External Resources for the .NET Compact Framework for information about Windows Mobile software and SDKs.

To create a mesh from a file

  • Load the mesh data from a file, and then fill a mesh with the data. The .NET Compact Framework does not directly support loading a mesh from a file, but the Direct3D Mobile Meshes Sample defines a class to load a mesh.

To create a mesh from an existing mesh

  • Use the Optimize method to create a new mesh with optimized data.


    Use the OptimizeInPlace method to optimize the current mesh.

    The primary use for cloning is to convert the mesh from floating-point to fixed-point format. The primary use for optimizing is to create a mesh that is faster to draw. Mesh optimization rearranges the triangles in the mesh so that drawing calls on the mesh perform faster. Mesh optimization also generates an attribute table, which is used to identify areas of the mesh that need to be drawn with different textures, render states, and materials.

To create a mesh by using a shape-creation function

  • Use one of the following static methods of the Mesh class to create a mesh with position and normals specified in floating-point math:

To create a mesh by using the Mesh constructor

  1. Call the Mesh constructor with the desired arguments.

  2. Set the index buffer, vertex buffer, and attribute table data. The data in this case is often generated at run time. The following example shows the steps to create a mesh in this manner.

The following code example creates a heightfield mesh on the x-y plane with the z-coordinate representing the vertical dimension. The particular mesh created runs from (0, 0) to (1, 1) and has a height specified by the GetHeight method. This mesh is also textured with a single texture over the entire mesh. The tessellation parameter, defined by the example, is used to control how many points along the edge of the mesh are used.

class Form1
        // In this example, initialize the Mesh object 
        // with 4 tessellations 

    private void InitializeMesh(int tessellation)
        Mesh mesh1 = CreateHeightfieldMesh(tessellation);

    private float GetHeight(float x, float y)
        return 0;
        //TODO: fill in this function

    private Mesh CreateHeightfieldMesh(int tessellation)
        Mesh mesh;

        Device device = null; // TODO: initialize this 

        short[] arrayIndices = new short[(tessellation - 1) * (tessellation - 1) * 6];
        CustomVertex.PositionTextured[] arrayVertices =
                new CustomVertex.PositionTextured[tessellation * tessellation];
        AttributeRange attributeRange = new AttributeRange();

        // Create mesh with desired vertex format and desired size
        mesh = new Mesh(arrayIndices.Length / 3, arrayVertices.Length, MeshFlags.SystemMemory,
        CustomVertex.PositionTextured.Format, device);

        // For each point in the height field calculate the x, y, z and 
        // texture coordinates. 
        for (int y = 0; y < tessellation; y++)
            for (int x = 0; x < tessellation; x++)
                int arrayIndex = y * tessellation + x;
                float xCoordinate = (float)x / (float)(tessellation - 1);
                float yCoordinate = (float)y / (float)(tessellation - 1);
                CustomVertex.PositionTextured vertex = new CustomVertex.PositionTextured
                        (xCoordinate, yCoordinate, GetHeight(xCoordinate, yCoordinate), xCoordinate, yCoordinate);
                arrayVertices[arrayIndex] = vertex;

        // Calculate the index buffer. 
        for (int y = 0; y < (tessellation - 1); y++)
            for (int x = 0; x < (tessellation - 1); x++)
                int arrayIndex = (y * (tessellation - 1) + x) * 6;
                int vertexIndex = y * tessellation + x;

                arrayIndices[arrayIndex] = (short)vertexIndex;
                arrayIndices[arrayIndex + 1] = (short)(vertexIndex + 1);
                arrayIndices[arrayIndex + 2] = (short)(vertexIndex + tessellation);
                arrayIndices[arrayIndex + 3] = (short)(vertexIndex + tessellation);
                arrayIndices[arrayIndex + 4] = (short)(vertexIndex + 1);
                arrayIndices[arrayIndex + 5] = (short)(vertexIndex + tessellation + 1);

        // There is only one attribute value for this mesh. 
        // By specifying an attribute range the DrawSubset function 
        // does not have to scan the entire mesh for all faces that are 
        // are marked with a particular attribute id.
        attributeRange.AttributeId = 0;
        attributeRange.FaceStart = 0;
        attributeRange.FaceCount = arrayIndices.Length / 3;
        attributeRange.VertexStart = 0;
        attributeRange.VertexCount = arrayVertices.Length;

        mesh.VertexBuffer.SetData(arrayVertices, 0, LockFlags.None);
        mesh.IndexBuffer.SetData(arrayIndices, 0, LockFlags.None);
        mesh.SetAttributeTable(new AttributeRange[] { attributeRange });

        return (mesh);

    public static void Main()
            Form Form1 = new Form();
        catch (NotSupportedException)
            MessageBox.Show("Your device does not have the needed 3d " +
                "support to run this sample");
        catch (DriverUnsupportedException)
            MessageBox.Show("Your device does not have the needed 3d " +
                "driver support to run this sample");
        catch (Exception e)
            MessageBox.Show("The sample has run into an error and " +
                "needs to close: " + e.Message);

Community Additions