⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 roam.cpp

📁 VC++ DEMO, used for the beginners and the amour
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	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 + -