📄 roam.cpp
字号:
PATCH::m_vTriangles.clear();
for (nCount=0; nCount < NUM_PATCHES_PER_SIDE*NUM_PATCHES_PER_SIDE; nCount++, patch++ )
{
if ( patch->IsVisible())
{
patch->PatchInToLand();
}
}
LONG number = PATCH::m_vTriangles.size();
TERRAIN::TERRAINVERTEX * PV;
m_pLandVB->Lock(0,0,(BYTE**)&PV,0);
for ( LONG i = 0; i < number; ++i)
{
*PV = PATCH::m_vTriangles[i].vFace[0];PV++;
*PV = PATCH::m_vTriangles[i].vFace[1];PV++;
*PV = PATCH::m_vTriangles[i].vFace[2];PV++;
}
m_pLandVB->Unlock();
D3DXMATRIX matScale,mat;
D3DXMatrixScaling(&matScale,1,MULT_SCALE,1);
m_pD3DDevice->GetTransform(D3DTS_WORLD,&mat);
m_pD3DDevice->SetTransform(D3DTS_WORLD,&matScale);
m_pD3DDevice->SetStreamSource(0,m_pLandVB,sizeof(TERRAIN::TERRAINVERTEX));
m_pD3DDevice->SetVertexShader(TERRAIN::TERRAINVERTEX::TERRAINFVF_VERTEX);
m_pD3DDevice->SetTexture(0,m_pLandTexture);
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,number);
m_pD3DDevice->SetTexture(0,0);
m_pD3DDevice->SetTransform(D3DTS_WORLD,&mat);
if ( GetNextTriNode() != m_nMaxDesiredTris )
{
m_fFrameVariance += ((FLOAT)GetNextTriNode() - (FLOAT)m_nMaxDesiredTris) / (FLOAT)m_nMaxDesiredTris;
}
CHECK_RANGE(m_fFrameVariance,0,10000);
D3DXVECTOR3 vPos = m_Camera->EyeAt();
CHECK_RANGE(vPos.x,100,MAP_SIZE - 100);
CHECK_RANGE(vPos.z,100,MAP_SIZE - 100);
vPos.y = GetHeightValue((LONG)vPos.x,(LONG)vPos.z) + CAMERA_HEIGHT ;
m_Camera->LayAt(vPos);
}
VOID LANDSCAPE::CreateLandMesh()
{
// Perform Tessellation
LONG nCount;
TERRAIN::PATCH *patch = &(m_vPatches[0][0]);
for (nCount=0; nCount < NUM_PATCHES_PER_SIDE*NUM_PATCHES_PER_SIDE; nCount++, patch++ )
{
if ( patch->IsVisible() )
{
patch->Tessellate();
}
}
}
VOID PATCH::RecursTessellate(BinTriangleNode *tri, INT leftX, INT leftY, INT rightX, INT rightY, INT apexX, INT apexY, INT node)
{
FLOAT TriVariance;
INT centerX = (leftX + rightX)>>1; // Compute X coordinate of center of Hypotenuse
INT centerY = (leftY + rightY)>>1; // Compute Y coord...
if ( node < (1<<VARIANCE_DEPTH) )
{
// Extremely slow distance metric (sqrt is used).
// Replace this with a faster one!
INT centerZ = m_ParentLand->m_pHeightMap[centerY * MAP_SIZE + centerX];
FLOAT distance = 1.0f + sqrtf( SQR((FLOAT)centerX - m_ParentLand->m_Camera->EyeAt().x) +
SQR((FLOAT)centerZ - m_ParentLand->m_Camera->EyeAt().y) +
SQR((FLOAT)centerY - m_ParentLand->m_Camera->EyeAt().z));
// Egads! A division too? What's this world coming to!
// This should also be replaced with a faster operation.
distance /= 4.0f;
TriVariance = ((FLOAT)m_CurrentVariance[node] * MAP_SIZE * 2)/distance; // Take both distance and variance into consideration
}
if ( (node >= (1<<VARIANCE_DEPTH)) || // IF we do not have variance info for this node, then we must have gotten here by splitting, so continue down to the lowest level.
(TriVariance > m_ParentLand->m_fFrameVariance)) // OR if we are not below the variance tree, test for variance.
{
Split(tri); // Split this triangle.
if (tri->LeftChild && // If this triangle was split, try to split it's children as well.
((abs(leftX - rightX) >= 3) || (abs(leftY - rightY) >= 3))) // Tessellate all the way down to one vertex per height field entry
{
RecursTessellate( tri->LeftChild, apexX, apexY, leftX, leftY, centerX, centerY, node<<1 );
RecursTessellate( tri->RightChild, rightX, rightY, apexX, apexY, centerX, centerY, 1+(node<<1) );
}
}
}
VOID PATCH::Tessellate()
{
// Split each of the base triangles
m_CurrentVariance = m_VarianceLeft;
RecursTessellate ( &m_BaseLeft,
m_WorldX, m_WorldY+PATCH_SIZE,
m_WorldX+PATCH_SIZE, m_WorldY,
m_WorldX, m_WorldY,
1 );
m_CurrentVariance = m_VarianceRight;
RecursTessellate ( &m_BaseRight,
m_WorldX+PATCH_SIZE, m_WorldY,
m_WorldX, m_WorldY+PATCH_SIZE,
m_WorldX+PATCH_SIZE, m_WorldY+PATCH_SIZE,
1 );
}
VOID PATCH::ReformTriangles(BinTriangleNode *tri, INT leftX, INT leftY, INT rightX, INT rightY, INT apexX, INT apexY)
{
if ( tri->LeftChild ) // All non-leaf nodes have both children, so just check for one
{
INT centerX = (leftX + rightX)>>1; // Compute X coordinate of center of Hypotenuse
INT centerY = (leftY + rightY)>>1; // Compute Y coord...
ReformTriangles( tri->LeftChild, apexX, apexY, leftX, leftY, centerX, centerY );
ReformTriangles( tri->RightChild, rightX, rightY, apexX, apexY, centerX, centerY );
}
else // A leaf node! Output a triangle to be rendered.
{
// Actual number of rendered triangles...
TERRAIN::TRIFACE face;
FLOAT leftZ = m_HeightMap[(leftY *MAP_SIZE)+leftX ];
FLOAT rightZ = m_HeightMap[(rightY*MAP_SIZE)+rightX];
FLOAT apexZ = m_HeightMap[(apexY *MAP_SIZE)+apexX ];
D3DXVECTOR3 vLeft = D3DXVECTOR3(leftX,leftZ,leftY);
D3DXVECTOR3 vRight = D3DXVECTOR3(rightX,rightZ,rightY);
D3DXVECTOR3 vApex = D3DXVECTOR3(apexX,apexZ,apexY);
D3DXVECTOR3 vNormal;
D3DXVec3Cross(&vNormal,&(vLeft-vApex),&(vRight-vApex));
D3DXVec3Normalize(&vNormal,&vNormal);
face.vFace[0].nx = vNormal.x;
face.vFace[0].ny = vNormal.y;
face.vFace[0].nz = vNormal.z;
face.vFace[1].nx = vNormal.x;
face.vFace[1].ny = vNormal.y;
face.vFace[1].nz = vNormal.z;
face.vFace[2].nx = vNormal.x;
face.vFace[2].ny = vNormal.y;
face.vFace[2].nz = vNormal.z;
face.vFace[0].x = m_WorldX + leftX;
face.vFace[0].y = leftZ;
face.vFace[0].z = m_WorldY + leftY;
face.vFace[0].tu = m_ParentLand->m_fXTile * (face.vFace[0].x / MAP_SIZE);
face.vFace[0].tv = m_ParentLand->m_fYTile * (1.0f - face.vFace[0].z / MAP_SIZE);
face.vFace[1].x = m_WorldX + rightX;
face.vFace[1].y = rightZ;
face.vFace[1].z = m_WorldY + rightY;
face.vFace[1].tu = m_ParentLand->m_fXTile * (face.vFace[1].x / MAP_SIZE);
face.vFace[1].tv = m_ParentLand->m_fYTile * (1.0f - face.vFace[1].z / MAP_SIZE);
face.vFace[2].x = m_WorldX + apexX;
face.vFace[2].y = apexZ;
face.vFace[2].z = m_WorldY + apexY;
face.vFace[2].tu = m_ParentLand->m_fXTile * (face.vFace[2].x / MAP_SIZE);
face.vFace[2].tv = m_ParentLand->m_fYTile * (1.0f - face.vFace[2].z / MAP_SIZE);
m_vTriangles.push_back(face);
}
}
VOID PATCH::PatchInToLand()
{
ReformTriangles ( &m_BaseLeft,
0, PATCH_SIZE,
PATCH_SIZE, 0,
0, 0);
ReformTriangles( &m_BaseRight,
PATCH_SIZE, 0,
0, PATCH_SIZE,
PATCH_SIZE, PATCH_SIZE);
}
VOID PATCH::Reset()
{
// Assume patch is not visible.
// Reset the important relationships
m_BaseLeft.LeftChild = m_BaseLeft.RightChild = m_BaseRight.LeftChild = m_BaseLeft.LeftChild = NULL;
// Attach the two m_Base triangles together
m_BaseLeft.BaseNeighbour = &m_BaseRight;
m_BaseRight.BaseNeighbour = &m_BaseLeft;
// Clear the other relationships.
m_BaseLeft.RightNeighbour = m_BaseLeft.LeftNeighbour = m_BaseRight.RightNeighbour = m_BaseRight.LeftNeighbour = NULL;
}
BOOL PATCH::IsVisible()
{
LONG patchCenterX = m_WorldX + PATCH_SIZE / 2;
LONG patchCenterY = m_WorldY + PATCH_SIZE / 2;
FLOAT patchCenterZ = MULT_SCALE * m_ParentLand->m_pHeightMap[patchCenterY*MAP_SIZE + patchCenterX];
return (m_ParentLand->m_Frustum->CheckCube((FLOAT)patchCenterX,patchCenterZ,(FLOAT)patchCenterY,PATCH_SIZE));
}
VOID LANDSCAPE::Create(LPDIRECT3DDEVICE8 device,TCHAR * tstrOfName)
{
FILE *fp;
TCHAR fileName[30];
m_pHeightMap = (BYTE *)malloc( MAP_SIZE * MAP_SIZE * sizeof(BYTE) + MAP_SIZE * 2 );
sprintf( fileName, "Height%d.raw", MAP_SIZE );
fp = fopen(fileName, "rb");
if ( fp == NULL )
{
sprintf( fileName, "Map.ved", MAP_SIZE );
fp = fopen(fileName, "rb");
if ( fp != NULL )
fseek( fp, 40, SEEK_SET ); // Skip to the goods...
}
if (fp == NULL)
{
memset( m_pHeightMap, 0, MAP_SIZE * MAP_SIZE + MAP_SIZE * 2 );
return;
}
fread(m_pHeightMap + MAP_SIZE, 1, (MAP_SIZE * MAP_SIZE), fp);
fclose(fp);
memcpy( m_pHeightMap, m_pHeightMap + MAP_SIZE * MAP_SIZE, MAP_SIZE );
memcpy( m_pHeightMap + MAP_SIZE * MAP_SIZE + MAP_SIZE, m_pHeightMap + MAP_SIZE, MAP_SIZE );
PATCH *patch;
LONG X, Y;
m_pD3DDevice = device;
for ( Y=0; Y < NUM_PATCHES_PER_SIDE; Y++)
{
for ( X=0; X < NUM_PATCHES_PER_SIDE; X++ )
{
patch = &(m_vPatches[Y][X]);
patch->CreatePatch(this,X*PATCH_SIZE, Y*PATCH_SIZE, X*PATCH_SIZE, Y*PATCH_SIZE, m_pHeightMap );
patch->ComputeVariance();
}
}
if ( FAILED(m_pD3DDevice->CreateVertexBuffer(sizeof(TERRAIN::TERRAINVERTEX)*POOL_SIZE*3,
0,0,D3DPOOL_MANAGED,&m_pLandVB)))
{
return;
}
}
BYTE LANDSCAPE::GetHeightValue(LONG x, LONG y)
{
CHECK_RANGE(x,0,MAP_SIZE);
CHECK_RANGE(y,0,MAP_SIZE);
return (MULT_SCALE * m_pHeightMap[y*MAP_SIZE + x]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -