📄 landscape.cpp
字号:
// Landscape.cpp: Implementierung der Klasse CLandscape.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Landscape.h"
// Conversion factor for converting between degrees and radians
#define PI_OVER_180 0.0174532925f
// RGB macros
#define RGB_GETRED(rgb) (((rgb) >> 16) & 0xff)
#define RGB_GETGREEN(rgb) (((rgb) >> 8) & 0xff)
#define RGB_GETBLUE(rgb) ((rgb) & 0xff)
// Array index for axis
const int x = 0;
const int y = 1;
const int z = 2;
//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////
CLandscape::CLandscape()
{
// Init member variables to default values
m_StepSize = 0.2f;
m_TextureCount = -1;
m_ArrayWidth = 0;
m_ArrayHeight = 0;
m_LandscapeList = 0;
m_TilesPerTexture = 10;
m_TilesPerSector = 7;
m_HeightMapHeightScaling = 5.0f;
// Pointers point to nothing
m_Surface = 0;
m_Triangles = 0;
m_VertexNormals = 0;
}
CLandscape::~CLandscape()
{
// Delete surface height data array
delete m_Surface;
m_Surface = 0;
// Delete pointer to dynamic array class
delete m_VertexNormals;
m_VertexNormals = 0;
// Delete triangle array
for (unsigned int i=0; i<m_ArrayWidth + 1; i++)
{
for (unsigned int j=0; j<m_ArrayHeight + 1; j++)
delete [] m_Triangles[i][j];
delete [] m_Triangles[i];
}
delete m_Triangles;
m_Triangles = 0;
}
void CLandscape::GenerateLandscape(const char sHeightMapFileName[], const short int iArrayWidth,
const short int iArrayHeight)
{
// Load heightmap file, calculate the triangles to make a landscape out of it and
// render it into a display list
// Declare variables
// Save passed array height & width to the corresponding member variables
// (Decrement cause array indexing starts with zero)
m_ArrayWidth = iArrayWidth;
m_ArrayWidth--;
m_ArrayHeight = iArrayHeight;
m_ArrayHeight--;
// Loop variables
unsigned int i; unsigned int j;
// Set surface height array pointer. Store the surface height aray in the member data
// cause GetSurfaceHeight() will need it after the calculation of the landscape has been
// finished. Pass a 1 based element count.
m_Surface = new CDynamicArray2D(m_ArrayWidth + 1, m_ArrayHeight + 1);
// 3D Triangle array to hold all later calculated landscape triangles. Store array in the
// memeber data.
m_Triangles = new CLandscapeTriangle ** [m_ArrayWidth + 1];
for (i=0; i<m_ArrayWidth + 1; i++)
{
m_Triangles[i] = new CLandscapeTriangle * [m_ArrayHeight + 1];
for (j=0; j<m_ArrayHeight + 1; j++)
m_Triangles[i][j] = new CLandscapeTriangle[2];
}
// Vertex normal array to hold all the later calculated normals. Pass a 1 based
// element count. Store array in the memeber data.
m_VertexNormals = new CDynamicArray3D(m_ArrayWidth + 1, m_ArrayHeight + 1, 3);
// Load the heightmap into the member data
LoadHeightmap(sHeightMapFileName);
// Calculate surface from the loaded heightmap
CalculateSurface(m_VertexNormals, m_Triangles);
// Render the loaded landscape into a displaylist
RenderToDisplayList(m_VertexNormals, m_Triangles);
}
void CLandscape::CalculateSurface(CDynamicArray3D *cVertexNormals, CLandscapeTriangle ***cTriangles)
{
// Fill the passed arrays with the data from in the member data stored surface height array, which
// must be already calculated. The m_ArrayHeight and m_ArrayWidth member variables need to be set,
// pointers have to be valid, pointers are not deleted.
// Loop trough the whole surface array
for (unsigned int iY=0; iY<=m_ArrayHeight - 1; iY++)
for (unsigned int iX=0; iX<=m_ArrayWidth - 1; iX++)
{
// Lower-left triangle
// Calculate and set triangle vertices
cTriangles[iX][iY][0].m_Vertices[0][x] = iY * m_StepSize;
cTriangles[iX][iY][0].m_Vertices[0][y] = m_Surface->m_Array[iX][iY];
cTriangles[iX][iY][0].m_Vertices[0][z] = iX * m_StepSize;
cTriangles[iX][iY][0].m_Vertices[1][x] = (iY + 1) * m_StepSize;
cTriangles[iX][iY][0].m_Vertices[1][y] = m_Surface->m_Array[iX+1][iY+1];
cTriangles[iX][iY][0].m_Vertices[1][z] = (iX + 1) * m_StepSize;
cTriangles[iX][iY][0].m_Vertices[2][x] = (iY + 1) * m_StepSize;
cTriangles[iX][iY][0].m_Vertices[2][y] = m_Surface->m_Array[iX][iY+1];
cTriangles[iX][iY][0].m_Vertices[2][z] = iX * m_StepSize;
// Calculate normal
cTriangles[iX][iY][0].CalcNormal();
cVertexNormals->m_Array[iX][iY][x] += cTriangles[iX][iY][0].m_Normal[x];
cVertexNormals->m_Array[iX+1][iY+1][y] += cTriangles[iX][iY][0].m_Normal[y];
cVertexNormals->m_Array[iX][iY+1][z] += cTriangles[iX][iY][0].m_Normal[z];
cVertexNormals->m_Array[iX][iY][x] += cTriangles[iX][iY][0].m_Normal[x];
cVertexNormals->m_Array[iX+1][iY+1][y] += cTriangles[iX][iY][0].m_Normal[y];
cVertexNormals->m_Array[iX][iY+1][z] += cTriangles[iX][iY][0].m_Normal[z];
cVertexNormals->m_Array[iX][iY][x] += cTriangles[iX][iY][0].m_Normal[x];
cVertexNormals->m_Array[iX+1][iY+1][y] += cTriangles[iX][iY][0].m_Normal[y];
cVertexNormals->m_Array[iX][iY+1][z] += cTriangles[iX][iY][0].m_Normal[z];
// Upper right triangle
// Calculate and set triangle vertices
cTriangles[iX][iY][1].m_Vertices[0][x] = iY * m_StepSize;
cTriangles[iX][iY][1].m_Vertices[0][y] = m_Surface->m_Array[iX+1][iY];
cTriangles[iX][iY][1].m_Vertices[0][z] = (iX + 1) * m_StepSize;
cTriangles[iX][iY][1].m_Vertices[1][x] = (iY + 1) * m_StepSize;
cTriangles[iX][iY][1].m_Vertices[1][y] = m_Surface->m_Array[iX+1][iY+1];
cTriangles[iX][iY][1].m_Vertices[1][z] = (iX + 1) * m_StepSize;
cTriangles[iX][iY][1].m_Vertices[2][x] = iY * m_StepSize;
cTriangles[iX][iY][1].m_Vertices[2][y] = m_Surface->m_Array[iX][iY];
cTriangles[iX][iY][1].m_Vertices[2][z] = iX * m_StepSize;
// Calculate normal
cTriangles[iX][iY][1].CalcNormal();
cVertexNormals->m_Array[iX+1][iY][x] += cTriangles[iX][iY][1].m_Normal[x];
cVertexNormals->m_Array[iX+1][iY+1][y] += cTriangles[iX][iY][1].m_Normal[y];
cVertexNormals->m_Array[iX][iY][z] += cTriangles[iX][iY][1].m_Normal[z];
cVertexNormals->m_Array[iX+1][iY][x] += cTriangles[iX][iY][1].m_Normal[x];
cVertexNormals->m_Array[iX+1][iY+1][y] += cTriangles[iX][iY][1].m_Normal[y];
cVertexNormals->m_Array[iX][iY][z] += cTriangles[iX][iY][1].m_Normal[z];
cVertexNormals->m_Array[iX+1][iY][x] += cTriangles[iX][iY][1].m_Normal[x];
cVertexNormals->m_Array[iX+1][iY+1][y] += cTriangles[iX][iY][1].m_Normal[y];
cVertexNormals->m_Array[iX][iY][z] += cTriangles[iX][iY][1].m_Normal[z];
}
// Convert all normals to unit length
for (unsigned int iCurNormalX=0; iCurNormalX<=m_ArrayWidth; iCurNormalX++)
for (unsigned int iCurNormalY=0; iCurNormalY<=m_ArrayHeight; iCurNormalY++)
if (iCurNormalX == 0 || iCurNormalY == 0)
{
// Special handling for the normals that don't have six neighbor planes
cVertexNormals->m_Array[iCurNormalX][iCurNormalY][x] = 0.0f;
cVertexNormals->m_Array[iCurNormalX][iCurNormalY][y] = 1.0f;
cVertexNormals->m_Array[iCurNormalX][iCurNormalY][z] = 0.0f;
}
else
{
cVertexNormals->m_Array[iCurNormalX][iCurNormalY][x] /= 3.0f;
cVertexNormals->m_Array[iCurNormalX][iCurNormalY][y] /= 3.0f;
cVertexNormals->m_Array[iCurNormalX][iCurNormalY][z] /= 3.0f;
}
}
void CLandscape::RenderToDisplayList(CDynamicArray3D *cVertexNormals, CLandscapeTriangle ***cTriangles)
{
// Render the loaded landscape into a displaylist. The m_ArrayHeight and m_ArrayWidth
// member variables need to be set, pointers have to be valid, pointers are not deleted.
// Generate a displaylist indexes
m_LandscapeList = glGenLists((int) ((float) m_ArrayWidth / (float) m_TilesPerSector) * ((float) m_ArrayHeight / (float) m_TilesPerSector) + 14);
// Texture ccordinate index
int iTexCoordX = 0;
int iTexCoordY = 0;
// Store start index
unsigned int iCurList = m_LandscapeList;
// Loop trough all sectors that should be generated
for (unsigned int iTileX=0; iTileX<=m_ArrayWidth / m_TilesPerSector; iTileX++)
for (unsigned int iTileY=0; iTileY<=m_ArrayHeight / m_TilesPerSector; iTileY++)
{
// Use generated display list index
glNewList(iCurList, GL_COMPILE);
// Next displaylist
iCurList++;
// Bright base color
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -