MULTIMEDIA

DirectX 10 Game Programming : 3D Introduction - Creating a 3D Grid

3/19/2013 3:43:43 AM
A cube is a nice start; it shows you how you can create entire 3D objects out of simple triangles. In this section, you’re going to take this manual creation a step further with the creation of terrain. If you’ve ever seen games that take place in an outside area, like a flight simulator, then you’ve been exposed to terrain rendering. Terrain rendering is the generation of a landscape, normally based on a grid, which includes features like hills, valleys, and mountains. Generating an outdoor environment might seem to be an outlandish leap from a spinning cube, but it really isn’t that different.

The entire terrain is going to be based on a two-dimensional grid with a fixed number of columns and rows. The grid is laid out as a series of quads made up of triangles; like I said, it’s actually very similar to the cube you just created. Initially, because the grid is flat, your terrain will appear as a large single-colored quad unless you view it in wireframe mode. When viewing the wireframe, you’ll be able to see all the triangles that make up the object.

Because it would be difficult and boring to generate every triangle in a huge landscape by hand, I’m going to show you how to dynamically generate any size terrain. Because the terrain is going to be based on a grid, the extents of this grid need to be defined first. Just to keep things even, I’m setting up the grid to be sixteen columns and sixteen rows.

// Grid Information
#define NUM_COLS 16
#define NUM_ROWS 16

The cells that are created by the rows and columns will need to have a bit of space between them so the vertices that will make up the terrain aren’t bunched right next to each other. As you can see in the following definitions, each of the cells is going to be 32×32 in size.

// The width and height of each cell in the grid
#define CELL_WIDTH 32
#define CELL_HEIGHT 32

The grid itself will have 16 columns but it takes one more vertex to create the final cell. The following definitions allow for this extra vertex and are used in the generation of the terrain.

#define NUM_VERTSX (NUM_COLS + 1)
#define NUM_VERTSY (NUM_ROWS + 1)

Generating the Grid

Like the triangle and cube objects you created before, the first step is the filling of a buffer with all the vertices in the object. Instead of hardcoding all the vertices required, they’re going to be generated using the extents of the grid. To do this I use a series of nested for loops. The outside loop goes through the rows with the inside loop representing the columns. When creating the grid, it is being set up so that the grid will extend away from the viewer in the positive Z direction. This minimizes the amount of movement needed to position the virtual camera.

Each of the vertex positions is created by simply multiplying the current X and Z values by the cell width and heights. You’ll notice that the Y value for each vertex is being set to 0. This will be changed later, but for now just understand that this keeps the grid completely flat.

Take a look at the following code. This shows how all the vertices for this grid are generated. The vertices that make up the grid use the VertexPosColorStruct created earlier.

// create the vertices array large enough to hold all those needed
VertexPosColorStruct vertices[NUM_VERTSX * NUM_VERTSY];

// Fill the vertices array with the terrain values
for(int z=0; z < NUM_VERTSY; ++z)
{
    for(int x=0; x < NUM_VERTSX; ++x)
    {
        vertices[x + z * NUM_VERTSX].Pos.x = (float)x * CELL_WIDTH;
        vertices[x + z * NUM_VERTSX].Pos.z = (float)z * CELL_HEIGHT;

        // Restrict the height to 0
        vertices[x + z * NUM_VERTSX].Pos.y = 0.0f;

        // Create the default color
        vertices[x + z * NUM_VERTSX].Color = D3DXVECTOR4(1.0, 0.0f, 0.0f, 0.0f);
    }
}

					  

After the vertex array is full, you need to create and fill the array of indices for the index buffer. To keep the index array simple, it is going to be filled with a series of triangles to create a triangle list. The first step is the sizing of the indices array. Each cell you create will require two triangles for a total of six vertices. The index array is sized to allow for all six vertices per cell.

Again, the indices are created using a series of nested loops. This keeps you from having to manually define all the indices for the array. Each cell is made up of a quad, so the inside of the loops will need to create two triangles. The triangles themselves are going to be laid out in a counterclockwise manner, making sure that all the triangles have the same winding order. Because the grid is being generated with triangle lists, there are going to be some vertices that are duplicated. Figure 1 shows how the triangles in the grid will be laid out.

Figure 1. The grid layout.


