Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <fstream>
- #include <iostream>
- #include <sstream>
- #include <stdlib.h>
- #include <vector>
- #include <gl/glut.h> // windows
- #include "ImageLoader.h"
- #include "vec3f.h"
- using namespace std;
- int a = 128;
- // Terrain
- class Terrain
- {
- private:
- int _width;
- int _length;
- float** heights;
- Vec3f** normals;
- bool computedNormals;
- public:
- Terrain(int width2, int height2)
- {
- _width = width2;
- _length = height2;
- heights = new float*[_length];
- for(int i = 0; i < _length; i++)
- heights[i] = new float[_width];
- normals = new Vec3f*[_length];
- for(int i = 0; i < _length; i++)
- normals[i] = new Vec3f[_width];
- computedNormals = false;
- }
- ~Terrain()
- {
- for(int i = 0; i < _length; i++)
- delete[] heights[i];
- delete[] heights;
- for(int i = 0; i < _length; i++)
- delete[] normals[i];
- delete[] normals;
- }
- int width() { return _width; }
- int length() { return _length; }
- void setHeight(int x, int z, float y)
- {
- heights[z][x] = y;
- computedNormals = true;
- }
- float getHeight(int x, int z) { return heights[z][x]; }
- void computeNormals()
- {
- if(computedNormals)
- return;
- Vec3f** normals2 = new Vec3f*[_length];
- for(int i = 0; i < _length; i++)
- normals2[i] = new Vec3f[_width];
- for(int z = 0; z < _length; z++)
- {
- for(int x = 0; x < _width; x++)
- {
- Vec3f sun(0.0f, 0.0f, 0.0f);
- Vec3f out;
- Vec3f in;
- Vec3f left;
- Vec3f right;
- if(z > 0)
- out = Vec3f(0.0f, heights[z - 1][x] - heights[z][x], -1.0f);
- if(z < _length - 1)
- in = Vec3f(0.0f, heights[z + 1][x] - heights[z][x], 1.0f);
- if(x > 0)
- left = Vec3f(-1.0f, heights[z][x - 1] - heights[z][x], 0.0f);
- if(x > 0 && z > 0)
- sun += out.cross(left).normalize();
- if(x > 0 && z < _length - 1)
- sun += left.cross(in).normalize();
- if(x < _width - 1 && z < _length - 1)
- sun += in.cross(right).normalize();
- if(x < _width - 1 && z > 0)
- sun += right.cross(out).normalize();
- normals2[z][x] = sun;
- }
- }
- const float FALLOUT_RATIO = 0.5f;
- for(int z = 0; z < _length; z++)
- {
- for(int x = 0; x < _width; x++)
- {
- Vec3f sun = normals2[z][x];
- if(x > 0)
- sun += normals2[z][x - 1] * FALLOUT_RATIO;
- if(x < _width - 1)
- sun += normals2[z][x + 1] * FALLOUT_RATIO;
- if(z > 0)
- sun += normals2[z - 1][x] * FALLOUT_RATIO;
- if(z < 0)
- sun += normals2[z + 1][x] * FALLOUT_RATIO;
- if(sun.magnitude() == 0)
- sun = Vec3f(0.0f, 1.0f, 0.0f);
- normals[z][x] = sun;
- }
- }
- for(int i = 0; i < _length; i++)
- delete[] normals2[_length];
- delete[] normals2;
- computedNormals = true;
- }
- Vec3f getNormal(int x, int z)
- {
- if(!computedNormals)
- computeNormals();
- return normals[z][x];
- }
- };
- Terrain* loadTerrain(const char* fileName, float height)
- {
- Bitmap* image = new Bitmap();
- image->loadBMP(fileName);
- Terrain* t = new Terrain(image->width, image->height);
- for(int y = 0; y < image->height; y++)
- {
- for(int x = 0; x < image->width; x++)
- {
- unsigned char color = (unsigned char)image->data[3 * (y * image->width + x)];
- float h = height * ((color / 255.0f) - 0.5f);
- t->setHeight(x, y, h);
- }
- }
- delete image;
- t->computeNormals();
- return t;
- }
- float _angle = 60.0f;
- Terrain* _terrain;
- void cleanUp() { delete _terrain; }
- void handleKeyPress(unsigned char key, int x, int y)
- {
- switch(key)
- {
- case 27:
- {
- cleanUp();
- exit(0);
- }
- break;
- }
- }
- void initRendering()
- {
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_COLOR_MATERIAL);
- glEnable(GL_LIGHTING);
- glEnable(GL_NORMALIZE);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glShadeModel(GL_SMOOTH);
- glLineWidth(2.5f);
- }
- void handleResze(int w, int h)
- {
- glViewport(0, 0, w, h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
- }
- void drawScene()
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glClearColor(0.1f, 0.2f, 1.0f, 1.0f);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.0f, 0.0f, -5.0f);
- glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
- glRotatef(-_angle, 0.0f, 1.0f, 0.0f);
- GLfloat ambientColor[] = {0.4f, 0.4f, 0.4f, 1.0f};
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
- GLfloat lightColor0[] = {0.6f, 0.6f, 0.6f, 1.0f};
- GLfloat lightPos0[] = {1.0f, 1.0f, 1.0f, 1.0f};
- glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
- glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
- float scale = 5.0f / max(_terrain->width() - 1, _terrain->length() - 1);
- glScalef(scale, scale, scale);
- glTranslatef(-(float)(_terrain->width() - 1) / 2, 0.0f, -(float)(_terrain->length() - 1) / 2);
- glColor3f(0.0f, 1.0f, 0.0f);
- for(int z = 0; z < _terrain->length() - 1; z++)
- {
- glBegin(GL_TRIANGLE_STRIP);
- for(int x = 0; x < _terrain->width(); x++)
- {
- Vec3f normal = _terrain->getNormal(x, z);
- glNormal3f(normal[0], normal[1], normal[2]);
- glVertex3f(x, _terrain->getHeight(x, z), z);
- normal = _terrain->getNormal(x, z + 1);
- glNormal3f(normal[0], normal[1], normal[2]);
- glVertex3f(x, _terrain->getHeight(x, z + 1), z + 1);
- }
- glEnd();
- }
- glutSwapBuffers();
- }
- void update(int value)
- {
- _angle += 1.0f;
- if(_angle > 360)
- _angle -= 360;
- glutPostRedisplay();
- glutTimerFunc(25, update, 0);
- }
- int main(int argc, char** argv)
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
- glutInitWindowSize(800, 600);
- glutCreateWindow("C++ - OpenGL terrain rendering");
- initRendering();
- _terrain = loadTerrain("heightmap.png", 10);
- glutDisplayFunc(drawScene);
- glutKeyboardFunc(handleKeyPress);
- glutReshapeFunc(handleResze);
- glutTimerFunc(25, update, 0);
- glutMainLoop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement