www.pudn.com > ATimeToKill.rar > terrain.cpp


#include "terrain.h" 
 
CTerrain::CTerrain() 
{ 
	width = 256; 
	scanDepth = 80.0; 
	terrainMul = 50.0; 
	textureMul = 0.25; 
	heightMul = 175.0; 
	fogColor[0] = 0.75f; 
	fogColor[1] = 0.9f; 
	fogColor[2] = 1.0f; 
	fogColor[3] = 1.0f; 
 
	// CObject attributes 
	position = CVector(0,0,0); 
	velocity = CVector(0,0,0); 
	acceleration = CVector(0,0,0); 
	size = sqrt(width*terrainMul*width*terrainMul + width*terrainMul*width*terrainMul); 
 
	BuildTerrain(width, 0.5f); 
} 
 
CTerrain::CTerrain(int w, float rFactor) 
{ 
	width = w; 
	scanDepth = 80.0; 
	terrainMul = 50.0; 
	textureMul = 0.25; 
	heightMul = 175.0; 
	fogColor[0] = 0.75f; 
	fogColor[1] = 0.9f; 
	fogColor[2] = 1.0f; 
	fogColor[3] = 1.0f; 
 
	heightMap = NULL; 
 
	// CObject attributes 
	position = CVector(0,0,0); 
	velocity = CVector(0,0,0); 
	acceleration = CVector(0,0,0); 
	size = sqrt(width*terrainMul*width*terrainMul + width*terrainMul*width*terrainMul); 
 
	BuildTerrain(width, rFactor); 
} 
 
void CTerrain::BuildTerrain(int w, float rFactor) 
{ 
	width = w; 
	heightMap = new float[width*width]; 
	MakeTerrainPlasma(heightMap, width, rFactor); 
	 
	// load texture 
	terrainTex[0].LoadTexture("ground.tga"); 
	glGenTextures(1, &terrainTex[0].texID); 
	glBindTexture(GL_TEXTURE_2D, terrainTex[0].texID); 
 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	//or GL_CLAMP 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);	//or GL_CLAMP 
 
	switch (terrainTex[0].textureType) 
	{ 
	case BMP: 
		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, terrainTex[0].width, terrainTex[0].height, 
					GL_RGB, GL_UNSIGNED_BYTE, terrainTex[0].data); 
		break; 
	case PCX: 
		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, terrainTex[0].width, terrainTex[0].height, 
					GL_RGBA, GL_UNSIGNED_BYTE, terrainTex[0].data); 
		break; 
	case TGA: 
		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, terrainTex[0].width, terrainTex[0].height, 
					GL_RGB, GL_UNSIGNED_BYTE, terrainTex[0].data); 
		break; 
	default: 
		break; 
	} 
} 
 
void CTerrain::OnCollision(CObject *collisionObject) 
{} 
 
void CTerrain::OnDraw(CCamera *camera) 
{ 
	int z, x; 
 
	glEnable(GL_DEPTH_TEST); 
 
	glFogi(GL_FOG_MODE, GL_LINEAR); 
	glFogfv(GL_FOG_COLOR, fogColor); 
	glFogf(GL_FOG_START, scanDepth * 0.2f); 
	glFogf(GL_FOG_END, scanDepth * 2.5); 
	glHint(GL_FOG_HINT, GL_FASTEST); 
	glEnable(GL_FOG); 
 
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
	glEnable(GL_BLEND); 
	glEnable(GL_ALPHA_TEST); 
	glAlphaFunc(GL_GREATER,0.0); 
	glDisable(GL_ALPHA_TEST); 
	// push/pop objects that move with the camera (e.g. a sun, the sky) 
	//glTranslatef(camera->x, camera->y, camera->z); 
 
	glEnable(GL_TEXTURE_2D); 
	glBindTexture(GL_TEXTURE_2D, terrainTex[0].texID); 
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
 
	glColor3f(1.0, 1.0, 1.0); 
	for (z = (int)(camera->position.z / terrainMul - scanDepth), z=z<0?0:z; (z < camera->position.z / terrainMul + scanDepth) && z < width-1; z++) 
	{ 
		glBegin(GL_TRIANGLE_STRIP); 
		for (x = (int)(camera->position.x / terrainMul - scanDepth), x=x<0?0:x; (x < camera->position.x / terrainMul + scanDepth) && x < width-1; x++) 
		{ 
		//	glColor3f(heightMap[x+z*width], heightMap[x+z*width], heightMap[x+z*width]); 
			glTexCoord2f(textureMul * x, textureMul * z); 
			glVertex3f((float)x*terrainMul, (float)heightMap[x + z*width]*heightMul, (float)z*terrainMul); 
 
		//	glColor3f(heightMap[x+1+z*width], heightMap[x+1+z*width], heightMap[x+1+z*width]); 
			glTexCoord2f(textureMul * (x+1), textureMul * z); 
			glVertex3f((float)(x+1)*terrainMul, (float)heightMap[x+1 + z*width]*heightMul, (float)z*terrainMul); 
 
		//	glColor3f(heightMap[x+(z+1)*width], heightMap[x+(z+1)*width], heightMap[x+(z+1)*width]); 
			glTexCoord2f(textureMul * x, textureMul * (z+1)); 
			glVertex3f((float)x*terrainMul, (float)heightMap[x + (z+1)*width]*heightMul, (float)(z+1)*terrainMul); 
 
		//	glColor3f(heightMap[x+1+(z+1)*width], heightMap[x+1+(z+1)*width], heightMap[x+1+(z+1)*width]); 
			glTexCoord2f(textureMul * (x+1), textureMul * (z+1)); 
			glVertex3f((float)(x+1)*terrainMul, (float)heightMap[x+1 + (z+1)*width]*heightMul, (float)(z+1)*terrainMul); 
		} 
		glEnd(); 
	} 
} 
 
// RangedRandom() 
// Returns a random number between v1 and v2 
float CTerrain::RangedRandom(float v1,float v2) 
{ 
	return v1 + (v2-v1)*((float)rand())/((float)RAND_MAX); 
} 
 
// NormalizeTerrain() 
// Given a height field, normalize it so that the minimum altitude 
// is 0.0 and the maximum altitude is 1.0 
void CTerrain::NormalizeTerrain(float field[],int size) 
{ 
	float maxVal,minVal,dh; 
	int i; 
 
	/* 
	Find the maximum and minimum values in the height field 
	*/  
	maxVal = field[0]; 
	minVal = field[0]; 
 
	for (i=1;i maxVal)  
		{ 
			maxVal = field[i]; 
		} 
		else if (field[i] < minVal)  
		{ 
			minVal = field[i]; 
		} 
	} 
 
	/* 
	Find the altitude range (dh) 
	*/ 
	if (maxVal <= minVal) return; 
	dh = maxVal-minVal; 
 
	/* 
	Scale all the values so they are in the range 0-1 
	*/ 
	for (i=0;i 0) 
	{ 
		 
		/* 
		Diamond step - 
 
		Find the values at the center of the retangles by averaging the values at  
		the corners and adding a random offset: 
 
 
		a.....b 
		.     .   
		.  e  . 
		.     . 
		c.....d    
 
		e  = (a+b+c+d)/4 + random 
 
		In the code below: 
		a = (i,j) 
		b = (ni,j) 
		c = (i,nj) 
		d = (ni,nj) 
		e = (mi,mj) 
 
		*/ 
		        
		for (i=0;i