00001
00002
00003 #include "Terrain.h"
00004
00005
00006 #include "Image.h"
00007 #include "MathUtils.h"
00008 #include "SingleTexturedMesh.h"
00009 #include "Texture.h"
00010 #include "TextureDatabase.h"
00011 #include "Triangle.h"
00012
00013
00014 namespace pge {
00015
00016
00017
00018
00019
00020
00021
00022 HeightmapLoader::HeightmapLoader(const std::string &file) {
00023 loadHeightmap(file);
00024 }
00025
00026
00027
00028
00029
00030
00031
00032 HeightmapLoader::~HeightmapLoader(void) {
00033 }
00034
00035
00036
00037
00038
00039
00040
00041 bool HeightmapLoader::loadHeightmap(const std::string &file) {
00042 m_heightmap = new Image(file);
00043
00044 if(m_heightmap->getType() == Image::RGBA) {
00045 printf("INFO: [%s] Heightmap type: RGBA\n", __FILE__);
00046 }
00047
00048 return m_heightmap->isLoaded();
00049 }
00050
00051
00052
00053
00054
00055
00056
00057 Vector3f* HeightmapLoader::generateTerrain(Vector3f startCorner, float mapScale,
00058 int vertexNumX, int vertexNumZ, float terrainWidth, float terrainDepth) {
00059
00060 int x;
00061 int z;
00062 float spaceX;
00063 float spaceZ;
00064 float dataY;
00065 float y;
00066 int mX;
00067 int mZ;
00068 Vector3f *vertices = new Vector3f[vertexNumX * vertexNumZ];
00069 unsigned char *buffer;
00070 int heightmapWidth = m_heightmap->getWidth();
00071 int heightmapHeight = m_heightmap->getHeight();
00072 int index;
00073
00074
00075 spaceX = terrainWidth / vertexNumX;
00076 spaceZ = terrainDepth / vertexNumZ;
00077
00078 buffer = m_heightmap->getImage();
00079
00080 index = 0;
00081
00082 for (z = 0; z < vertexNumZ; z++) {
00083 for (x = 0; x < vertexNumX; x++) {
00084
00085 mX = (int)mathutils::mapValueToInterval(0.0f, (float)vertexNumX, 0.0f, (float)heightmapWidth, (float)x);
00086 mZ = (int)mathutils::mapValueToInterval(0.0f, (float)vertexNumZ, 0.0f, (float)heightmapHeight, (float)z);
00087
00088 dataY = (float)buffer[((mZ * heightmapHeight) + mX) * 4];
00089
00090 y = startCorner.m_v[1] + dataY * mapScale;
00091
00092 vertices[index] = Vector3f(startCorner.m_v[0] + (x * spaceX), y, startCorner.m_v[2] + (z * spaceZ));
00093 index++;
00094 }
00095 }
00096 return vertices;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105 Terrain::Terrain(const std::string &heightmapFile, const std::string &textureFile,
00106 Vector3f startCorner, float mapScale, int vertexNumX, int vertexNumZ,
00107 float terrainWidth, float terrainDepth) {
00108
00109 HeightmapLoader *loader = new HeightmapLoader(heightmapFile);
00110
00111
00112 m_texture = TextureDatabase::getInstance()->addTexture(textureFile);
00113
00114
00115 createTerrain(loader->generateTerrain(startCorner, mapScale, vertexNumX, vertexNumZ,
00116 terrainWidth, terrainDepth), vertexNumX, vertexNumZ);
00117
00118
00119 buildBoundingBox();
00120 }
00121
00122
00123
00124
00125
00126
00127
00128 Terrain::~Terrain(void) {
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 void Terrain::createTerrain(Vector3f *vertices, int vertexNumX, int vertexNumZ) {
00138 int x;
00139 int z;
00140 int numTriangles;
00141 float textureRepeatU = 20.0f;
00142 float textureRepeatV = 20.0f;
00143 float texPerCentU = textureRepeatU / (float) vertexNumX;
00144 float texPerCentV = textureRepeatV / (float) vertexNumX;
00145 SingleTexturedMesh *mesh = new SingleTexturedMesh();
00146
00147
00148 mesh->setTexture(m_texture);
00149
00150 numTriangles = 0;
00151 for(z = 0; z < vertexNumZ - 1; z++) {
00152 for(x = 0; x < vertexNumX - 1; x++) {
00153
00154 Vector3f v0 = vertices[(z * vertexNumX) + x];
00155 Vector3f v1 = vertices[((z + 1) * vertexNumX) + x];
00156 Vector3f v2 = vertices[(z * vertexNumX) + (x + 1)];
00157 Vector3f v3 = vertices[((z + 1) * vertexNumX) + (x + 1)];
00158
00159 Triangle triangle0;
00160 Triangle triangle1;
00161
00162 triangle0.m_vertices[0] = v0;
00163 triangle0.m_vertices[1] = v1;
00164 triangle0.m_vertices[2] = v2;
00165 triangle0.m_texCoords[0] = Vector2f(x * texPerCentU, z * texPerCentV);
00166 triangle0.m_texCoords[1] = Vector2f(x * texPerCentU, (z + 1) * texPerCentV);
00167 triangle0.m_texCoords[2] = Vector2f((x + 1) * texPerCentU, z * texPerCentV);
00168
00169 triangle1.m_vertices[0] = v2;
00170 triangle1.m_vertices[1] = v1;
00171 triangle1.m_vertices[2] = v3;
00172 triangle1.m_texCoords[0] = Vector2f((x + 1) * texPerCentU, z * texPerCentV);
00173 triangle1.m_texCoords[1] = Vector2f(x * texPerCentU, (z + 1) * texPerCentV);
00174 triangle1.m_texCoords[2] = Vector2f((x + 1) * texPerCentU, (z + 1) * texPerCentV);
00175
00176
00177 triangle0.m_plane = new Plane(v0, v1, v2);
00178 triangle1.m_plane = new Plane(v2, v1, v3);
00179
00180 mesh->addTriangle(triangle0);
00181 mesh->addTriangle(triangle1);
00182 numTriangles += 2;
00183
00184 if(numTriangles >= 1000000) {
00185 addMesh(mesh);
00186 mesh = NULL;
00187 mesh = new SingleTexturedMesh();
00188 mesh->setTexture(m_texture);
00189 numTriangles = 0;
00190 }
00191 }
00192 }
00193
00194 if(numTriangles > 0) {
00195 addMesh(mesh);
00196 }
00197 }
00198 };