Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

How To: Draw Points, Lines, and Other 3D Primitives

Demonstrates how to draw points, lines, and other 3D primitives.

In the XNA Framework, a 3D primitive is a special type of 3D shape that describes how the graphics device interprets vertices stored in a vertex array or vertex stream. The following example shows you how to use the point, line, and triangle primitive types that are the basis for all low-level drawing calls in the XNA Framework.

Bb196414.note(en-US,XNAGameStudio.30).gifNote
To render primitives, you need to create a basic effect and several transformation matrices. This topic follows the steps described in How To: Use BasicEffect to create an instance of BasicEffect. This sample uses orthographic projection, but you can also use perspective projection to render primitives.

The vertices used in the sample are of type VertexPositionColor Structure. Vertices of this type contain position and color information.

The Complete Sample

The code in this topic shows you the technique. You can download a complete code sample for this topic, including full source code and any additional supporting files required by the sample.

The major steps for this example are listed below:

Drawing Points

To draw a point list

  1. Create a list of vertices in 3D space that represent the points to draw.

    The following code initializes eight points, and stores them in an array of type VertexPositionColor. This results in an array with the following vertex positions.

    pointList = new VertexPositionColor[points];
    
    for (int x = 0; x < points / 2; x++)
    {
        for (int y = 0; y < 2; y++)
        {
            pointList[(x * 2) + y] = new VertexPositionColor(
                new Vector3(x * 100, y * 100, 0), Color.White);
        }
    }
    
    Bb196414.DrawPrimitives1(en-US,XNAGameStudio.30).jpg

    These eight points form a triangle strip consisting of six triangles drawn along the plane z = 0, with the first point at (0, 0, 0). The camera is positioned at (0, 0, 1) looking at (0, 0, 0). An orthogonal projection matrix is created with the upper-left point at (0, 0) and the lower-right point at (800, 600). In addition, a translation matrix shifts the point set to the center of the screen. The following code implements the positioning of the points, the camera, and the required transformations:

    viewMatrix = Matrix.CreateLookAt(
        new Vector3(0.0f, 0.0f, 1.0f),
        Vector3.Zero,
        Vector3.Up
        );
    
    projectionMatrix = Matrix.CreateOrthographicOffCenter(
        0,
        (float)GraphicsDevice.Viewport.Width,
        (float)GraphicsDevice.Viewport.Height,
        0,
        1.0f, 1000.0f);
    
  2. Render the size of a point from a point list by setting the property RenderState.PointSize.

    The point size here is 10. You will see a 10-pixel square at each point in the list.

    GraphicsDevice.RenderState.PointSize = 10;
    
  3. Render the points by calling DrawUserPrimitives, which specifies PrimitiveType.PointList to determine how the data in the vertex array is interpreted.

    GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
        PrimitiveType.PointList,
        pointList,
        0,  // index of the first vertex to draw
        8   // number of primitives
    );
    

Drawing Lines

The following example uses the sample vertex list created in step 1 of "To draw a point list."

To draw a line list

  1. Create an index array that indexes into the vertex buffer.

    This identifies a series of lines.

    // Initialize an array of indices of type short.
    lineListIndices = new short[(points * 2) - 2];
    
    // Populate the array with references to indices in the vertex buffer
    for (int i = 0; i < points - 1; i++)
    {
        lineListIndices[i * 2] = (short)(i);
        lineListIndices[(i * 2) + 1] = (short)(i + 1);
    }
    

    This is equivalent to setting lineListIndices to the following array, which consists of a series of lines between pointList[0] and pointList[1], pointList[1] and pointList[2], and so forth.

    lineListIndices = new short[14]{ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7 };
    
  2. Render the lines by calling DrawUserIndexedPrimitives, which specifies PrimitiveType.LineList to determine how to interpret the data in the vertex array.

    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
        PrimitiveType.LineList,
        pointList,
        0,  // vertex buffer offset to add to each element of the index buffer
        8,  // number of vertices in pointList
        lineListIndices,  // the index buffer
        0,  // first index element to read
        7   // number of primitives to draw
    );
    

Drawing a Line Strip

The following example uses the same point list and renders the same output as "To draw a line list." However, it uses a line strip primitive type when it identifies the indices of the vertex array to draw. You store fewer indices when you use a line strip.

To draw a line strip

  1. Create a list of indices to identify the order in which to draw the points in the specified point list.

    You need only half the number of indices here as you used for the line list because the data consist of a series of connected lines.

    // Initialize an array of indices of type short.
    lineStripIndices = new short[points];
    
    // Populate the array with references to indices in the vertex buffer.
    for (int i = 0; i < points; i++)
    {
        lineStripIndices[i] = (short)(i);
    }
    

    This is equivalent to setting lineStripIndices to the following array, which consists of a series of connected lines between pointList[0], pointList[1], and pointList[2], and so forth.

    lineStripIndices = new short[8]{ 0, 1, 2, 3, 4, 5, 6, 7 };
    
  2. Render the line strip by calling DrawUserIndexedPrimitives, which specifies PrimitiveType.LineStrip to determine how to interpret the data in the vertex array.

    Note that you use fewer vertices to render the same number of primitives rendered earlier by the line list.

    Bb196414.note(en-US,XNAGameStudio.30).gifNote

    In the example code, the line strip is rendered by a series of red lines, instead of the white lines used for the previous line list. This is accomplished by changing the vertex color before you draw the line strip. After you complete the drawing, it reverts to the original color. In addition, vertex coloring was enabled for the basic effect (using BasicEffect.VertexColorEnabled Property).

    The color change indicates a different primitive type was used to achieve the same result.

    for (int i = 0; i < pointList.Length; i++)
        pointList[i].Color = Color.Red;
    
    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
        PrimitiveType.LineStrip,
        pointList,
        0,   // vertex buffer offset to add to each element of the index buffer
        8,   // number of vertices to draw
        lineStripIndices,
        0,   // first index element to read
        7    // number of primitives to draw
    );
    for (int i = 0; i < pointList.Length; i++)
        pointList[i].Color = Color.White;
    

Drawing Triangles

Like a line list, a triangle list is a primitive type that indicates you need to interpret the vertices in the vertex buffer as a series of separately drawn triangles.

To draw a triangle list

  1. Create an array to hold the list of indices that identify a series of triangles to draw from the specified point list.

    triangleListIndices = new short[(width - 1) * (height - 1) * 6];
    
    for (int x = 0; x < width - 1; x++)
    {
        for (int y = 0; y < height - 1; y++)
        {
            triangleListIndices[(x + y * (width - 1)) * 6] = (short)(2 * x);
            triangleListIndices[(x + y * (width - 1)) * 6 + 1] = (short)(2 * x + 1);
            triangleListIndices[(x + y * (width - 1)) * 6 + 2] = (short)(2 * x + 2);
    
            triangleListIndices[(x + y * (width - 1)) * 6 + 3] = (short)(2 * x + 2);
            triangleListIndices[(x + y * (width - 1)) * 6 + 4] = (short)(2 * x + 1);
            triangleListIndices[(x + y * (width - 1)) * 6 + 5] = (short)(2 * x + 3);
        }
    }
    

    This is equivalent to setting triangleListIndices to the following array, which consists of a series of triangles between pointList[0], pointList[1], and pointList[2], and so forth.

    triangleListIndices = new short[18]{ 0, 1, 2, 2, 1, 3, 2, 3, 4, 4, 3, 5, 4, 5, 6, 6, 5, 7 };
    
  2. Render the lines by calling DrawUserIndexedPrimitives

    This specifies PrimitiveType.TriangleList, which determines how the data in the vertex array is interpreted.

    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
        PrimitiveType.TriangleList,
        pointList,
        0,   // vertex buffer offset to add to each element of the index buffer
        8,   // number of vertices to draw
        triangleListIndices,
        0,   // first index element to read
        6    // number of primitives to draw
    );
    

Drawing a Triangle Strip

A triangle strip is a set of triangles that share multiple vertices. This example shows you how to render an object that looks the same as the object rendered with a triangle list. However, fewer vertices are needed because the triangles share multiple vertices.

To draw a triangle strip

  1. Create an array to hold the list of indices that identify a strip of triangles.

    // Initialize an array of indices of type short.
    triangleStripIndices = new short[points];
    
    // Populate the array with references to indices in the vertex buffer.
    for (int i = 0; i < points; i++)
    {
        triangleStripIndices[i] = (short)i;
    }
    

    This is equivalent to setting triangleStripIndices to the following array, which consists of a series of connected triangles between pointList[0], pointList[1], and pointList[2], and so forth.

    triangleStripIndices = new short[8]{ 0, 1, 2, 3, 4, 5, 6, 7 };
    
  2. Render the lines by calling DrawUserIndexedPrimitives.

    This specifies PrimitiveType.TriangleStrip to determine how to interpret the data in the vertex array. Note that you use fewer vertices to render the same number of primitives rendered earlier by the triangle list.

    Bb196414.note(en-US,XNAGameStudio.30).gifNote
    In the example code, the triangle strip is rendered by a series of red lines, instead of the white lines used for the previous triangle list. The color change indicates a different primitive type was used to achieve the same result.
    for (int i = 0; i < pointList.Length; i++)
        pointList[i].Color = Color.Red;
    
    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
        PrimitiveType.TriangleStrip,
        pointList,
        0,  // vertex buffer offset to add to each element of the index buffer
        8,  // number of vertices to draw
        triangleStripIndices,
        0,  // first index element to read
        6   // number of primitives to draw
    );
    for (int i = 0; i < pointList.Length; i++)
        pointList[i].Color = Color.White;
    

Community Additions

ADD
Show:
© 2015 Microsoft