Dela via


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.

Note

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.

    -or-

    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.

Example

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

    Private Sub New()
        MyBase.New()
        ' In this example, initialize the mesh with 
        ' 4 tessellations 
        Me.InitializeMesh(4)
    End Sub 

    Private Sub InitializeMesh(ByVal tessellation As Integer)
        Dim mesh1 As Mesh = CreateHeightfieldMesh(tessellation)
    End Sub 


    Private Function GetHeight(ByVal x As Single, ByVal y As Single) As Single 
        Return 0

    End Function 

    Private Function CreateHeightfieldMesh(ByVal tessellation As Integer) As Mesh
        Dim mesh As Mesh

        Dim device As Device = Nothing 
        Dim arrayIndices((tessellation - 1) * (tessellation - 1) * 6) As Short 
        Dim arrayVertices(tessellation * tessellation) As CustomVertex.PositionTextured
        Dim attributeRange As 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. 
        Dim y As Integer 
        For y = 0 To tessellation
            Dim x As Integer 
            For x = 0 To tessellation
                Dim arrayIndex As Integer = y * tessellation + x
                Dim xCoordinate As Single = System.Convert.ToSingle(x) / System.Convert.ToSingle(tessellation - 1)
                Dim yCoordinate As Single = System.Convert.ToSingle(y) / System.Convert.ToSingle(tessellation - 1)
                Dim vertex As New CustomVertex.PositionTextured(xCoordinate, yCoordinate, GetHeight(xCoordinate, yCoordinate), xCoordinate, yCoordinate)
                arrayVertices(arrayIndex) = vertex
            Next x
        Next y

        ' Calculate the index buffer. 
        Dim z As Integer 
        For z = 0 To (tessellation - 1)
            Dim x As Integer 
            For x = 0 To (tessellation - 1)
                Dim arrayIndex As Integer = (z * (tessellation - 1) + x) * 6
                Dim vertexIndex As Integer = z * tessellation + x

                arrayIndices(arrayIndex) = Fix(vertexIndex)
                arrayIndices((arrayIndex + 1)) = Fix(vertexIndex + 1)
                arrayIndices((arrayIndex + 2)) = Fix(vertexIndex + tessellation)
                arrayIndices((arrayIndex + 3)) = Fix(vertexIndex + tessellation)
                arrayIndices((arrayIndex + 4)) = Fix(vertexIndex + 1)
                arrayIndices((arrayIndex + 5)) = Fix(vertexIndex + tessellation + 1)
            Next x
        Next z

        ' 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

    End Function 

    Public Shared Sub Main()
        Try 
            Dim Form1 As New Form()
            Application.Run(Form1)
        Catch e As NotSupportedException

            MsgBox("Your device does not have the " + _
                "needed 3d support to run this sample")

        Catch e As DriverUnsupportedException

            MsgBox("Your device does not have the " + _
                "needed 3d driver support to run this sample")

        Catch e As Exception

            MsgBox("The sample has run into an error and " + _
                "needs to close: " + e.Message)
        End Try 

    End Sub 
End Class
class Form1
{
    Form1()
    {
        // In this example, initialize the Mesh object 
        // with 4 tessellations 
        this.InitializeMesh(4);
    }

    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()
    {
        try
        {
            Form Form1 = new Form();
            Application.Run(Form1);
        }
        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);
        }
    }
}

Compiling the Code

This example requires references to the following namespaces:

See Also

Concepts

.NET Compact Framework How-to Topics

Other Resources

Mobile Direct3D Programming in the .NET Compact Framework