You’ll see that each of the triangles uses vertices from both the surrounding columns and rows. Look at the following code example that uses this layout to define the indices.

// Create the indices array, six vertices for each cell
DWORD indices[NUM_VERTSX * NUM_VERTSY * 6];

// The index counter
int curIndex = 0;

// Fill the indices array to create the triangles needed for the terrain
// The triangles are created in a counterclockwise direction
for (int z=0; z < NUM_ROWS; z++)
{
    for (int x=0; x < NUM_COLS; x++)
    {
        // The current vertex to build off of
        int curVertex = x + (z * NUM_VERTSX);

        // Create the indices for the first triangle
        indices[curIndex]    = curVertex;
        indices[curIndex+1] = curVertex + NUM_VERTSX;
        indices[curIndex+2] = curVertex + 1;

        // Create the indices for the second triangle
        indices[curIndex+3] = curVertex + 1;
        indices[curIndex+4] = curVertex + NUM_VERTSX;
        indices[curIndex+5] = curVertex + NUM_VERTSX + 1;

        // increment curIndex by the number of vertices for the two triangles
        curIndex += 6;
    }
}

					  

Once the index array is full, you can use it to create the index buffer you’ll need when drawing the grid. Figure 2 shows what the grid looks like when rendered in wireframe mode.

Figure 2. A wireframe grid.


Generating Terrain

The only difference between the grid you just created and an outdoor environment is height. As I mentioned before, outdoor environments have hills and valleys, so how do you add these features to the flat grid you have now? The key to adding height is in the code that generates the vertices. Remember how the Y value for all the vertices was being set to 0? By altering the value stored in Y, the height of that cell in the grid is altered as well. This value can be either positive, generating a hill or a negative value, allowing for a dip in the grid.

To allow for more of a dynamic variation, the following code uses the rand function to create the Y value and then uses the modulus (%) operator to restrict the height within the range of CELL_HEIGHT. This will keep the heights from being huge numbers.

// create the vertices array large enough to hold all those needed
VertexPosColorStruct vertices[NUM_VERTSX * NUM_VERTSY];

// Fill the vertices array with the terrain values
for(int z=0; z < NUM_VERTSY; ++z)
{
    for(int x=0; x < NUM_VERTSX; ++x)
    {
        vertices[x + z * NUM_VERTSX].Pos.x = (float)x * CELL_WIDTH;
        vertices[x + z * NUM_VERTSX].Pos.z = (float)z * CELL_HEIGHT;

        // Allow the height of the cell to be randomly decided
        vertices[x + z * NUM_VERTSX].Pos.y = (float)(rand() % CELL_HEIGHT);

        // Create the default color
        vertices[x + z * NUM_VERTSX].Color = D3DXVECTOR4(1.0, 0.0f, 0.0f, 0.0f);
    }
}

					  

Note

Terrain height is commonly generated using a heightmap. The heightmap is either an input file with a series of height values for each part of the grid or a grayscale image file where the brightness of each pixel determines the height in the grid.


If you look at Figure 3 you’ll see the difference that the height makes.

Figure 3. A heightmap drawn using wireframe mode.

Other  
 
Video
Video tutorials
- How To Install Windows 8

- How To Install Windows Server 2012

- How To Install Windows Server 2012 On VirtualBox

- How To Disable Windows 8 Metro UI

- How To Install Windows Store Apps From Windows 8 Classic Desktop

- How To Disable Windows Update in Windows 8

- How To Disable Windows 8 Metro UI

- How To Add Widgets To Windows 8 Lock Screen

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010
programming4us programming4us
Top 10
Free Mobile And Desktop Apps For Accessing Restricted Websites
MASERATI QUATTROPORTE; DIESEL : Lure of Italian limos
TOYOTA CAMRY 2; 2.5 : Camry now more comely
KIA SORENTO 2.2CRDi : Fuel-sipping slugger
How To Setup, Password Protect & Encrypt Wireless Internet Connection
Emulate And Run iPad Apps On Windows, Mac OS X & Linux With iPadian
Backup & Restore Game Progress From Any Game With SaveGameProgress
Generate A Facebook Timeline Cover Using A Free App
New App for Women ‘Remix’ Offers Fashion Advice & Style Tips
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone