I've gotten the rendering for the quad tree system to work but there is a major problem.
I'm not sure how to correctly extract the height data from the map given that each terrain 'piece' holds only world coordinates. Extracting the index into the heightmap from the world coordinates is proving to be messy.
I still need some type of LOD method because with 360500 triangles I'm still only getting about 26 to 30 FPS.
Because the height data is not extracting correctly, I'm getting some very strange maps.
But the quad-tree portion works fine and splits the terrain up correctly.
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);
}