📄 landscape.cpp
字号:
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// Activate the landscape texture
if (m_TextureCount != -1)
m_TextureList[0].Use();
// Set the triangle vertices based on the surface array
glBegin(GL_TRIANGLES);
for (unsigned int iY=iTileY * m_TilesPerSector; iY<=(iTileY + 1) * m_TilesPerSector - 1 && iY<=m_ArrayHeight-1; iY++)
{
// Set Y texture coord index
iTexCoordY = iY % m_TilesPerTexture;
for (unsigned int iX=iTileX * m_TilesPerSector; iX<=(iTileX + 1) * m_TilesPerSector - 1 && iX<=m_ArrayWidth-1; iX++)
{
// Set X texture coord index
iTexCoordX = iX % m_TilesPerTexture;
// Set vertices, normals and texture coordinates for the first triangle
glTexCoord2f((float) iTexCoordX / m_TilesPerTexture,
(float) iTexCoordY / m_TilesPerTexture);
glNormal3fv(cVertexNormals->m_Array[iX][iY]);
glVertex3fv(cTriangles[iX][iY][0].m_Vertices[0]);
glTexCoord2f(((float) iTexCoordX + 1.0f) / m_TilesPerTexture,
((float) iTexCoordY + 1.0f) / m_TilesPerTexture);
glNormal3fv(cVertexNormals->m_Array[iX+1][iY+1]);
glVertex3fv(cTriangles[iX][iY][0].m_Vertices[1]);
glTexCoord2f((float) iTexCoordX / m_TilesPerTexture,
(float) (iTexCoordY + 1.0f) / m_TilesPerTexture);
glNormal3fv(cVertexNormals->m_Array[iX][iY+1]);
glVertex3fv(cTriangles[iX][iY][0].m_Vertices[2]);
// Set vertices, normals and texture coordinates for the second triangle
glTexCoord2f((float) (iTexCoordX + 1.0f) / m_TilesPerTexture,
(float) iTexCoordY / m_TilesPerTexture);
glNormal3fv(cVertexNormals->m_Array[iX+1][iY]);
glVertex3fv(cTriangles[iX][iY][1].m_Vertices[0]);
glTexCoord2f(((float) iTexCoordX + 1.0f) / m_TilesPerTexture,
((float) iTexCoordY + 1.0f) / m_TilesPerTexture);
glNormal3fv(cVertexNormals->m_Array[iX+1][iY+1]);
glVertex3fv(cTriangles[iX][iY][1].m_Vertices[1]);
glTexCoord2f((float) iTexCoordX / m_TilesPerTexture,
(float) iTexCoordY / m_TilesPerTexture);
glNormal3fv(cVertexNormals->m_Array[iX][iY]);
glVertex3fv(cTriangles[iX][iY][1].m_Vertices[2]);
}
}
glEnd();
glEndList();
}
// Textures were disabled, restore state
if (m_TextureCount == -1)
glPopAttrib();
}
void CLandscape::LoadHeightmap(const char sHeightMapFileName[])
{
// Load the passed terrain heightmap file and fill the surface height array
// with it. The m_ArrayHeight and m_ArrayWidth member variables need to be set.
// Load heightmap as a monochrome bitmap and select it into the heightmap DC
HBITMAP hBitmap = (HBITMAP) LoadImage(NULL, sHeightMapFileName, IMAGE_BITMAP,
0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_MONOCHROME);
HDC hDC = CreateCompatibleDC(GetWindowDC(GetActiveWindow()));
HGDIOBJ hOldObject = SelectObject(hDC, hBitmap);
// Fill surface array with height values
for (unsigned int iCols=0; iCols<=m_ArrayWidth; iCols++)
for (unsigned int iRows=0; iRows<=m_ArrayHeight; iRows++)
{
// Get color at a given point on the heightmap
COLORREF iColor = GetPixel(hDC, iCols, iRows);
// Convert color to height value and set it. Only get the red
// color component because in a grayscale image RGB are always equal.
// Scale the height value so that it fits to the step size and the
// scaling constant.
m_Surface->m_Array[iCols][iRows] = (float) RGB_GETRED(iColor) /
(255.0f / (m_StepSize * m_HeightMapHeightScaling));
}
// Destroy height map
SelectObject(hDC, hOldObject); // Select old object back into the DC
DeleteObject(hBitmap); // Delete heightmap
DeleteDC(hDC); // Delete heightmap DC
}
void CLandscape::DrawLandscape(float fYRotation, float fXViewer, float fYViewer, float fZViewer)
{
// Call display list for the landscape
for (unsigned int iCurSektor=m_LandscapeList; iCurSektor<=m_LandscapeList + (m_ArrayWidth / m_TilesPerSector) * (m_ArrayHeight / m_TilesPerSector) + 14; iCurSektor++)
glCallList(iCurSektor);
}
bool CLandscape::RegisterTexture(char sFileName[])
{
// Registers a new landscape texture
// Has the maximum of loadable textures been reached ?
if (m_TextureCount >= MAX_TEXTURE_COUNT)
return FALSE;
// Load & add the new texture
if (m_TextureCount == -1)
{
// First texture
m_TextureCount = 0;
m_TextureList[m_TextureCount].LoadBMP(sFileName);
}
else
{
// Already one or more Texture(s) present
m_TextureCount++;
m_TextureList[m_TextureCount].LoadBMP(sFileName);
}
// Texture succesful added
return TRUE;
}
int CLandscape::Rnd(int iMax)
{
// Return an integer with a value between 0 and iMax
return ((rand() * iMax) / RAND_MAX);
}
float CLandscape::GetSurfaceHeight(float fX, float fY)
{
// Get the height of the surface at a given point
// Has a surface been calculated ?
if (!m_Surface)
return -1.0f;
// Is the given point on the surface ?
if (fX < 0.0f ||
fY < 0.0f ||
fX > m_StepSize * m_ArrayWidth ||
fY > m_StepSize * m_ArrayHeight)
return -1.0f;
// Get the four nearest height values
float fHeight1 = m_Surface->m_Array[(int) floor(fX / m_StepSize)][(int) floor(fY / m_StepSize)];
float fHeight2 = m_Surface->m_Array[(int) ceil(fX / m_StepSize)][(int) floor(fY / m_StepSize)];
float fHeight3 = m_Surface->m_Array[(int) floor(fX / m_StepSize)][(int) ceil(fY / m_StepSize)];
float fHeight4 = m_Surface->m_Array[(int) ceil(fX / m_StepSize)][(int) ceil(fY / m_StepSize)];
// Calculate how much weight each height value has
// Distribution between left and right height values
float fHeight1Weight = (float) ceil(fX / m_StepSize) - (fX / m_StepSize);
float fHeight2Weight = (fX / m_StepSize) - (float) floor(fX / m_StepSize);
// Avoid error when floor() and ceil() return the same value
if (fHeight1Weight == 0.0f && fHeight2Weight == 0.0f)
{
fHeight1Weight = 0.5f;
fHeight2Weight = 0.5f;
}
// Distribution between top and bottom height values
float fHeight3Weight = (float) ceil(fY / m_StepSize) - (fY / m_StepSize);
float fHeight4Weight = (fY / m_StepSize) - (float) floor(fY / m_StepSize);
// Avoid error when floor() and ceil() return the same value
if (fHeight3Weight == 0.0f && fHeight4Weight == 0.0f)
{
fHeight3Weight = 0.5f;
fHeight4Weight = 0.5f;
}
// Interpolate between the four nearest height values
// Get the height for the given X position trough interpolation between
// the left and the right height
float fHeightBottom = (fHeight1 * fHeight1Weight + fHeight2 * fHeight2Weight);
float fHeightTop = (fHeight3 * fHeight1Weight + fHeight4 * fHeight2Weight);
return (fHeightBottom * fHeight3Weight + fHeightTop * fHeight4Weight);
}
void CLandscape::SetStepSize(float fStepSize)
{
// Set the step size
// Check value
if (fStepSize > 0.0f && fStepSize < 1000.0f)
m_StepSize = fStepSize;
}
float CLandscape::GetStepSize()
{
// Get the step size
return m_StepSize;
}
void CLandscape::GetLandscapeDimensions(LPRECT lpRect)
{
// Return the dimensions of the landscape
lpRect->left = 0;
lpRect->top = 0;
lpRect->right = m_ArrayWidth;
lpRect->bottom = m_ArrayHeight;
}
void CLandscape::SetHeightScaling(float fHeightScaling)
{
m_HeightMapHeightScaling = fHeightScaling;
}
float CLandscape::GetHeightScaling()
{
return m_HeightMapHeightScaling;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -