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
Call the Mesh constructor with the desired arguments.
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