heightmap.cpp

来自「3D游戏展示程序」· C++ 代码 · 共 618 行 · 第 1/2 页

CPP
618
字号
	{
		Zpos = 1-checked->z*WORLD_TO_HEIGHT+int(checked->z*WORLD_TO_HEIGHT);
	}

	int addx = point.x + 1;
	int addy = point.y + 1;
	if(addx==m_Size)	addx = 0;
	if(addy==m_Size)	addy = 0;
/*
*/
	float h11 = float(m_HeightData.m_pData[m_Size * point.y + point.x]);
	float h12 = float(m_HeightData.m_pData[m_Size * addy + point.x]);
	float h21 = float(m_HeightData.m_pData[m_Size * point.y + addx]);
	float h22 = float(m_HeightData.m_pData[m_Size * addy + addx]);
	//三次线性插值
	float ha = h11 + Xpos * (h21 - h11);
	float hb = h12 + Xpos * (h22 - h12);	
	float ypos = ha + Zpos * (hb - ha);

	//float haa = h11 + Zpos * (h12-h11);
	//float hbb = h21 + Zpos * (h22-h21);
	//float yposs = haa + Xpos * (hbb-haa);

	return ypos;
}

//----------------------------------------------------
// 获取精确高度
//----------------------------------------------------
float CHeightmap::GetHeight(float Worldxpos, float Worldzpos)
{
	D3DXVECTOR3 temp = D3DXVECTOR3(Worldxpos, 0, Worldzpos);
	float ypos = GetHeight(&temp);
	return ypos;
}

//----------------------------------------------------
// 世界坐标转换到高度图(循环地形)
//----------------------------------------------------
POINT CHeightmap::ConvertToHeightmap(D3DXVECTOR3 *pos)
{
	POINT point;
	if(pos->x<0)
	{
		point.x = (m_Size-1) + int(pos->x*WORLD_TO_HEIGHT)%m_Size;
	}
	else
	{
		point.x = int(pos->x*WORLD_TO_HEIGHT)%m_Size;
	}
	if(pos->z<=0)
	{
		point.y = -(int(pos->z*WORLD_TO_HEIGHT)%m_Size);
	}
	else 
	{
		point.y = (m_Size-1) - int(pos->z*WORLD_TO_HEIGHT)%m_Size;
	}

	return point;
}

//----------------------------------------------------
// 世界坐标转换到移动图
//----------------------------------------------------
POINT CHeightmap::ConvertToMovemap(D3DXVECTOR3 pos)
{
	POINT point;
	if(pos.x < m_ViewOffsetX)
	{
		point.x = int((pos.x-m_ViewOffsetX)*WORLD_TO_MOVE)+MOVE_MAP_SIZE/2-1;
	}
	else
	{
		point.x = int((pos.x-m_ViewOffsetX)*WORLD_TO_MOVE)+MOVE_MAP_SIZE/2;
	}
	if(pos.z < m_ViewOffsetZ)
	{
		point.y = int((pos.z-m_ViewOffsetZ)*WORLD_TO_MOVE)+MOVE_MAP_SIZE/2-1;
	}
	else
	{
		point.y = int((pos.z-m_ViewOffsetZ)*WORLD_TO_MOVE)+MOVE_MAP_SIZE/2;
	}
/*
	if(point.x<0 || point.x>=MOVE_MAP_SIZE || point.y<0 || point.y>=MOVE_MAP_SIZE)
	{   
		POINT pt;
		pt.x = 0;
		pt.y = 0;
		return pt;
	}
*/
	return point;
}

//----------------------------------------------------
// 移动图转换到世界坐标(y轴是高度图的高度)
//----------------------------------------------------
D3DXVECTOR3 CHeightmap::ConvertToWorld(int movemapXPos, int movemapZPos)
{
	D3DXVECTOR3 position;
	position.x = float(m_ViewOffsetX + (movemapXPos-MOVE_MAP_SIZE/2)*HEIGHT_MAP_SCALE*MOVE_MAP_SCALE);
	position.z = float(m_ViewOffsetZ + (movemapZPos-MOVE_MAP_SIZE/2)*HEIGHT_MAP_SCALE*MOVE_MAP_SCALE);

	POINT point;
	point.x = m_pMovemap[movemapZPos*MOVE_MAP_SIZE+movemapXPos].xpos;
	point.y = m_pMovemap[movemapZPos*MOVE_MAP_SIZE+movemapXPos].zpos;

	position.y = m_HeightData.m_pData[m_Size * point.y + point.x];

	return position;
}

//----------------------------------------------------
// 可视检测(世界坐标)
//----------------------------------------------------
bool CHeightmap::IsInFrustum(D3DXVECTOR3 *checked)
{
	POINT point = ConvertToMovemap(*checked);
	return m_Frustum.IsInFrustum(point.x, point.y);
}

//----------------------------------------------------
// 可视检测(世界坐标)
//----------------------------------------------------
bool CHeightmap::IsInFrustum(float x, float z)
{
	POINT point = ConvertToMovemap(D3DXVECTOR3(x, 255, z));
	return m_Frustum.IsInFrustum(point.x, point.y);
}

//----------------------------------------------------
// 可视检测(包围体)
//----------------------------------------------------
bool CHeightmap::IsInFrustum(Boundary_3D *pBoundary)
{
	if(IsInFrustum(pBoundary->minx, pBoundary->minz))	return true;
	if(IsInFrustum(pBoundary->maxx, pBoundary->minz))	return true;
	if(IsInFrustum(pBoundary->maxx, pBoundary->maxz))	return true;
	if(IsInFrustum(pBoundary->minx, pBoundary->maxz))	return true;

	return false;
}

//----------------------------------------------------
// 计算地形光照阴影和纹理混合alpha(顶点DIFFUSE)
//----------------------------------------------------
void CHeightmap::ComputeDiffuse(D3DXVECTOR3* directionToLight)
{
	/*
	___________________________________________________
	1. (C-A)与(B-A)的叉乘得出面法线向量.
	2. 法线向量与光照方向的点乘得出夹角的大小(即光照分量)
	3. 两个向量都标准化之后, 点乘的值小于等于1.0f
	___________________________________________________

	A------->C
	|
	|
	|
	B

	*/
	if(m_pLightColor == NULL)
		return;
	int index;
	float heightA, heightB, heightC;
	for(int i=0; i<m_Size; i++)
	{
		for(int j=0; j<m_Size; j++)
		{
			index = i*m_Size+j;
			heightA = (float)m_HeightData.m_pData[index];
			if(i+1>=m_Size)	{	index = j;	}
			else			{	index = (i+1)*m_Size+j;	}
			heightB = (float)m_HeightData.m_pData[index];
			if(j+1>=m_Size)	{	index = i*m_Size;	}
			else			{	index = i*m_Size+(j+1);	}
			heightC = (float)m_HeightData.m_pData[index];
			
			D3DXVECTOR3 u((float)HEIGHT_MAP_SCALE, heightC - heightA, 0.0f);
			D3DXVECTOR3 v(0.0f, heightB - heightA, (float)(HEIGHT_MAP_SCALE));
			D3DXVECTOR3 n;
			D3DXVec3Cross(&n, &u, &v);
			D3DXVec3Normalize(&n, &n);
			D3DXVec3Normalize(directionToLight, directionToLight);
			float cosine = D3DXVec3Dot(&n, directionToLight);

			if(cosine < 0.0f)
				cosine = 0.0f;

			m_pLightColor[i*m_Size+j] = MakeARGB(0x00, (BYTE)(cosine*0xff), (BYTE)(cosine*0xff), (BYTE)(cosine*0xff));		
		}
	}
	
	// 纹理混合Alpha分量
	//___________________________________________________
	// 64*64
	//___________________________________________________
	
	unsigned char texindex[64][64];
	FILE *fp = fopen("Picture\\texture_index.BMP", "rb");
	if(fp==NULL)
	{
		return;
	}
	fseek(fp, 1078, SEEK_SET);
	for(int z=63; z>-1; z--)
	{
		for(int x=0; x<64; x++)
		{
			fread(&texindex[z][x], sizeof(unsigned char), 1, fp);	
		}
	}
	fclose(fp); 
	BYTE alpha_1 = 0;
	BYTE alpha_2 = 0;
	BYTE alpha_3 = 0;
	BYTE alpha_4 = 0;
	for(int z=0; z<64; z++)
	{
		for(int x=0; x<64; x++)
		{
			int addx = x + 1;
			int addz = z + 1;
			if(addx==64) addx = 0;
			if(addz==64) addz = 0;
			alpha_1 = 0x00;
			alpha_2 = 0x00;
			alpha_3 = 0x00;
			alpha_4 = 0x00;

			if(texindex[z][x] < 64)			alpha_1 = 0xFF;	
			if(texindex[z][addx] < 64)		alpha_2 = 0xFF;
			if(texindex[addz][x] < 64)		alpha_3 = 0xFF;
			if(texindex[addz][addx] < 64)	alpha_4 = 0xFF;

			int delta1 = (alpha_2-alpha_1)/4;
			int delta2 = (alpha_4-alpha_3)/4;
			for(int i=0; i<5; i++)
			{
				BYTE colorAlpha1 = alpha_1+delta1*i;
				BYTE colorAlpha2 = alpha_3+delta2*i;
				int colorDelta = (colorAlpha2-colorAlpha1)/4;
				for(int j=0; j<5; j++)
				{
					BYTE coloralpha = colorAlpha1+colorDelta*j;
					m_pLightColor[(z*4+j)*m_Size+x*4+i] = m_pLightColor[(z*4+j)*m_Size+x*4+i] | coloralpha<<24;
				}
			}
		}
	}
	
	//___________________________________________________
	// 256*256
	//___________________________________________________
	/*
	unsigned char texindex[256][256];
	FILE *fp = fopen("Picture\\tex_index256.BMP", "rb");
	if(fp==NULL)
	{
		return;
	}
	fseek(fp, 1078, SEEK_SET);
	for(int z=255; z>-1; z--)
	{
		for(int x=0; x<256; x++)
		{
			fread(&texindex[z][x], sizeof(unsigned char), 1, fp);	
		}
	}
	fclose(fp); 
	for(int z=0; z<256; z++)
	{
		for(int x=0; x<256; x++)
		{
			BYTE alpha = 0x00;
			if(texindex[z][x] < 64)			alpha = 0xFF;	
		
			m_pLightColor[z*m_Size+x] = m_pLightColor[z*m_Size+x] | alpha<<24;
		}
	}
	*/
}

//----------------------------------------------------
// 计算顶点
//----------------------------------------------------
void CHeightmap::CreateVertex(void)
{
	for(int i=0; i<m_Size; i++)
	{
		for(int j=0; j<m_Size; j++)
		{
			float height = (float)m_HeightData.m_pData[i*m_Size+j];
			m_pVertex[i*m_Size+j] = HeightmapVertex((float)(j*HEIGHT_MAP_SCALE), height, (float)((255-i)*HEIGHT_MAP_SCALE),
				m_pLightColor[i*m_Size+j], 0.25f*j, 63.75f-i*0.25f);
		}
	}
}

//----------------------------------------------------
// 设置可视距离
//----------------------------------------------------
void CHeightmap::SetViewDistance(int distance)
{
	m_Frustum.InitFrustum(45, distance);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?