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