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

📄 landscape.cpp

📁 c++程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -