Code:
const char heightmapFilename[] = "Terrains\\heightmap.raw";
const float MAX_HEIGHT = 30.0f;
const float SCALE_FACTOR = 256.0f / MAX_HEIGHT;
int Height(BYTE *pHeightMap, int X, int Y)
{
// Make sure we don't go past our array size
int x = X % TERRAIN_SIZE; // Error check our x value
int y = Y % TERRAIN_SIZE; // Error check our y value
if(!pHeightMap) return 0; // Make sure our data is valid
// Use the equation: index = (x + (y * arrayWidth) ) to find the current height
return pHeightMap[x + (y * TERRAIN_SIZE)]; // Index into our height array and return the height
}
void DrawTerrain(int DrawWater)
{
glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");
FILE *pFile = fopen(heightmapFilename, "rb");
fread(&heightmap, TERRAIN_SIZE * TERRAIN_SIZE, 1, pFile);
fclose(pFile);
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Texture[14]);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Texture[2]);
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Texture[0]);
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE; ++x)
{
// render two vertices of the strip at once
float scaledHeight = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
float nextScaledHeight = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
float color = 0.5f + 0.5f * scaledHeight / MAX_HEIGHT;
float nextColor = 0.5f + 0.5f * nextScaledHeight / MAX_HEIGHT;
glColor3f(color, color, color);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight, static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glColor3f(nextColor, nextColor, nextColor);
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight, static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
glEnd();
}
if(DrawWater == 1)
{
glColor4f(0.9f, 0.9f, 0.9f, 0.15f);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Texture[18]);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Texture[0]);
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_Texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(-40.0, 0.0);glVertex3f(-SEA_SIZE / 2, SEA_LEVEL, SEA_SIZE / 2);
glTexCoord2f(-40.0, 40.0);glVertex3f(-SEA_SIZE / 2, SEA_LEVEL, -SEA_SIZE / 2);
glTexCoord2f(40.0, 40.0);glVertex3f(SEA_SIZE / 2, SEA_LEVEL, -SEA_SIZE / 2);
glTexCoord2f(40.0, 0.0);glVertex3f(SEA_SIZE / 2, SEA_LEVEL, SEA_SIZE / 2);
glEnd();
glDisable(GL_BLEND);
}
CVector3 currentPos = g_Camera.Position();
CVector3 newPos = currentPos;
if (currentPos.y < Height(g_HeightMap, currentPos.x, currentPos.y) + 10)
{
newPos.y = (float)Height(g_HeightMap, currentPos.x, currentPos.y) + 10;
float temp = newPos.y - currentPos.y;
CVector3 vView = g_Camera.View();
vView.y += temp;
g_Camera.PositionCamera(newPos.x, newPos.y, newPos.z,
vView.x, vView.y, vView.z,
0, 1, 0);
}
}
Terrain.h: