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 + -
显示快捷键?