Fixed normal calculation at edges, more UI changes
[ted.git] / qsrc / terraindisplay.cpp
blob387c45596c823d31b514cbf47ffccd8ed4dca3ff
1 #include "terraindisplay.h"
3 #include <QtGui/QMessageBox>
4 #include <QtGui/QMouseEvent>
5 //#include <QtScript/QScriptEngine>
6 //#include <QtCore/QDebug>
8 #include <iostream>
10 #include <GL/gl.h>
11 #include <math.h>
12 #include <stdlib.h>
13 #include <time.h>
15 #define DEFAULT_SIZE 64
17 TerrainDisplay::TerrainDisplay(QWidget *parent) : QGLWidget(parent)
19 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
21 m_mesh = terrain_create(DEFAULT_SIZE);
23 setZoom(10.0);
25 m_mouseSensitivity = 0.5;
27 setXRotation(45.0);
28 setYRotation(45.0);
29 emit zRotationChanged(0.0); // to fill in the UI
31 makeCurrent();
33 setSize(DEFAULT_SIZE);
34 setSeed(time(0));
35 setMagnitude(DEFAULT_SIZE);
36 setRoughness(0.65);
37 zoomFit();
40 TerrainDisplay::~TerrainDisplay()
42 makeCurrent();
43 terrain_destroy(m_mesh);
46 QSize TerrainDisplay::minimumSizeHint() const
48 return QSize(64, 64);
51 QSize TerrainDisplay::sizeHint() const
53 return QSize(320, 320);
56 void TerrainDisplay::initializeGL()
58 glClearColor(0.0, 0.0, 0.0, 0.0);
60 glEnable(GL_DEPTH_TEST);
61 glEnable(GL_NORMALIZE);
62 glEnable(GL_CULL_FACE);
63 glFrontFace(GL_CW);
65 glEnable(GL_DEPTH_TEST);
66 glEnable(GL_CULL_FACE);
67 glFrontFace(GL_CW);
69 glShadeModel(GL_SMOOTH);
71 glEnable(GL_LIGHTING);
72 glEnable(GL_LIGHT0);
75 float position[] = { 10.0f, 10.0f, 10.0f, 1.0f };
76 glLightfv(GL_LIGHT0, GL_POSITION, position);
78 float specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
79 glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
81 float ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
82 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
84 float diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
85 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
87 glEnable(GL_COLOR_MATERIAL);
88 glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
90 glMaterialf(GL_FRONT, GL_SHININESS, 128);
91 glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
95 void TerrainDisplay::resizeGL(int w, int h)
97 float ratio = (float)w/h;
98 float scale = 10.0;
100 glViewport(0, 0, w, h);
102 glMatrixMode(GL_PROJECTION);
103 glLoadIdentity();
104 glOrtho(-scale*ratio, scale*ratio, -scale, scale, -1000.0, 1000.0);
105 glMatrixMode(GL_MODELVIEW);
108 void TerrainDisplay::paintGL()
110 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
111 glLoadIdentity();
112 glTranslatef(0.0, 0.0, -10.0);
113 glRotated(m_rot[0], 1.0, 0.0, 0.0);
114 glRotated(m_rot[1], 0.0, 1.0, 0.0);
115 glRotated(m_rot[2], 0.0, 0.0, 1.0);
117 glScalef(m_zoom, m_zoom, m_zoom);
118 glColor3f(1.0, 1.0, 1.0);
119 terrain_draw(m_mesh);
121 glPushMatrix();
123 glScalef(1.0/m_zoom, 1.0/m_zoom, 1.0/m_zoom);
125 glDisable(GL_LIGHTING);
126 glDisable(GL_DEPTH_TEST);
128 glBegin(GL_LINES);
130 glColor3f(1.0, 0.0, 0.0); // x
131 glVertex3f(0.0, 0.0, 0.0);
132 glVertex3f(1.0, 0.0, 0.0);
134 glColor3f(0.0, 1.0, 0.0); // y
135 glVertex3f(0.0, 0.0, 0.0);
136 glVertex3f(0.0, 1.0, 0.0);
138 glColor3f(0.0, 0.0, 1.0); // z
139 glVertex3f(0.0, 0.0, 0.0);
140 glVertex3f(0.0, 0.0, 1.0);
142 glEnd();
144 glEnable(GL_DEPTH_TEST);
145 glEnable(GL_LIGHTING);
147 glPopMatrix();
150 void TerrainDisplay::mousePressEvent(QMouseEvent *event)
152 m_lastPos = event->pos();
155 void TerrainDisplay::mouseMoveEvent(QMouseEvent *event)
157 int dx = event->x() - m_lastPos.x();
158 int dy = event->y() - m_lastPos.y();
160 if (event->buttons() & Qt::LeftButton)
162 setXRotation(getXRotation() + m_mouseSensitivity * dy);
163 setYRotation(getYRotation() + m_mouseSensitivity * dx);
165 else if (event->buttons() & Qt::RightButton)
167 setZoom(getZoom() + m_mouseSensitivity/100.0 * dy * getZoom());
169 else if (event->buttons() & Qt::MidButton)
171 makeCurrent();
172 makeFractal();
173 updateGL();
176 m_lastPos = event->pos();
179 void TerrainDisplay::zoomFit()
181 setZoom(10.0/getSize());
185 void TerrainDisplay::setZoom(double amount)
187 if (amount != m_zoom && amount > 0.0)
189 m_zoom = amount;
190 emit zoomChanged(amount);
191 updateGL();
195 void normalizeAngle(double *angle)
197 //int adj = *angle/360;
198 //*angle -= adj*360;
201 void TerrainDisplay::setXRotation(double angle)
203 normalizeAngle(&angle);
204 if (angle != m_rot[0])
206 m_rot[0] = angle;
207 emit xRotationChanged(angle);
208 updateGL();
212 void TerrainDisplay::setYRotation(double angle)
214 normalizeAngle(&angle);
215 if (angle != m_rot[1])
217 m_rot[1] = angle;
218 emit yRotationChanged(angle);
219 updateGL();
223 void TerrainDisplay::setZRotation(double angle)
225 normalizeAngle(&angle);
226 if (angle != m_rot[2])
228 m_rot[2] = angle;
229 emit zRotationChanged(angle);
230 updateGL();
234 void TerrainDisplay::setRoughness(double rough)
236 if (rough != m_roughness)
238 m_roughness = rough;
239 emit roughnessChanged(rough);
240 makeFractal();
241 updateGL();
245 void TerrainDisplay::setMagnitude(double mag)
247 if (mag != m_magnitude)
249 m_magnitude = mag;
250 emit magnitudeChanged(mag);
251 makeFractal();
252 updateGL();
256 void TerrainDisplay::setSize(int size)
258 if (size != m_mesh->size)
260 TERRAIN_MODE m = m_mesh->drawmode;
261 terrain_destroy(m_mesh);
262 m_mesh = terrain_create(size);
263 m_mesh->drawmode = m;
264 makeFractal();
265 emit sizeChanged(size);
266 zoomFit();
267 updateGL();
271 void TerrainDisplay::setDrawMode(int mode)
273 switch(mode)
275 case 0:
276 m_mesh->drawmode = FLAT;
277 m_mesh->dirty = 1;
278 break;
279 case 1:
280 m_mesh->drawmode = NORMAL;
281 m_mesh->dirty = 1;
282 break;
283 case 2:
284 m_mesh->drawmode = NORMAL_DEBUG;
285 m_mesh->dirty = 1;
286 break;
287 default:
288 break;
290 updateGL();
293 void TerrainDisplay::setSeed(int seed)
295 if ((unsigned int)seed != m_mesh->seed)
297 m_mesh->seed = seed;
298 makeFractal();
299 emit seedChanged(seed);
300 updateGL();
304 void TerrainDisplay::makeFractal()
306 terrain_clear(m_mesh);
307 terrain_fractal(m_mesh, m_magnitude);
308 terrain_smooth(m_mesh, m_roughness);
309 terrain_bake(m_mesh);