
1 Attachment(s)
Terrain generation (DX9)
heres the code i use to generate/draw terrain:
Code:
void Create_cVertex(cVertex *p_Vertex, float fX, float fY, float fZ, float fTU, float fTV)
{
p_Vertex>x = fX;
p_Vertex>y = fY;
p_Vertex>z = fZ;
p_Vertex>tu = fTU;
p_Vertex>tv = fTV;
p_Vertex>color = D3DCOLOR_XRGB(255, 255, 255);
}
#define TILES_X 64
#define TILES_Y 64
// Globals:
cVertex terrain[TILES_X * TILES_Y][4];
IDirect3DTexture9 *texture; //already loaded elsewhere
void GenerateTerrain()
{
memset(&terrain, 0, sizeof(terrain));
unsigned int x, y;
float SIZEX = 0.5f, SIZEY = 0.5f;
srand(timeGetTime());
for (x = 0; x < TILES_X; ++x)
{
for (y = 0; y < TILES_Y; ++y)
{
Create_cVertex(&terrain[y + (x * TILES_Y)][0], SIZEX * y, rand() % 2, SIZEY  SIZEX, 0, 0);
Create_cVertex(&terrain[y + (x * TILES_Y)][1], SIZEX * y, rand() % 2, SIZEY, 1, 0);
Create_cVertex(&terrain[y + (x * TILES_Y)][2], SIZEX * (y + 1), rand() % 2, SIZEY  SIZEX, 0, 1);
Create_cVertex(&terrain[y + (x * TILES_Y)][3], SIZEX * (y + 1), rand() % 2, SIZEY, 1, 1);
}
SIZEY += 0.5f;
}
}
void DrawTerrain()
{
unsigned int x, y;
for (x = 0; x < TILES_ROW; ++x)
{
for (y = 0; y < TILES_COLUMN; ++y)
{
g_Device>SetTexture(0, texture);
g_Device>DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, terrain[y + (x * TILES_Y)], sizeof(cVertex));
}
}
}
That works fine for flat terrains, but when i added (rand() % 2) to the y value of each vertex, i get really messed up tiles (image attached).
Also, ive been looking through a few sites, and ive noticed that this person did it differently, using only 3 vertices for each tile and his results seem fine, but its in OpenGL and he uses X and Z instead of X and Y.. Is his method better? and if so, how can i convert his code to work with DirectX.
Thanks in advance.

I may be wrong , but say in a Tile 1, you set the vertices on the left side to a Y of 0, and on the right side (both top and bottom, they end up with Y = 1.
So you're left with an inclined tile going up, to the right.
Then, in the tile beside it (to the right), you set both Y values (on the left side of the tile) to 0 (Well, Rand() decided it so)...then, wouldn't you be left with a gap between the right side of Tile 1 and left side of Tile 2?
Perhaps I missed something, but that seems like a potential problem. I think you'd have to (once all tiles have Y values) compare adjacent tiles and average out the YValues of overlapping vertices to get a smoother terrain. I don't know why this would be producing triangles though...What are your Location/LookAt vectors for your camera?

Code:
void UpdateView()
{
D3DXMATRIX matIdentity, matView, matProjection;
D3DXVECTOR3 vLookatPt(User.x, User.y, User.z);
D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
D3DXVECTOR3 vEyePt(User.x, Camera.y, User.z + Camera.z);
D3DXMatrixIdentity(&matIdentity);
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
D3DXMatrixPerspectiveFovLH(&matProjection, D3DXToRadian(60), (float)g_DisplayMode.Width / (float)g_DisplayMode.Height, 1.0f, 50000.0f);
g_Device>SetTransform(D3DTS_PROJECTION, &matProjection);
g_Device>SetTransform(D3DTS_WORLD, &matIdentity);
g_Device>SetTransform(D3DTS_VIEW, &matView);
}
user.* is just a struct i use to move around the terrain
camera.y = 5.0f; (so its looking down on the terrain)
camera.z = 3.0f; (so its a 3rd person camera, ie. its 3 units behind user.z)

You are creating several disjoint triangles. Remember that in a grid, any one triangle will have a certain number of neighbors. So if you don't use an index buffer you will be recreating several vertices twice.
Render that scene in wireframe mode and you will see that you don't have a grid at all. Practice creating a grid from x,z to +x,+z and set y to 0.0f. You should have a perfect grid squares and 2 tri's within each square or quad. Now displace the y value a bit and don't touch the x and z values. This should produce what you want. Render the scene as a triangle list first and then try to produce as many strips as possible. Notice that at max x,z you could move to max x,z+cellsize and only set two vertices to create your quad as a triangle strip.
It is better, however, to load the height values from a map. Notice that x and z do not change in the grid and they increment by constants. The only thing that really changes with simple terrains is the height or y value. So it makes sense that you could create a greyscale image and load the data into memory. To displace the y component of the vertex, check the map at (x/cellsize),(z/cellsize), scale the value to fit your needs and set that vertices y component and/or set it's texture ID and texture coords. Now render and extract the texture ID from each vertex. If the texture ID does not match the current one, switch to the vertex texture ID, set current texture ID to it's ID and render  you should have some very good looking tiled and textured terrain. If you would like to smooth it notice that any smoothing function that can be done on an array can be done on your terrain since it is really just an array of Y values. The possibilities are endless. Another thing to do is add light. Here are the computations for simple precomputed pervertex dot3 lighting in Direct3D for any one triangle. The normal for a vertex here is assumed to be the normal of the plane created by the vertices. You could do normal averaging and get much better results. Notice in a triangle list every 6 vertices is 1 quad or 2 triangles.
Code:
for (int i=0;i<m_iNumVertices;i++)
{
//Vector to light source
D3DXVECTOR3 ToLight=Vertices[i].PosLight.Pos;
//Find normal of plane formed by this triangle
D3DXVECTOR3 V1=Vertices[i].PosVertices[i+1].Pos;
D3DXVECTOR3 V2=Vertices[i].PosVertices[i+2].Pos;
D3DXVec3Normalize(&V1,&V1);
D3DXVec3Normalize(&V2,&V2);
D3DXVec3Cross(&Vertices[i].Normal,&V1,&V2);
//Normalize vector to light source
D3DXVec3Normalize(&ToLight,&ToLight);
//Set dot3 value of this vertex
//Always satisfies 0<dot3<1.0f
Vertices[i].PreComputedDot=MAX(D3DXVec3Dot(&ToLight,&Vertices[i].Normal),0.0f);
}
Not every vertex needs a normal  just every 7th one because when we compute the normal we are using 3 vertices that make up the tri and setting the first vertex normal to that value. So if we always look at the ith vertex normal  the next 5 will be the same value.

1 Attachment(s)
what do you mean by not having a grid? heres a screenshot in wireframe mode, it seems to have a grid..

btw, about the lightmap, i was going to add that once i figured out how i could fix this problem, because the only way i know atm, is to edit 4 different vertices for 1 point on the terrain to .. elevate, im guessing this is because i use 4 vertices per square, and no index buffer. Is there a better way? like maybe sharing the vertices from the previous tile, and so on, that might work out better

I would share the vertices. It is more efficient not to, but it adds flexibility to the system if you do  at the small cost of memory which by today's standards isn't even a consideration.
There is no way that is the same image as the top one, just in wireframe mode. The first one is a huge mess of oddly placed triangles. If you perturb the y values of the vertices in the second picture  you should get a terrain.

1 Attachment(s)
but thats exactly, what i do, i just edit the y values of the tiles in the picture. but since the vertices arent shared, only 1 vertex from the tile changes, and it 'seperates' from the other tiles around it. how would i actually go about sharing the vertices? ive never done it before, except for 2 triangles (quad).
image of triangles with modified y values

Iterate through the array and change the y values. If you are using an array, they should all be shared.
Triangle 1  0,1,2
Triangle 2  1,3,2
01
23
1 Quad.
So your grid will look like this:
0145
2367
or something close to it.

If you have all your vertices in an array indexed 0 to n1, then create an array of render indices that specify the drawing order for your mesh. for example
Code:
say your 2D array is represented as a 1D array like the element indices below:
1 2 3
4 5 6
7 8 9
ex. array vaules (heights):
heights = {
23 45 60
32 35 63
63 53 55
}
now create an array which specifies the rendering order.. for triangle strips it could be as follows.
renderIndices = { 1 4 2 5 3 6 9 5 8 4 7 }

2 Attachment(s)
image #1 has vertices going from v1 to v4 on the first line
image #2 has vertices going from v1 to v14 on the first line
i just googled a bit more and found an article with image #1, as you can see, he defined the first row up to v9. in image #2 (my method), i defined the first row up to v15, because i use 2 vertices for 1 point most of the time.
my question is, if i defined it like in image #1, up to v9, how would i render it? the creation is easy, the rendering part i dont understand, since the first triangle is v0  v1  v5 instead of v0  v1  v2.

>>my question is, if i defined it like in image #1, up to v9, how would i render it?
just like i explained above if you want one continuous triangle strip. Maybe it would be easier for you to start with rendering individual rows of triangle strips.
looky...
Code:
for (int i = 0; i < height  1; i++) {
beginTriangleStrip
for (int j = 0; j < width; j++) {
render vertex i * width + j
render vertex (i + 1) * width + j
}
endTriangleStrip
}
so, from your image above... it would render v0, v5, v1, v6, v2, v7 etc....
what Bubba and i are suggesting is to precalculate these render indices and store them in an array. This makes using vertex arrays (or whatever DX calls it) easy and rendering faster.