Are you tiling the terrain?
If not it's:
Code:
float uinc=1.0f/width;
float vinc=1.0f/height;
float tu=0.0f;
float tv=0.0f;
for (float i=startx;....)
{
for (float j=starty;...)
{
..Create vertex at i,j with texture coords of tu,tv
tu+=uinc
}
tv+=vinc;
}
I will show you my example but beware it's in Direct3D. Most of the code though is not related to Direct3D at all.
Code:
void CTerrain::Init(IDirect3DDevice9 *Device,
int NumVertsPerRow,
int NumVertsPerCol,
int CellSize)
{
m_pDevice=Device;
m_iCellSize=CellSize;
m_iNumVertsPerCol=NumVertsPerCol;
m_iNumVertsPerRow=NumVertsPerRow;
m_iNumCellsPerRow=NumVertsPerRow-1;
m_iNumCellsPerCol=NumVertsPerCol-1;
m_iWidth=m_iNumCellsPerRow*CellSize;
m_iDepth=m_iNumCellsPerCol*CellSize;
m_iNumVertices=m_iNumVertsPerRow*m_iNumVertsPerCol;
m_iNumTris=m_iNumCellsPerRow*m_iNumCellsPerCol*2;
m_pDevice->CreateVertexBuffer(m_iNumVertices*sizeof(TerrainVertex),
D3DUSAGE_DYNAMIC,
TerrainVertex::FVF,
D3DPOOL_DEFAULT,
&m_pVB,
NULL);
TerrainVertex *Vertices;
m_pVB->Lock(0,0,(void **)&Vertices,0);
int iStartX=-(m_iWidth>>1);
int iStartZ=(m_iDepth>>1);
int iEndX=m_iWidth>>1;
int iEndZ=-m_iDepth>>1;
unsigned int vnum=0;
float fAngle=0.0f;
int i=0;
int j=0;
int index=0;
float angle=0.0f;
float vy=0.0f;
float uinc=1.0f/(float)(m_iWidth/2);
float vinc=1.0f/(float)(m_iDepth/2);
for (int vz=iStartZ;vz>=iEndZ;vz-=m_iCellSize)
{
for (int vx=iStartX;vx<=iEndX;vx+=m_iCellSize)
{
index=i*m_iNumVertsPerRow+j;
Vertices[index]=TerrainVertex(D3DXVECTOR3((float)vx,0.0f,(float)vz),
vx*uinc,
vz*vinc);
Vertices[index].Diffuse=D3DXCOLOR(0.0f,1.0f,0.0f,1.0f);
Vertices[index].r=0.0f;
Vertices[index].g=1.0f;
Vertices[index].b=0.0f;
j++;
}
i++;
j=0;
}
m_pVB->Unlock();
m_pDevice->CreateIndexBuffer(m_iNumTris*3*sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&m_pIB,
0);
WORD *Indices=0;
m_pIB->Lock(0,0,(void **)&Indices,0);
unsigned int baseindex=0;
i=0;j=0;
for (i=0;i<m_iNumCellsPerCol;i++)
{
for (int j=0;j<m_iNumCellsPerRow;j++)
{
Indices[baseindex]= i * m_iNumVertsPerRow+ j;
Indices[baseindex+1]= i * m_iNumVertsPerRow+ j +1;
Indices[baseindex+2]= (i+1) * m_iNumVertsPerRow+ j;
Indices[baseindex+3]= (i+1) * m_iNumVertsPerRow+ j;
Indices[baseindex+4]= i * m_iNumVertsPerRow+ j +1;
Indices[baseindex+5]= (i+1) * m_iNumVertsPerRow+ j +1;
baseindex+=6;
}
}
m_pIB->Unlock();
}
That code generates a flat terrain.
I perturb the terrain with this sphere algo. Essentially it picks a size and height value for the sphere. Then it perturbs all affected vertices relative to it's distance from the sphere.
It's slow to generate on the fly, but you could generate the data, save it, and load it later to speed the process up.
Code:
void CTerrain::SphereGenerate(int numiterations)
{
TerrainVertex *Vertices;
m_pVB->Lock(0,0,(void **)&Vertices,0);
int num=0;
do
{
int centerx=rand () % m_iNumVertsPerCol;
int centery=rand () % m_iNumVertsPerRow;
int size=15+rand () % 200;
int height=-400 + (rand () % 800);
for (int i=0;i<m_iNumCellsPerCol;i++)
{
for (int j=0;j<m_iNumCellsPerRow;j++)
{
int index=i*m_iNumCellsPerRow+j;
int distx=centerx-i;
int disty=centery-j;
float dist=sqrt((distx*distx)+(disty*disty));
dist*=2.0f;
dist/=(float)size;
if (fabs(dist)<=1.0f)
{
float height2=(float)height *.5f;
Vertices[index].Position.y+=height2+cosf(dist*3.14f)*height2;
}
}
}
num++;
} while (num<numiterations);
m_pVB->Unlock();
}
Then I set the texture to what I want. I won't show this code because it is pure Direct3D.
Here is the end result...with some fogging added.