CTerrain.cpp
上传用户:arsena_zhu
上传日期:2022-07-12
资源大小:399k
文件大小:29k
- /*
- Class Name:
- CTerrain.
- Created by:
- Allen Sherrod (Programming Ace of www.UltimateGameProgramming.com).
- Description:
- This class is a base class used to load and save a terrain.
- */
- #include "main.h"
- float mod(float f)
- {
- while(f >= 1) f--;
- return f;
- }
- CTerrain::CTerrain()
- {
- bInvert = true;
- fScale = 0.1f;
- pVertex = NULL;
- pTexCoords = NULL;
- pTexCoords2 = NULL;
- iVerts = 0;
- iTriangles = 0;
- iDetail = 1;
- }
- CTerrain::~CTerrain()
- {
- ShutDown();
- }
- bool CTerrain::LoadMap(char *filename, int detailRepeats)
- {
- FILE *f = NULL;
- f = fopen(filename, "rb");
- if(f == NULL) return false;
- fread(&side, 1, sizeof(side), f);
- if (side > 1024 || side < 32) side = 128;
- side_ = side-1;
- hMap = new float[side*side];
- fread(hMap, sizeof(*hMap), side*side, f);
- if(f == NULL) { MessageBox(NULL, "f == NULL :/", "map loading failed", MB_OK); fclose(f); return false; }
- fclose(f);
-
- if (detailRepeats == 0)
- { if (iDetail == 0) iDetail = 16; }
- else iDetail = detailRepeats;
- CreateTerrainMesh();
- return true;
- }
- bool CTerrain::SaveMap(char *filename)
- {
- FILE *f = NULL;
- f = fopen(filename, "wb");
- if(f == NULL) return false;
- fwrite(&side, 1, sizeof(side), f);
- fwrite(hMap, sizeof(*hMap), side*side, f);
- if(f == NULL) { MessageBox(NULL, "f == NULL :/", "map loading failed", MB_OK); fclose(f); return false; }
- fclose(f);
-
- return true;
- }
- void CTerrain::ConvertMesh()
- {
- for (int x=0 ; x < side ; x++)
- {
- for (int z=0 ; z < side ; z++)
- {
- hMap[x + z*side] = GetHeight(x, z);
- }
- }
- }
- void CTerrain::CreateTerrainMesh()
- {
- // Index counters.
- int i = 0, t = 0, t2 = 0;
- if(pVertex) delete[] pVertex;
- if(pTexCoords) delete[] pTexCoords;
- if(pTexCoords2) delete[] pTexCoords2;
- iVerts = 0;
- iTriangles = 0;
- //Sizes we need for the points/color and tex coords.
- int size = ((side - 1) *
- (side - 1) * 6) * 3;
- int tSize = ((side - 1) *
- (side - 1) * 6) * 2;
- // Create enough space for all vertex points and their colors.
- pVertex = new float[size];
- pTexCoords = new float[tSize];
- pTexCoords2 = new float[tSize];
- // Loop through and generate a grid. Use the height map
- // when setting the Y to create the terrain mesh. Create 2 triangles
- // each iteration.
- for(int z = 0; z < side - 1; z++)
- {
- for(int x = 0; x < side - 1; x++)
- {
- // Calculate texture coords for these tris.
- float left = (float)x / side;
- float right = ((float)x + 1) / side;
- float bottom = (float)z / side;
- float top = (float)(z + 1) / side;
- // V1.
- pTexCoords[t++] = left;
- pTexCoords[t++] = bottom;
- pTexCoords2[t2++] = left * iDetail;
- pTexCoords2[t2++] = bottom * iDetail;
- pVertex[i++] = (float)x;
- pVertex[i++] = GetDataHeight(x, z);
- pVertex[i++] = (float)z;
- iVerts++;
- // V2.
- pTexCoords[t++] = left;
- pTexCoords[t++] = top;
- pTexCoords2[t2++] = left * iDetail;
- pTexCoords2[t2++] = top * iDetail;
- pVertex[i++] = (float)x;
- pVertex[i++] = GetDataHeight(x, z + 1);
- pVertex[i++] = (float)z + 1;
- iVerts++;
- // V3.
- pTexCoords[t++] = right;
- pTexCoords[t++] = bottom;
- pTexCoords2[t2++] = right * iDetail;
- pTexCoords2[t2++] = bottom * iDetail;
- pVertex[i++] = (float)x + 1;
- pVertex[i++] = GetDataHeight(x + 1, z);
- pVertex[i++] = (float)z;
- iVerts++;
- // V4.
- pTexCoords[t++] = right;
- pTexCoords[t++] = bottom;
- pTexCoords2[t2++] = right * iDetail;
- pTexCoords2[t2++] = bottom * iDetail;
- pVertex[i++] = (float)x + 1;
- pVertex[i++] = GetDataHeight(x + 1, z);
- pVertex[i++] = (float)z;
- iVerts++;
- // V5.
- pTexCoords[t++] = right;
- pTexCoords[t++] = top;
- pTexCoords2[t2++] = right * iDetail;
- pTexCoords2[t2++] = top * iDetail;
- pVertex[i++] = (float)x + 1;
- pVertex[i++] = GetDataHeight(x + 1, z + 1);
- pVertex[i++] = (float)z + 1;
- iVerts++;
- // V6.
- pTexCoords[t++] = left;
- pTexCoords[t++] = top;
- pTexCoords2[t2++] = left * iDetail;
- pTexCoords2[t2++] = top * iDetail;
- pVertex[i++] = (float)x;
- pVertex[i++] = GetDataHeight(x, z + 1);
- pVertex[i++] = (float)z + 1;
- iVerts++;
- iTriangles += 2;
- }
- }
- }
- void CTerrain::CreateTexCoords()
- {
- // Index counters.
- int t = 0, t2 = 0;
- if(pTexCoords) delete[] pTexCoords;
- if(pTexCoords2) delete[] pTexCoords2;
- //Sizes we need for the points/color and tex coords.
- int size = ((side - 1) *
- (side - 1) * 6) * 3;
- int tSize = ((side - 1) *
- (side - 1) * 6) * 2;
- // Create enough space for all vertex points and their colors.
- pTexCoords = new float[tSize];
- pTexCoords2 = new float[tSize];
- // Loop through and generate a grid. Use the height map
- // when setting the Y to create the terrain mesh. Create 2 triangles
- // each iteration.
- for(int z = 0; z < side - 1; z++)
- {
- for(int x = 0; x < side - 1; x++)
- {
- // Calculate texture coords for these tris.
- float left = (float)x / side;
- float right = ((float)x + 1) / side;
- float bottom = (float)z / side;
- float top = (float)(z + 1) / side;
- // V1.
- pTexCoords[t++] = left;
- pTexCoords[t++] = bottom;
- pTexCoords2[t2++] = left * iDetail;
- pTexCoords2[t2++] = bottom * iDetail;
- // V2.
- pTexCoords[t++] = left;
- pTexCoords[t++] = top;
- pTexCoords2[t2++] = left * iDetail;
- pTexCoords2[t2++] = top * iDetail;
- // V3.
- pTexCoords[t++] = right;
- pTexCoords[t++] = bottom;
- pTexCoords2[t2++] = right * iDetail;
- pTexCoords2[t2++] = bottom * iDetail;
- // V4.
- pTexCoords[t++] = right;
- pTexCoords[t++] = bottom;
- pTexCoords2[t2++] = right * iDetail;
- pTexCoords2[t2++] = bottom * iDetail;
- // V5.
- pTexCoords[t++] = right;
- pTexCoords[t++] = top;
- pTexCoords2[t2++] = right * iDetail;
- pTexCoords2[t2++] = top * iDetail;
- // V6.
- pTexCoords[t++] = left;
- pTexCoords[t++] = top;
- pTexCoords2[t2++] = left * iDetail;
- pTexCoords2[t2++] = top * iDetail;
- }
- }
- }
- void CTerrain::SetHeightScale(int val)
- {
- // Set the scale value to want is passed in.
- fScale = val;
- }
- void CTerrain::SetDataHeight(int x, int z, float set)
- {
- if (x < 0 || z < 0 || x >= side || z >= side) return;
- hMap[x + side * z] = set;
- }
- float CTerrain::GetDataHeight(int x, int z)
- {
- if (x < 0 || z < 0 || x >= side || z >= side) return 0;
- return hMap[x + side * z];
- }
- float CTerrain::RegionPercent(int tileType, float height)
- {
- float distance1 = 0, distance2 = 0;
- // First we test each tile and see if the test height is greater than its optimal height.
- // We only test those that are the type we sent it.
- if(m_tiles.texTiles[0].image)
- {
- if(tileType == 0 && height < m_tiles.regions[0].optimalHeight)
- return 1.0f;
- }
- else if(m_tiles.texTiles[1].image)
- {
- if(tileType == 1 && height < m_tiles.regions[1].optimalHeight)
- return 1.0f;
- }
- else if(m_tiles.texTiles[2].image)
- {
- if(tileType == 2 && height < m_tiles.regions[2].optimalHeight)
- return 1.0f;
- }
- else if(m_tiles.texTiles[3].image)
- {
- if(tileType == 3 && height < m_tiles.regions[3].optimalHeight)
- return 1.0f;
- }
- // If the height we are testing is below or above the choose tile type then we return 0.
- if(height < m_tiles.regions[tileType].lowHeight)
- return 0.0f;
- else if(height > m_tiles.regions[tileType].highHeight)
- return 0.0f;
- // If the height is below the optimal height
- if(height < m_tiles.regions[tileType].optimalHeight)
- {
- // Get the distance between the m_tiles lowest height and the test height.
- distance1 = (float)(height - m_tiles.regions[tileType].lowHeight);
- // Get the distance between the optimal height and the lowest height.
- distance2 = (float)(m_tiles.regions[tileType].optimalHeight -
- m_tiles.regions[tileType].lowHeight);
- // return the percent.
- return (distance1 / distance2);
- }
- else if(height == m_tiles.regions[tileType].optimalHeight)
- {
- // Else if the height equals the optimal height we send in full color.
- return 1.0f;
- }
- else if(height > m_tiles.regions[tileType].optimalHeight)
- {
- // Else if the height is greater than the optimal height.
- // Get the distance between the max height from the optimal height.
- distance1 = (float)(m_tiles.regions[tileType].highHeight -
- m_tiles.regions[tileType].optimalHeight);
- // Return the distance - the test height -
- // optimal height / by the distance to get %.
- return((distance1 - (height -
- m_tiles.regions[tileType].optimalHeight)) / distance1);
- }
- // Return 0 if we get here.
- return 0.0f;
- }
- void CTerrain::GetTexCoords(unsigned int texWidth, unsigned int texHeight,
- unsigned int x, unsigned int z, float &tu, float &tv)
- {
- // These two will store the amount of times the texture
- // repeats across the terrain along the x and z.
- int totalWidthRepeats = -1;
- int totalHeightRepeats = -1;
- // Temp number to hold temp values.
- int i = 0;
- // Calculate the amount of times this image would repeat across the x.
- while(totalWidthRepeats == -1)
- {
- i++;
- // We test if this point (x value) is less than the width times i.
- // If x is 156 and the image width is 256 then it will not repeat.
- // If x is 512 and the image width is 256 then the image will repeat
- // at least 1 time.
- if(x < (texWidth * i)) totalWidthRepeats = i - 1;
- }
- // Reset.
- i = 0;
- // Calculate the amount of times this image would repeat across the z.
- while(totalHeightRepeats == -1)
- {
- i++;
- // Same as with the x.
- if(z < (texHeight * i)) totalHeightRepeats = i - 1;
- }
- // Calculate the final texture coordinate.
- tu = (float)(x - (texWidth * totalWidthRepeats));
- tv = (float)(z - (texHeight * totalHeightRepeats));
- }
- float CTerrain::InterpolateDataHeight(int x, int z, float textureMapRatio)
- {
- float low = 0, high = 0;
- float interpolatedX = 0.0f, interpolatedZ = 0.0f;
- float interpolation = 0.0f;
- float scaledX = x * textureMapRatio;
- float scaledZ = z * textureMapRatio;
- // Set low as the height of this point.
- low = GetDataHeight((int)scaledX, (int)scaledZ);
- // Set the high value. If scaled x + 1 is greater than the entire size of the map then
- // we send the low to return as default. Else we grab the high x.
- // This way we don't go out of bounds in the array.
- if((scaledX + 1) > side)
- return low;
- else
- high = GetDataHeight((int)scaledX + 1, (int)scaledZ);
- // Set the interpolation to be the remainder of scaled x - itself.
- // This will give us a value between 0 and 0.99. Then we interpolate
- // the high and low.
- interpolation = (scaledX - (int)scaledX);
- interpolatedX = ((high - low) * interpolation) + low;
- // Next we do the same thing for the z that we did for the x.
- if((scaledZ + 1 ) > side)
- return low;
- else
- high = GetDataHeight((int)scaledX, (int)scaledZ + 1);
- // Calculate the interpolation for z.
- interpolation = (scaledZ - (int)scaledZ);
- interpolatedZ = ((high - low) * interpolation) + low;
- // Average out the interpolation for the x and z.
- return (interpolatedX + interpolatedZ) / 2;
- }
- float CTerrain::InterpolateHeight(int x, int z, float textureMapRatio)
- {
- float low = 0, high = 0;
- float interpolatedX = 0.0f, interpolatedZ = 0.0f;
- float interpolation = 0.0f;
- float scaledX = x * textureMapRatio;
- float scaledZ = z * textureMapRatio;
- // Set low as the height of this point.
- low = GetHeight((int)scaledX, (int)scaledZ);
- // Set the high value. If scaled x + 1 is greater than the entire size of the map then
- // we send the low to return as default. Else we grab the high x.
- // This way we don't go out of bounds in the array.
- if((scaledX + 1) > side)
- return low;
- else
- high = GetHeight((int)scaledX + 1, (int)scaledZ);
- // Set the interpolation to be the remainder of scaled x - itself.
- // This will give us a value between 0 and 0.99. Then we interpolate
- // the high and low.
- interpolation = (scaledX - (int)scaledX);
- interpolatedX = ((high - low) * interpolation) + low;
- // Next we do the same thing for the z that we did for the x.
- if((scaledZ + 1 ) > side)
- return low;
- else
- high = GetHeight((int)scaledX, (int)scaledZ + 1);
- // Calculate the interpolation for z.
- interpolation = (scaledZ - (int)scaledZ);
- interpolatedZ = ((high - low) * interpolation) + low;
- // Average out the interpolation for the x and z.
- return (interpolatedX + interpolatedZ) / 2;
- }
- unsigned char *CTerrain::GenerateTextureMap(unsigned int imageSize)
- {
- // Red, green, and blue color values. OpenGL texture id.
- unsigned char red = 0, green = 0, blue = 0;
- // Set of texture coords and last height which is used in combining the images.
- float tu, tv;
- int lastHeight = 1;
- // Each of these hold the total color values of each used in the final image.
- float totalRed = 0, totalGreen = 0, totalBlue = 0;
-
- // Blend amounts for each texture tile and the ratio between the terrain size and image size.
- float blendList[4] = {0};
- float textureMapRatio = (float)side / (float)imageSize;
- // Reset the number of m_tiles.
- m_tiles.numTiles = 0;
- // First we loop through the max amount of m_tiles we can have and see how many actually
- // have images. This way the user does not have to have a set number of images before
- // we can generate a texture. Need just at least 1 to see anything.
- for(int i = 0; i < 4; i++)
- {
- if(m_tiles.texTiles[i].image) m_tiles.numTiles++;
- }
- if(m_tiles.numTiles == 0) return NULL;
- // Loop through again to calculate the tile regions.
- for(int i = 0; i < 4; i++)
- {
- // If the image was loaded, perform calculations.
- if(m_tiles.texTiles[i].image)
- {
- // Here we calculate the low, optimal, and high height for this region.
- m_tiles.regions[i].lowHeight = lastHeight + 1;
-
- lastHeight += (int)(GetMaxHeight() / m_tiles.numTiles);
- m_tiles.regions[i].optimalHeight = lastHeight;
- m_tiles.regions[i].highHeight = (lastHeight -
- m_tiles.regions[i].lowHeight) + lastHeight;
- }
- }
- // Create the texture array.
- unsigned char *image = new unsigned char[imageSize * imageSize * 3];
- // And the last part in the generation is to create the 2D image.
- for(unsigned int z = 0; z < imageSize; z++)
- {
- for(unsigned int x = 0; x < imageSize; x++)
- {
- // Intialize the color variables.
- totalRed = 0.0f;
- totalGreen = 0.0f;
- totalBlue = 0.0f;
- // Loop through all tiles and generate each final pixel color.
- for(int i = 0; i < m_tiles.numTiles; i++)
- {
- // Calculate the texture coords. This is used to
- // get a pixel from each tile.
- GetTexCoords(m_tiles.texTiles[i].width,
- m_tiles.texTiles[i].height, x, z,
- tu, tv);
- // Get the color of the pixel for the set of texture coords.
- int index = (((unsigned int)tv * imageSize) + (unsigned int)tu) * 3;
- red = m_tiles.texTiles[i].image[index + 0];
- green = m_tiles.texTiles[i].image[index + 1];
- blue = m_tiles.texTiles[i].image[index + 2];
- // Calculate the amount to blend this pixel with the rest.
-
- blendList[i] = RegionPercent(i, InterpolateDataHeight(x, z, textureMapRatio));
- // Store the pixel from this tile to the total.
- totalRed += red * blendList[i];
- totalGreen += green * blendList[i];
- totalBlue += blue * blendList[i];
- }
- // Set a pixel in our final texture image.
- image[((z * imageSize) + x) * 3] = (unsigned char)totalRed;
- image[((z * imageSize) + x) * 3 + 1] = (unsigned char)totalGreen;
- image[((z * imageSize) + x) * 3 + 2] = (unsigned char)totalBlue;
- }
- }
- return image;
- }
- void CTerrain::ShutDown()
- {
- // Release all resources used by the terrain.
- fScale = 0.0f;
- delete[] m_tiles.texTiles[0].image;
- delete[] m_tiles.texTiles[1].image;
- delete[] m_tiles.texTiles[2].image;
- delete[] m_tiles.texTiles[3].image;
-
- if(pVertex)
- {
- delete[] pVertex;
- pVertex = NULL;
- }
- if(pTexCoords)
- {
- delete[] pTexCoords;
- pTexCoords = NULL;
- }
- if(pTexCoords2)
- {
- delete[] pTexCoords2;
- pTexCoords2 = NULL;
- }
- if(hMap)
- {
- delete[] hMap;
- side = 0;
- }
- }
- float CTerrain::GetMaxHeight()
- {
- float max = 0;
- for (int x=0 ; x < side ; x++)
- {
- for (int z=0 ; z < side ; z++)
- {
- if (max < GetHeight(x, z)) max = GetHeight(x, z);
- }
- }
- return max;
- }
- float CTerrain::GetMinHeight()
- {
- float min = 0;
- for (int x=0 ; x < side ; x++)
- {
- for (int z=0 ; z < side ; z++)
- {
- if (min > GetHeight(x, z)) min = GetHeight(x, z);
- }
- }
- return min;
- }
- float *CTerrain::GetTriangle(float x, float z)
- {
- int tri_index = (int)z * (side_)*2 + (int)x * 2;
- if (mod(x)+mod(z) > 1) tri_index++;
- return &pVertex[tri_index*9];
- }
- float CTerrain::GetHeight(int x, int z)
- {
- bool xmax, zmax;
- xmax = (x == side_);
- zmax = (z == side_);
- if (xmax && zmax)
- return GetVertex(x-1, z-1, 4);
- if (xmax)
- return GetVertex(x-1, z, 3);
- if (zmax)
- return GetVertex(x, z-1, 5);
- return GetVertex(x, z, 0); // default index is zero
- }
- void CTerrain::AddToHeight(int x, int z, float add)
- {
- float set = GetHeight(x, z);
- SetHeight(x, z, set+add);
- }
- void CTerrain::SetHeight(int x, int z, float set)
- { /* |34| x
- |25| |
- |01| +->z */
- SetVertex(x, z, 0, set);
- SetVertex(x-1, z, 2, set);
- SetVertex(x-1, z, 3, set);
- SetVertex(x, z-1, 1, set);
- SetVertex(x, z-1, 5, set);
- SetVertex(x-1, z-1, 4, set);
- }
- int CTerrain::ConvertToI(int x, int z, int index)
- { /* |34| x
- |25| |
- |01| +->z */
- if (x < 0 || x > side-2) return 0;
- if (z < 0 || z > side-2) return 0;
-
- int i = z*(side_)*2 + x*2; // set to triangle index
- i *= 9; // convert to index of first float in triangle
- i += index*3 + 1; // go to requested point and add one for y-coord
- if (i < 0 || i > (18*(side_)*(side_)))
- return 0; // if it is negative, or greater than MAX
- return i;
- }
- void CTerrain::SetVertex(int x, int z, int index, float set)
- {
- int i = ConvertToI(x, z, index);
- if (i == 0) return;
- pVertex[i] = set;
- }
- float CTerrain::GetVertex(int x, int z, int index)
- {
- int i = ConvertToI(x, z, index);
- if (i == 0) return 0; // so zero should never be used on terrain
- return pVertex[i];
- }
- void CTerrain::AddToVertex(int x, int z, int index, float add)
- {
- SetVertex(x, z, index, GetVertex(x, z, index)+add);
- }
- void CTerrain::CreatePlaneFromTri(float tri[9], float *plane)
- {
- CVector tri1(tri[0], tri[1], tri[2]);
- CVector tri2(tri[3], tri[4], tri[5]);
- CVector tri3(tri[6], tri[7], tri[8]);
- CVector normal;
- normal.CrossProduct(tri3 - tri1, tri2 - tri1);
- normal.Normal();
- float a, b, c, d;
- a = normal.x; b = normal.y; c = normal.z;
- d = - (a * tri1.x + b * tri1.y + c * tri1.z);
- plane[0] = a;
- plane[1] = b;
- plane[2] = c;
- plane[3] = d;
- }
- float CTerrain::GetRealHeight(float x, float z)
- {
- if (x < 0 || z < 0 || x >= side_ || z >= side_) return 0;
- float *triangle = GetTriangle(x, z);
- float plane[4]; // a b c d
- CreatePlaneFromTri(triangle, plane);
- float y = plane[0]*x + plane[2]*z + plane[3];
- if (plane[1] == 0)
- err("WTF???", "division by zero, plane D equals zero");
- else
- y /= -plane[1];
- return y;
- }
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- CTerrainData::CTerrainData()
- {
- iTexID = 0;
- glActiveTextureARB = NULL;
- glClientActiveTextureARB = NULL;
- mode = GL_TRIANGLES;
- }
- bool CTerrainData::InitExtensions()
- {
- char *extension = (char*)glGetString(GL_EXTENSIONS);
- if(strstr(extension, "GL_ARB_multitexture") == 0) return false;
- glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
- glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)wglGetProcAddress("glClientActiveTextureARB");
- if(!glActiveTextureARB || !glClientActiveTextureARB) return false;
- return true;
- }
- bool CTerrainData::LoadDetailTexture(char *detail_tex)
- {
- if(!LoadTGA(&terrDetailTex, detail_tex)) return false;
- return true;
- }
-
- bool CTerrainData::InitTextures()
- {
- unsigned char *img;
- // converts from verts (our editted stuff) into float heightmap
- terr->ConvertMesh();
- img = terr->GenerateTextureMap(256);
- glGenTextures(1, &iTexID);
- glBindTexture(GL_TEXTURE_2D, iTexID);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
- glGenTextures(1, &terrDetailTex.texID);
- glBindTexture(GL_TEXTURE_2D, terrDetailTex.texID);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, terrDetailTex.width,
- terrDetailTex.height, 0, GL_RGB, GL_UNSIGNED_BYTE, terrDetailTex.image);
- delete[] img;
- return true;
- }
- void CTerrainData::SetMode(int m)
- {
- mode = m;
- }
- void CTerrainData::RenderAll()
- {
- // Apply the textures.
- glActiveTextureARB(GL_TEXTURE0_ARB);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, iTexID);
- glActiveTextureARB(GL_TEXTURE1_ARB);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, terrDetailTex.texID);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
- glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2);
- glActiveTextureARB(GL_TEXTURE0_ARB);
- // Set pointers.
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, terr->pVertex);
- glTexCoordPointer(2, GL_FLOAT, 0, terr->pTexCoords);
- glClientActiveTextureARB(GL_TEXTURE1_ARB);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 0, terr->pTexCoords2);
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- glDrawArrays(mode, 0, terr->iVerts);
- // Disable all the client states we enabled.
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glClientActiveTextureARB(GL_TEXTURE1_ARB);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- }
- void CTerrainData::Destroy()
- {
- terr->ShutDown();
- delete[] terrDetailTex.image;
- glDeleteTextures(1, &iTexID);
- }
- bool CTerrainData::Init(CTerrain *tt)
- {
- terr = tt; // set terrain pointer
- if (!InitExtensions()) return false;
- return true;
- }
- bool CTerrainData::Generate(char *map, int detail, char *t0, char *t1, char *t2, char *t3, char *detail_tex)
- {
- if (terr == NULL) err("null");
- terr->LoadMap(map, detail);
- terr->LoadTile(0, t0);
- terr->LoadTile(1, t1);
- terr->LoadTile(2, t2);
- terr->LoadTile(3, t3);
- if (!LoadDetailTexture(detail_tex)) return false;
- if (!InitTextures()) return false;
- return true;
- }
- bool CTerrain::LoadTile(int tileType, char *filename)
- {
- return LoadTGA(&m_tiles.texTiles[tileType], filename);
- }
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- /*******************************************************************************
- * CTerrainEdit
- *******************************************************************************/
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- void CTerrainEdit::Zero()
- {
- for (int x=0 ; x < t->side ; x++)
- {
- for (int z=0 ; z < t->side ; z++)
- {
- t->SetHeight(x, z, 0);
- }
- }
- }
- void CTerrainEdit::Normalize(float scale)
- {
- float max = t->GetMaxHeight();
- float min = t->GetMinHeight();
- float range = max-min;
- if (range == 0) range = 0.001;
- float mm;
- for (int x=0 ; x < t->side ; x++)
- {
- for (int z=0 ; z < t->side ; z++)
- {
- mm = t->GetHeight(x, z);
- t->SetHeight(x, z, scale * mm / range);
- }
- }
- }
- void CTerrainEdit::Increase(float power)
- {
- float mm;
- for (int x=0 ; x < t->side ; x++)
- {
- for (int z=0 ; z < t->side ; z++)
- {
- mm = t->GetHeight(x, z);
- t->SetHeight(x, z, mm+power);
- }
- }
- }
- void CTerrainEdit::Flatten(float power)
- {
- float mm;
- for (int x=0 ; x < t->side ; x++)
- {
- for (int z=0 ; z < t->side ; z++)
- {
- mm = t->GetHeight(x, z);
- t->SetHeight(x, z, pow(mm, power));
- }
- }
- }
- void CTerrainEdit::Multiply(float m)
- {
- float mm;
- for (int x=0 ; x < t->side ; x++)
- {
- for (int z=0 ; z < t->side ; z++)
- {
- mm = t->GetHeight(x, z);
- t->SetHeight(x, z, mm*m);
- }
- }
- }
- void CTerrainEdit::DoHill(int x, int z, int radius, float power)
- {
- for (int xr=-radius ; xr <= radius ; xr++)
- {
- for (int zr=-radius ; zr <= radius ; zr++)
- {
- float change = radius - sqrt(xr*xr + zr*zr);
- if (change < 0) change = 0;
- change *= power;
- t->AddToHeight(x+xr, z+zr, change);
- }
- }
- }
- void CTerrainEdit::CreateHill(int x, int y, int radius, int iters, float power)
- {
- for (int j=0 ; j < iters ; j++)
- {
- DoHill(x, y, radius, power);
- }
- }
- void CTerrainEdit::GenerateIsland(int width_x, int width_z, int x_pos, int y_pos, int iters, int max_radius, int max_iters)
- {
- for (int i=0 ; i < iters ; i++)
- {
- int height = rand() % max_iters;
- int radius = rand() % max_radius;
- int x = rand() % width_x + x_pos - width_x/2;
- int y = rand() % width_z + y_pos - width_z/2;
- CreateHill(x, y, radius, height);
- }
- }
- void CTerrainEdit::GenerateTerrain(int iters, int max_radius, int max_iters)
- {
- for (int i=0 ; i < iters ; i++)
- {
- int height = rand() % max_iters;
- int radius = rand() % max_radius;
- int x = (rand()%(t->side*2))-t->side;
- int y = (rand()%(t->side*2))-t->side;
- CreateHill(x, y, radius, iters, 0.1);
- }
- }