Advertisement
Guest User

main.cpp

a guest
Nov 13th, 2011
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.56 KB | None | 0 0
  1. /* Permission is hereby granted, free of charge, to any person obtaining a copy
  2.  * of this software and associated documentation files (the "Software"), to deal
  3.  * in the Software without restriction, including without limitation the rights
  4.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  5.  * copies of the Software, and to permit persons to whom the Software is
  6.  * furnished to do so, subject to the following conditions:
  7.  *
  8.  * The above notice and this permission notice shall be included in all copies
  9.  * or substantial portions of the Software.
  10.  *
  11.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17.  * SOFTWARE.
  18.  */
  19. /* File for "Terrain" lesson of the OpenGL tutorial on
  20.  * www.videotutorialsrock.com
  21.  */
  22.  
  23.  
  24.  
  25. #include <iostream>
  26. #include <stdlib.h>
  27.  
  28. #ifdef __APPLE__
  29. #include <OpenGL/OpenGL.h>
  30. #include <GLUT/glut.h>
  31. #else
  32. #include <GL/glut.h>
  33. #endif
  34.  
  35. #include "imageloader.h"
  36. #include "vec3f.h"
  37.  
  38. using namespace std;
  39.  
  40. //Represents a terrain, by storing a set of heights and normals at 2D locations
  41. class Terrain {
  42.     private:
  43.         int w; //Width
  44.         int l; //Length
  45.         float** hs; //Heights
  46.         Vec3f** normals;
  47.         bool computedNormals; //Whether normals is up-to-date
  48.     public:
  49.         Terrain(int w2, int l2) {
  50.             w = w2;
  51.             l = l2;
  52.            
  53.             hs = new float*[l];
  54.             for(int i = 0; i < l; i++) {
  55.                 hs[i] = new float[w];
  56.             }
  57.            
  58.             normals = new Vec3f*[l];
  59.             for(int i = 0; i < l; i++) {
  60.                 normals[i] = new Vec3f[w];
  61.             }
  62.            
  63.             computedNormals = false;
  64.         }
  65.        
  66.         ~Terrain() {
  67.             for(int i = 0; i < l; i++) {
  68.                 delete[] hs[i];
  69.             }
  70.             delete[] hs;
  71.            
  72.             for(int i = 0; i < l; i++) {
  73.                 delete[] normals[i];
  74.             }
  75.             delete[] normals;
  76.         }
  77.        
  78.         int width() {
  79.             return w;
  80.         }
  81.        
  82.         int length() {
  83.             return l;
  84.         }
  85.        
  86.         //Sets the height at (x, z) to y
  87.         void setHeight(int x, int z, float y) {
  88.             hs[z][x] = y;
  89.             computedNormals = false;
  90.         }
  91.        
  92.         //Returns the height at (x, z)
  93.         float getHeight(int x, int z) {
  94.             return hs[z][x];
  95.         }
  96.        
  97.         //Computes the normals, if they haven't been computed yet
  98.         void computeNormals() {
  99.             if (computedNormals) {
  100.                 return;
  101.             }
  102.            
  103.             //Compute the rough version of the normals
  104.             Vec3f** normals2 = new Vec3f*[l];
  105.             for(int i = 0; i < l; i++) {
  106.                 normals2[i] = new Vec3f[w];
  107.             }
  108.            
  109.             for(int z = 0; z < l; z++) {
  110.                 for(int x = 0; x < w; x++) {
  111.                     Vec3f sum(0.0f, 0.0f, 0.0f);
  112.                    
  113.                     Vec3f out;
  114.                     if (z > 0) {
  115.                         out = Vec3f(0.0f, hs[z - 1][x] - hs[z][x], -1.0f);
  116.                     }
  117.                     Vec3f in;
  118.                     if (z < l - 1) {
  119.                         in = Vec3f(0.0f, hs[z + 1][x] - hs[z][x], 1.0f);
  120.                     }
  121.                     Vec3f left;
  122.                     if (x > 0) {
  123.                         left = Vec3f(-1.0f, hs[z][x - 1] - hs[z][x], 0.0f);
  124.                     }
  125.                     Vec3f right;
  126.                     if (x < w - 1) {
  127.                         right = Vec3f(1.0f, hs[z][x + 1] - hs[z][x], 0.0f);
  128.                     }
  129.                    
  130.                     if (x > 0 && z > 0) {
  131.                         sum += out.cross(left).normalize();
  132.                     }
  133.                     if (x > 0 && z < l - 1) {
  134.                         sum += left.cross(in).normalize();
  135.                     }
  136.                     if (x < w - 1 && z < l - 1) {
  137.                         sum += in.cross(right).normalize();
  138.                     }
  139.                     if (x < w - 1 && z > 0) {
  140.                         sum += right.cross(out).normalize();
  141.                     }
  142.                    
  143.                     normals2[z][x] = sum;
  144.                 }
  145.             }
  146.            
  147.             //Smooth out the normals
  148.             const float FALLOUT_RATIO = 0.5f;
  149.             for(int z = 0; z < l; z++) {
  150.                 for(int x = 0; x < w; x++) {
  151.                     Vec3f sum = normals2[z][x];
  152.                    
  153.                     if (x > 0) {
  154.                         sum += normals2[z][x - 1] * FALLOUT_RATIO;
  155.                     }
  156.                     if (x < w - 1) {
  157.                         sum += normals2[z][x + 1] * FALLOUT_RATIO;
  158.                     }
  159.                     if (z > 0) {
  160.                         sum += normals2[z - 1][x] * FALLOUT_RATIO;
  161.                     }
  162.                     if (z < l - 1) {
  163.                         sum += normals2[z + 1][x] * FALLOUT_RATIO;
  164.                     }
  165.                    
  166.                     if (sum.magnitude() == 0) {
  167.                         sum = Vec3f(0.0f, 1.0f, 0.0f);
  168.                     }
  169.                     normals[z][x] = sum;
  170.                 }
  171.             }
  172.            
  173.             for(int i = 0; i < l; i++) {
  174.                 delete[] normals2[i];
  175.             }
  176.             delete[] normals2;
  177.            
  178.             computedNormals = true;
  179.         }
  180.        
  181.         //Returns the normal at (x, z)
  182.         Vec3f getNormal(int x, int z) {
  183.             if (!computedNormals) {
  184.                 computeNormals();
  185.             }
  186.             return normals[z][x];
  187.         }
  188. };
  189.  
  190. //Loads a terrain from a heightmap.  The heights of the terrain range from
  191. //-height / 2 to height / 2.
  192. Terrain* loadTerrain(const char* filename, float height) {
  193.     Image* image = loadBMP(filename);
  194.     Terrain* t = new Terrain(image->width, image->height);
  195.     for(int y = 0; y < image->height; y++) {
  196.         for(int x = 0; x < image->width; x++) {
  197.             unsigned char color =
  198.                 (unsigned char)image->pixels[3 * (y * image->width + x)];
  199.             float h = height * ((color / 255.0f) - 0.5f);
  200.             t->setHeight(x, y, h);
  201.         }
  202.     }
  203.    
  204.     delete image;
  205.     t->computeNormals();
  206.     return t;
  207. }
  208.  
  209. float _angle = 60.0f;
  210. Terrain* _terrain;
  211.  
  212. void cleanup() {
  213.     delete _terrain;
  214. }
  215.  
  216. void handleKeypress(unsigned char key, int x, int y) {
  217.     switch (key) {
  218.         case 27: //Escape key
  219.             cleanup();
  220.             exit(0);
  221.     }
  222. }
  223.  
  224. void initRendering() {
  225.     glEnable(GL_DEPTH_TEST);
  226.     glEnable(GL_COLOR_MATERIAL);
  227.     glEnable(GL_LIGHTING);
  228.     glEnable(GL_LIGHT0);
  229.     glEnable(GL_NORMALIZE);
  230.     glShadeModel(GL_SMOOTH);
  231. }
  232.  
  233. void handleResize(int w, int h) {
  234.     glViewport(0, 0, w, h);
  235.     glMatrixMode(GL_PROJECTION);
  236.     glLoadIdentity();
  237.     gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
  238. }
  239.  
  240. void drawScene() {
  241.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  242.    
  243.     glMatrixMode(GL_MODELVIEW);
  244.     glLoadIdentity();
  245.     glTranslatef(0.0f, 0.0f, -10.0f);
  246.     glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
  247.     glRotatef(-_angle, 0.0f, 1.0f, 0.0f);
  248.    
  249.     GLfloat ambientColor[] = {0.4f, 0.4f, 0.4f, 1.0f};
  250.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
  251.    
  252.     GLfloat lightColor0[] = {0.6f, 0.6f, 0.6f, 1.0f};
  253.     GLfloat lightPos0[] = {-0.5f, 0.8f, 0.1f, 0.0f};
  254.     glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
  255.     glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
  256.    
  257.     float scale = 5.0f / max(_terrain->width() - 1, _terrain->length() - 1);
  258.     glScalef(scale, scale, scale);
  259.     glTranslatef(-(float)(_terrain->width() - 1) / 2,
  260.                  0.0f,
  261.                  -(float)(_terrain->length() - 1) / 2);
  262.    
  263.     glColor3f(0.3f, 0.9f, 0.0f);
  264.     for(int z = 0; z < _terrain->length() - 1; z++) {
  265.         //Makes OpenGL draw a triangle at every three consecutive vertices
  266.         glBegin(GL_TRIANGLE_STRIP);
  267.         for(int x = 0; x < _terrain->width(); x++) {
  268.             Vec3f normal = _terrain->getNormal(x, z);
  269.             glNormal3f(normal[0], normal[1], normal[2]);
  270.             glVertex3f(x, _terrain->getHeight(x, z), z);
  271.             normal = _terrain->getNormal(x, z + 1);
  272.             glNormal3f(normal[0], normal[1], normal[2]);
  273.             glVertex3f(x, _terrain->getHeight(x, z + 1), z + 1);
  274.         }
  275.         glEnd();
  276.     }
  277.    
  278.     glutSwapBuffers();
  279. }
  280.  
  281. void update(int value) {
  282.     _angle += 1.0f;
  283.     if (_angle > 360) {
  284.         _angle -= 360;
  285.     }
  286.    
  287.     glutPostRedisplay();
  288.     glutTimerFunc(25, update, 0);
  289. }
  290.  
  291. int main(int argc, char** argv) {
  292.     glutInit(&argc, argv);
  293.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  294.     glutInitWindowSize(400, 400);
  295.    
  296.     glutCreateWindow("Terrain - videotutorialsrock.com");
  297.     initRendering();
  298.    
  299.     _terrain = loadTerrain("heightmap.bmp", 20);
  300.    
  301.     glutDisplayFunc(drawScene);
  302.     glutKeyboardFunc(handleKeypress);
  303.     glutReshapeFunc(handleResize);
  304.     glutTimerFunc(25, update, 0);
  305.    
  306.     glutMainLoop();
  307.     return 0;
  308. }
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement