• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KGLLib

simpleterrain.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Rivo Laks <rivolaks@hot.ee>
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either 
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public 
00015  * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
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;  // Don't call setDirty() here
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         // Delete current arrays
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 }

KGLLib

Skip menu "KGLLib"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KGLLib
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal