Rendering Other Primitive Types

All of the code we've written thus far concentrated on drawing a single type of primitive, namely a list of triangles. However, there are actually numerous different primitive types we can draw. The following list describes these primitive types:

  • PointList This is a self-describing primitive type, as it will render the data as a list of points. You cannot use this primitive type if you are drawing indexed primitives (which we'll cover later in this chapter). See Figure 4.1.

    Figure 4.1. Point lists.

    graphics/04fig01.gif

  • LineList Renders each pair of vertices as individual lines. You must pass in an even number of vertices (at least two) when using this primitive type. See Figure 4.2.

    Figure 4.2. Line lists.

    graphics/04fig02.gif

  • LineStrip Renders the vertices as a single polyline. After the first line segment is drawn using the first two vertices, each subsequent line segment is drawn using the previous line's endpoint as its start point. You must pass in at least two vertices for this primitive type. See Figure 4.3.

    Figure 4.3. Line strips.

    graphics/04fig03.gif

  • TriangleList The primitive type we've been using thus far. Renders each set of three vertices as a single isolated triangle. Back face culling is determined by the current cull render state. See Figure 4.4.

    Figure 4.4. Triangle lists.

    graphics/04fig04.gif

  • TriangleStrip A triangle strip draws each triangle after the first using the last two vertices of the triangle before it. The cull mode is automatically flipped on all even-numbered triangles. The cull mode is flipped on these triangles; since it is sharing the last two vertices of the previous triangle, the vertices will be wound the opposite direction. This is by far the most common primitive type for complex 3D objects. See Figure 4.5.

    Figure 4.5. Triangle strips.

    graphics/04fig05.gif

  • TriangleFan Similar to the TriangleStrip, but each triangle shares the same first vertex. See Figure 4.6.

    Figure 4.6. Triangle fan.

    graphics/04fig06.gif

We can use the same vertex data to draw any of these types of primitives. Direct3D will interpret the vertex data differently depending on the type of primitive that you tell it will be drawn. Let's write a quick bit of code to draw each of the different primitive types.

The sample code on the CD was derived from the first vertex buffer sample we created in Chapter 3, "Rendering Using Simple Techniques." The changes made to the code will be outlined here. Since this code will not require our vertices to be moved, the world transform in SetupCamera was removed, as well as all references to the private "angle" member variable. The following constant was then added:

 private const int NumberItems = 12; 

Twelve was picked arbitrarily, but for a reason. Too many vertices, and the screen gets cluttered; however, we want to ensure we have a number of vertices that is both even and divisible by three. This is so both our LineList primitives and our TriangleList primitives can be rendered correctly. We next need to modify the vertex buffer creation and the OnVertexBufferCreate function as in Listing 4.1:

Listing 4.1 Creating Random Vertices
 vb = new VertexBuffer(typeof(CustomVertex.PositionColored), NumberItems, device,     Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format,     Pool.Default); // Create a list of vertices equal to the number of items CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[NumberItems]; // Randomly select the position of this vertex..  Keep it within a range of 5. for(int i = 0; i < NumberItems; i++) {     float xPos = (float)(Rnd.NextDouble() * 5.0f) - (float)(Rnd.NextDouble() * 5.0f);     float yPos = (float)(Rnd.NextDouble() * 5.0f) - (float)(Rnd.NextDouble() * 5.0f);     float zPos = (float)(Rnd.NextDouble() * 5.0f) - (float)(Rnd.NextDouble() * 5.0f);     verts[i].SetPosition(new Vector3(xPos, yPos, zPos));     verts[i].Color = RandomColor.ToArgb(); } buffer.SetData(verts, 0, LockFlags.None); 

There is nothing magical going on here. We modified our vertex buffer to hold the correct number of vertices (as defined by our NumberItems constant). We then modified our vertex creation function to plot the correct number of vertices in a random way. You can see the source code included on the CD for the definitions of "Rnd" and "RandomColor".

Now we need to modify our actual drawing calls. An easy way to show the difference in how these various primitive types interact with one another would be to have the code scroll through them sequentially. Let's have our drawing code do that every two seconds. An easy way to do this would be to check our current time (in ticks) versus the startup time. Add the following member variables into your declaration section:

 private bool needRecreate = false; // Timing information private static readonly int InitialTickCount = System.Environment.TickCount; 

The Boolean value will allow us to re-create our vertex buffer at the start of each "cycle," so we don't continue to display the same vertices over and over again. Replace the single DrawPrimitives call with the code section in Listing 4.2:

Listing 4.2 Rendering Each Primitive Type
 // We will decide what to draw based on primitives int index = ((System.Environment.TickCount - InitialTickCount) / 2000) % 6; switch (index) {     case 0: // Points         device.DrawPrimitives(PrimitiveType.PointList, 0, NumberItems);         if (needRecreate)         {             // After the primitives have been drawn, recreate a new set             OnVertexBufferCreate(vb, null);             needRecreate = false;         }         break;     case 1: // LineList         device.DrawPrimitives(PrimitiveType.LineList, 0, NumberItems / 2);         needRecreate = true;         break;     case 2: // LineStrip         device.DrawPrimitives(PrimitiveType.LineStrip, 0, NumberItems - 1);         break;     case 3: // TriangleList         device.DrawPrimitives(PrimitiveType.TriangleList, 0, NumberItems / 3);         break;     case 4: // TriangleStrip         device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, NumberItems - 2);         break;     case 5: // TriangleFan         device.DrawPrimitives(PrimitiveType.TriangleFan, 0, NumberItems - 2);         break; } 

This is a relatively self-explanatory section of code. Depending on which primitive type we are on in our cycle, we simply call DrawPrimitives with the appropriate type. You'll notice that for a list of points, we simply use the number of vertices as our primitive count, drawing one point for each vertex. LineList and TriangleList primitives draw isolated primitives, so our DrawPrimitives call with these types is the number of vertices divided by the number of vertices in a single primitive of the correct type: two or three respectively. For LineStrip primitives, given that each vertex after the second shares its starting point with the ending point of the previous line, you only need to draw one less than the current number of items. TriangleStrip and TriangleFan primitives behave the same way, but since there are three vertices in a triangle, with two shared, we use two less.

Running this application will show you first a series of points rendered on the screen, followed by a series of disjointed lines. Next these lines will connect to form a solid polyline, and then switch to a series of isolated triangles. Finally, these triangles will begin sharing vertices to form a strip, and then a fan. One thing you may notice is that the "points" may be small and hard to see. You can artificially "scale" these points by setting a render state. Add the following line to your SetupCamera function to scale each point to three times its normal size:

 device.RenderState.PointSize = 3.0f; 

You'll notice that the single points are now much larger than they were originally. Feel free to play with this render state. Now that we have the different types of primitives drawing correctly, let's investigate ways to lower the amount of memory usage of our data.



Managed DirectX 9 Graphics and Game Programming, Kick Start
Managed DirectX 9 Kick Start: Graphics and Game Programming
ISBN: B003D7JUW6
EAN: N/A
Year: 2002
Pages: 180
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net