Code:
void CTerrain::CreateVertices(TerrainNode *pNode,
int x,int z,int x2,int z2,
int DesiredSize)
{
//Check for leaf condition
//char txt[100];
//sprintf(txt,"X:%d\n Z:%d\n X2:%d\n Z2:%d\n W:%d\n D:%d\n DS:%d",x,z,x2,x,x2-x,z2-z,DesiredSize);
//::MessageBox(0,txt,0,0);
pNode->vMin=D3DXVECTOR3((float)x,-32767.0f,(float)z);
pNode->vMax=D3DXVECTOR3((float)x2,32767.0f,(float)z2);
if ((x2-x)<=DesiredSize)
{
//Yes, we are a leaf
pNode->iType=QUAD_LEAF;
//Set min/max in prep for later frustum cull
//Get extents of vertex buffer
pNode->iNumVertsPerRow=((x2-x)/m_iCellSize)+1;
pNode->iNumVertsPerCol=((z2-z)/m_iCellSize)+1;
pNode->iNumCellsPerRow=pNode->iNumVertsPerRow-1;
pNode->iNumCellsPerCol=pNode->iNumVertsPerCol-1;
pNode->iNumVerts=pNode->iNumVertsPerRow*pNode->iNumVertsPerCol;
pNode->iNumTris=(pNode->iNumCellsPerRow*pNode->iNumCellsPerCol)*2;
pNode->iMapWidth=(x2-x)/m_iCellSize;
pNode->iMapDepth=(z2-z)/m_iCellSize;
//sprintf(txt,"%d %d %d %d %d",pNode->iNumVertsPerRow,
// pNode->iNumVertsPerCol,
// pNode->iNumCellsPerRow,
// pNode->iNumCellsPerCol,
// pNode->iNumVerts);
//::MessageBox(0,txt,0,0);
//Allocate vertex memory
HRESULT hr=m_pDevice->CreateVertexBuffer(pNode->iNumVerts*sizeof(TerrainVertex),
D3DUSAGE_WRITEONLY,
TerrainVertex::FVF,
D3DPOOL_MANAGED,
&pNode->pVB,0);
if (FAILED(hr))
{
::MessageBox(0,"Cannot create mesh",0,0);
return;
}
//Create vertices
int StartX=x;
int StartZ=z;
int EndX=x2;
int EndZ=z2;
//Lock vertex buffer
TerrainVertex *Vertices=0;
pNode->pVB->Lock(0,0,(void **)&Vertices,0);
int index=0;
int lastindex=0;
//Generate vertices
float TexU=fabs(StartX/(float)m_dwWorldWidth);
float TexV=fabs(StartZ/(float)m_dwWorldDepth);
float StartTexU=TexU;
float TexInc=1.0f/(float)m_iMapWidth;
int row=0,col=0;
if (StartX<0)
{
row=(m_dwWorldWidth2+StartX)/m_iCellSize;
} else row=(m_dwWorldWidth2-StartX)/m_iCellSize;
if (StartZ<0)
{
col=(m_dwWorldDepth2+StartZ)/m_iCellSize;
} else col=(m_dwWorldDepth2-StartZ)/m_iCellSize;
int startcol=col;
//char txt[100];
//sprintf(txt,"%d %d %u %u %d %d",row,col,m_dwWorldWidth2,m_dwWorldDepth2,StartX,StartZ);
//::MessageBox(0,txt,0,0);
float minheight=0.0f;
float maxheight=0.0f;
for (int i=StartZ;i<=EndZ;i+=m_iCellSize)
{
col=0;
for (int j=StartX;j<=EndX;j+=m_iCellSize)
{
float height=(float)(m_puHeightMap[row*m_iNumVertsPerRow+col]<<2);
if (minheight<=height) minheight=height;
if (maxheight>=height) maxheight=height;
Vertices[index]=TerrainVertex((float)j,height,(float)i,
TexU,TexV);
Vertices[index].Diffuse=D3DXCOLOR(0.0f,0.0f,0.0f,1.0f);
Vertices[index].Specular=D3DXCOLOR(0.0f,0.0f,0.0f,1.0f);
Vertices[index].DetailTexU=128.0f*TexU;
Vertices[index].DetailTexV=128.0f*TexV;
Vertices[index].LightU=TexU;
Vertices[index].LightV=TexV;
index++;
TexU+=TexInc;
col++;
}
//sprintf(txt,"VB Index:%d\n VB Max:%d Diff:%d",index-1,pNode->iNumVerts,
//index-lastindex);
//::MessageBox(0,txt,0,0);
//lastindex=index;
TexV+=TexInc;
TexU=StartTexU;
row++;
col=startcol;
}
//::MessageBox(0,"Vertex buffer done",0,0);
pNode->pVB->Unlock();
pNode->vMin.y=maxheight;
pNode->vMax.y=minheight;
//Generate indices
index=0;
hr=m_pDevice->CreateIndexBuffer(pNode->iNumTris*3*sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&pNode->pIB,
0);
if (FAILED(hr))
{
::MessageBox(0,"Cannot create index buffer",0,0);
return;
}
WORD *Indices=0;
pNode->pIB->Lock(0,0,(void **)&Indices,0);
for (int i=0;i<pNode->iNumCellsPerCol;i++)
{
for (int j=0;j<pNode->iNumCellsPerRow;j++)
{
Indices[index]=i*pNode->iNumVertsPerRow+j;
Indices[index+1]=i*pNode->iNumVertsPerRow+(j+1);
Indices[index+2]=(i+1)*pNode->iNumVertsPerRow+j;
Indices[index+3]=i*pNode->iNumVertsPerRow+(j+1);
Indices[index+4]=(i+1)*pNode->iNumVertsPerRow+(j+1);
Indices[index+5]=(i+1)*pNode->iNumVertsPerRow+j;
index+=6;
}
//sprintf(txt,"%d %d",index,pNode->iNumIndices);
//::MessageBox(0,txt,0,0);
}
//::MessageBox(0,"Index buffer done",0,0);
pNode->pIB->Unlock();
//End recursion
return;
}
//This is a node, not a leaf
pNode->iType=QUAD_NODE;
//Find centers
int midx=(x2-x)>>1;
int midz=(z2-z)>>1;
midx+=x;
midz+=z;
//char txt[100];
//sprintf(txt,"%d %d %d %d MX:%d MZ:%d",x,z,x2,z2,midx,midz);
//::MessageBox(0,txt,0,0);
//Create children and recurse into tree
pNode->ChildUL=new TerrainNode();
CreateVertices(pNode->ChildUL,x,z,midx,midz,DesiredSize);
pNode->ChildUR=new TerrainNode();
CreateVertices(pNode->ChildUR,midx,z,x2,midz,DesiredSize);
pNode->ChildLL=new TerrainNode();
CreateVertices(pNode->ChildLL,x,midz,midx,z2,DesiredSize);
pNode->ChildLR=new TerrainNode();
CreateVertices(pNode->ChildLR,midx,midz,x2,z2,DesiredSize);
}