00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "simpleterrain.h"
00019
00020 #include <kgllib.h>
00021
00022 #include <QImage>
00023 #include <QColor>
00024
00025 #include <Eigen/Geometry>
00026
00027 using namespace Eigen;
00028
00029 namespace KGLLib
00030 {
00031
00032 class SimpleTerrain::Chunk
00033 {
00034
00035 };
00036
00037 SimpleTerrain::SimpleTerrain(const QString& filename) : Mesh()
00038 {
00039 mHeight = mWidth = 0;
00040 mHeightmap = 0;
00041 mNormalmap = 0;
00042 mVertices = mNormals = 0;
00043 mIndices = 0;
00044
00045 QImage img(filename);
00046 if (img.isNull()) {
00047 return;
00048 }
00049 mWidth = img.width();
00050 mHeight = img.height();
00051 mMinHeight = 0;
00052 mMaxHeight = 1;
00053 mTileSize = 1;
00054
00055 mNormalmap = 0;
00056 mIndices = 0;
00057 mVertices = 0;
00058 mNormals = 0;
00059
00060
00061 mHeightmap = new float*[mWidth];
00062 for (int x = 0; x < mWidth; x++) {
00063 mHeightmap[x] = new float[mHeight];
00064 for (int z = 0; z < mHeight; z++) {
00065 QColor c(img.pixel(x, z));
00066 mHeightmap[x][z] = c.redF()*0.30 + c.greenF()*0.60 + c.blueF()*0.10;
00067 }
00068 }
00069
00070 mDirty = true;
00071 setPrimitiveType(GL_TRIANGLE_STRIP);
00072 }
00073
00074 SimpleTerrain::~SimpleTerrain()
00075 {
00076 if (mHeightmap) {
00077 for (int x = 0; x < mWidth; x++) {
00078 delete[] mHeightmap[x];
00079 }
00080 delete[] mHeightmap;
00081 }
00082 if (mNormalmap) {
00083 for (int x = 0; x < mWidth; x++) {
00084 delete[] mNormalmap[x];
00085 }
00086 delete[] mNormalmap;
00087 }
00088 }
00089
00090 void SimpleTerrain::setHeightRange(float min, float max)
00091 {
00092 mMinHeight = min;
00093 mMaxHeight = max;
00094 setDirty();
00095 }
00096
00097 void SimpleTerrain::setTileSize(float size)
00098 {
00099 mTileSize = size;
00100 setDirty();
00101 }
00102
00103 bool SimpleTerrain::isValid() const
00104 {
00105 return mWidth != 0 && mHeight != 0;
00106 }
00107
00108 void SimpleTerrain::setDirty()
00109 {
00110 if (!mDirty) {
00111
00112 for (int x = 0; x < mWidth; x++) {
00113 delete[] mNormalmap[x];
00114 }
00115 delete[] mNormalmap;
00116 delete[] mIndices;
00117 delete[] mVertices;
00118 delete[] mNormals;
00119 }
00120 mDirty = true;
00121 }
00122
00123 void SimpleTerrain::render()
00124 {
00125 if (!isValid()) {
00126 return;
00127 }
00128 if (mDirty) {
00129 cookMesh(false);
00130 }
00131 Mesh::render();
00132 }
00133
00134 void SimpleTerrain::recalcNormalmap()
00135 {
00136 if (mNormalmap) {
00137 for (int x = 0; x < mWidth; x++) {
00138 delete[] mNormalmap[x];
00139 }
00140 delete[] mNormalmap;
00141 }
00142
00143 mNormalmap = new Vector3f*[mWidth];
00144 for (int x = 0; x < mWidth; x++) {
00145 mNormalmap[x] = new Vector3f[mHeight];
00146 for (int z = 0; z < mHeight; z++) {
00147 mNormalmap[x][z] = Vector3f(0, 0, 0);
00148 if (x > 0) {
00149 if (z > 0) {
00150 mNormalmap[x][z] += cellNormal(x, z, x, z-1, x-1, z);
00151 }
00152 if (z+1 < mHeight) {
00153 mNormalmap[x][z] += cellNormal(x, z, x-1, z, x, z+1);
00154 }
00155 }
00156 if (x+1 < mWidth) {
00157 if (z > 0) {
00158 mNormalmap[x][z] += cellNormal(x, z, x+1, z, x, z-1);
00159 }
00160 if (z+1 < mHeight) {
00161 mNormalmap[x][z] += cellNormal(x, z, x, z+1, x+1, z);
00162 }
00163 }
00164 mNormalmap[x][z].normalize();
00165 }
00166 }
00167 }
00168
00169 Vector3f SimpleTerrain::cellNormal(int x1, int z1, int x2, int z2, int x3, int z3)
00170 {
00171 Vector3f a(x1*mTileSize, height(x1, z1), z1*mTileSize);
00172 Vector3f b(x2*mTileSize, height(x2, z2), z2*mTileSize);
00173 Vector3f c(x3*mTileSize, height(x3, z3), z3*mTileSize);
00174 return (c - b).cross(a - b).normalized();
00175 }
00176
00177 void SimpleTerrain::cookMesh(bool useIndices)
00178 {
00179 if (!isValid()) {
00180 return;
00181 }
00182
00183 mDirty = false;
00184 recalcNormalmap();
00185
00186 delete[] mVertices;
00187 delete[] mNormals;
00188 delete[] mIndices;
00189
00190 int vcount = mWidth * mHeight;
00191 int icount = (mWidth-1) * (2 + 2*mHeight);
00192
00193 if (useIndices) {
00194 mIndices = new unsigned int[icount];
00195 } else {
00196 vcount = icount;
00197 }
00198
00199 mVertices = new Vector3f[vcount];
00200 mNormals = new Vector3f[vcount];
00201 int index = 0;
00202
00203 if (!useIndices) {
00204 for (int x = 1; x < mWidth; x++) {
00205 addVertex(x-1, 0, index++);
00206 for (int z = 0; z < mHeight; z++) {
00207 addVertex(x-1, z, index++);
00208 addVertex(x , z, index++);
00209 }
00210 addVertex(x, mHeight-1, index++);
00211 }
00212 } else {
00213 for (int x = 0; x < mWidth; x++) {
00214 for (int z = 0; z < mHeight; z++) {
00215 addVertex(x , z , index++);
00216 }
00217 }
00218 index = 0;
00219 for (int x = 1; x < mWidth; x++) {
00220 mIndices[index++] = (x-1)*mHeight + 0;
00221 for (int z = 0; z < mHeight; z++) {
00222 mIndices[index++] = (x-1)*mHeight + z;
00223 mIndices[index++] = (x )*mHeight + z;
00224 }
00225 mIndices[index++] = (x )*mHeight + mHeight-1;
00226 }
00227 }
00228
00229 setVertexCount(vcount);
00230 setVertices(mVertices);
00231 setNormals(mNormals);
00232 if (useIndices) {
00233 setIndices(mIndices, icount);
00234 }
00235 }
00236
00237 void SimpleTerrain::addVertex(int x, int z, int index)
00238 {
00239 mNormals[index] = mNormalmap[x][z];
00240 mVertices[index] = Vector3f(x*mTileSize, height(x, z), z*mTileSize);
00241 }
00242
00243 }