NumCellsPerCol and NumCellsPerRow are

int m_iNumCellsPerCol=m_iNumVertsPerCol-1;

int m_iNumCellsPerRow=m_iNumVertsPerRow-1;

So it doesn't go out of bounds. Mr. Wizard is correct in that normal information is being overwritten. I could fix this by creating 6 vertices per quad, but this is why I didn't do that:

1. It's wasteful.

2. Accessing the terrain information later becomes extremely tedious. Here's why:

Let's say we have a grid...or an array to be more exact. I'll use Direct3D code here to illustrate. This assumes that m_pVB is a valid IDirect3DVertexBuffer9 interface pointer with size (width*height)*sizeof(VertexType).

Code:

VertexType *Vertices;
m_pVB->Lock(0,0,(void **)&Vertices,0);
int startx=-((width*cellsize)>>1);
int startz=-((depth*cellsize))>>1);
int vx=startx;
int vz=startz;
for (int i=0;i<depth;i++)
{
for (int j=0;j<width;j++)
{
int index=i * m_iNumVertsPerRow + j;
Vertices[index]=VertexType((float)vx,0.0f,(float)vz);
vx+=cellsize;
}
vx=startx;
vz+=cellsize;
}
m_pVB->Unlock();

Now with this code I have a simple 2D array or grid of vertices. I can access any grid point using a simple VertexBuffer[row * width + column].

This also makes it very easy to do algos that require indexing into the array to change y values based on distance from some point, etc, etc.

So the vertex buffer in memory is easy to use.

Now take the following code.

Code:

VertexType *Vertices;
m_pVB->Lock(0,0,(void **)&Vertices,0);
int startx=-((width*cellsize)>>1);
int startz=-((depth*cellsize))>>1);
int vx=startx;
int vz=startz;
for (int i=0;i<depth-1;i++)
{
for (int j=0;j<width-1;j++)
{
int index1=i * m_iNumVertsPerRow + j;
int index2=i*m_iNumVertsPerRow+j+1;
int index3=(i+1)*m_iNumVertsPerRow+j;
int index4=index3;
int index5=index2;
int index6=(i+1)*m_iNumVertsPerRow+j+1;
Vertices[index1]=VertexType((float)vx,0.0f,(float)vz);
Vertices[index2]=VertexType((float)vx+cellsize,0.0f,vz);
Vertices[index3]=VertexType((float)vx,0.0f,vz+cellsize);
Vertices[index4]=Vertices[index3];
Vertices[index5]=Vertices[index2];
Vertices[index6]=VertexType((float)vx+cellsize,0.0f,vz+cellsize);
}
}
m_pVB->Unlock();

Now you see that the array is not easy to use. Every 6 vertices or 6 elements represents one quad. It's not impossible to index into it for terrain algos, but it is cumbersome and quite confusing. The corners of the quad are really (starting at Vertex 0):

Vertex 0......Vertex 1/4

................................

Vertex 2/3......Vertex 5

0,1,2 - First triangle

3,4,5 - Second triangle

Duplicated Vertices:

Vertex 2 (duplicate is Vertex 3)

Vertex 1(duplicate is Vertex 4)

The duplicate vertices method allows me much more flexibility since each triangle of the quad can have different normals.....which fits with the design of the terrain. Perhaps I'll need to do this in order to get it to work. But accessing the terrain data is not going to be as easy as my first method. I must remember that if the algo is changing the height value of the upper right corner or the lower left corner...I must change this for both triangles. This would be Vertex 1,4 and Vertex 2,3 since they are overlapping vertices.