2012-07-13 12:23:58 +00:00
|
|
|
#include "widgetheightmap.h"
|
|
|
|
|
|
|
|
#include <QTime>
|
2012-07-15 14:42:50 +00:00
|
|
|
#include <QMouseEvent>
|
2013-04-19 21:51:17 +00:00
|
|
|
#include <QWidget>
|
2012-07-13 12:23:58 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <GL/glu.h>
|
|
|
|
#include "tools.h"
|
2013-10-29 20:28:59 +00:00
|
|
|
#include "Scenery.h"
|
2012-07-13 12:23:58 +00:00
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
#define HEIGHTMAP_RESOLUTION 256
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
WidgetHeightMap::WidgetHeightMap(QWidget* parent) :
|
2013-04-27 19:41:57 +00:00
|
|
|
QGLWidget(parent)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
|
|
|
setMinimumSize(500, 500);
|
|
|
|
setFocusPolicy(Qt::StrongFocus);
|
2012-07-15 14:42:50 +00:00
|
|
|
setMouseTracking(true);
|
2012-07-16 20:34:01 +00:00
|
|
|
setCursor(Qt::CrossCursor);
|
|
|
|
startTimer(100);
|
2012-07-13 12:23:58 +00:00
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
_terrain = NULL;
|
2013-01-10 15:41:14 +00:00
|
|
|
_renderer = rendererCreate();
|
2012-12-10 22:05:53 +00:00
|
|
|
_vertices = new _VertexInfo[HEIGHTMAP_RESOLUTION * HEIGHTMAP_RESOLUTION];
|
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
_dirty = true;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-04-27 21:40:31 +00:00
|
|
|
_water = true;
|
|
|
|
_wireframe = true;
|
2013-06-20 15:38:23 +00:00
|
|
|
_painted_area = true;
|
2013-05-11 21:34:30 +00:00
|
|
|
WaterDefinition* water_definition = (WaterDefinition*)WaterDefinitionClass.create();
|
2013-04-27 21:40:31 +00:00
|
|
|
sceneryGetWater(water_definition);
|
2013-06-09 21:03:16 +00:00
|
|
|
_water_height = 0.0;
|
2013-04-27 21:40:31 +00:00
|
|
|
WaterDefinitionClass.destroy(water_definition);
|
|
|
|
|
2012-07-13 12:23:58 +00:00
|
|
|
_average_frame_time = 0.0;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-16 20:34:01 +00:00
|
|
|
_last_brush_action = 0;
|
2013-06-03 20:03:52 +00:00
|
|
|
_last_mouse_x = 250;
|
|
|
|
_last_mouse_y = 250;
|
2012-07-24 14:59:06 +00:00
|
|
|
_last_time = QDateTime::currentDateTime();
|
2012-07-23 09:58:06 +00:00
|
|
|
_mouse_moved = false;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-04-28 13:32:10 +00:00
|
|
|
_target_x = 0.0;
|
|
|
|
_target_z = 0.0;
|
2013-04-28 19:34:35 +00:00
|
|
|
_last_update_x = 0;
|
|
|
|
_last_update_z = 0;
|
|
|
|
|
2013-04-20 11:28:56 +00:00
|
|
|
_current_camera = cameraCreateDefinition();
|
|
|
|
_top_camera = cameraCreateDefinition();
|
|
|
|
_temp_camera = cameraCreateDefinition();
|
2013-04-28 13:32:10 +00:00
|
|
|
_zoom = 35.0;
|
2013-04-20 11:28:56 +00:00
|
|
|
|
2013-04-27 21:40:31 +00:00
|
|
|
Vector3 camera_location = {0.0, 80.0, 10.0};
|
2013-04-27 19:41:57 +00:00
|
|
|
cameraSetLocation(_current_camera, camera_location);
|
|
|
|
cameraSetTarget(_current_camera, VECTOR_ZERO);
|
2013-04-27 21:40:31 +00:00
|
|
|
cameraSetZoomToTarget(_top_camera, _zoom);
|
2013-04-27 19:41:57 +00:00
|
|
|
cameraCopyDefinition(_current_camera, _top_camera);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
_brush = NULL;
|
2012-07-15 14:42:50 +00:00
|
|
|
_brush_x = 0.0;
|
|
|
|
_brush_z = 0.0;
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WidgetHeightMap::~WidgetHeightMap()
|
|
|
|
{
|
2013-04-27 19:41:57 +00:00
|
|
|
cameraDeleteDefinition(_current_camera);
|
|
|
|
cameraDeleteDefinition(_top_camera);
|
|
|
|
cameraDeleteDefinition(_temp_camera);
|
2013-01-20 15:07:45 +00:00
|
|
|
rendererDelete(_renderer);
|
2012-08-08 13:30:40 +00:00
|
|
|
delete[] _vertices;
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
void WidgetHeightMap::setTerrain(TerrainDefinition* terrain)
|
2012-07-15 14:42:50 +00:00
|
|
|
{
|
2013-05-05 13:37:06 +00:00
|
|
|
_terrain = terrain;
|
|
|
|
TerrainRendererClass.bind(_renderer, _terrain);
|
2013-06-09 21:03:16 +00:00
|
|
|
_water_height = _renderer->terrain->getWaterHeight(_renderer) / _terrain->scaling;
|
2012-07-15 14:42:50 +00:00
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
revert();
|
2012-07-15 14:42:50 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
void WidgetHeightMap::setBrush(PaintingBrush* brush)
|
2012-07-16 20:34:01 +00:00
|
|
|
{
|
2013-05-05 13:37:06 +00:00
|
|
|
_brush = brush;
|
2012-07-16 20:34:01 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetHeightMap::revert()
|
|
|
|
{
|
|
|
|
_dirty = true;
|
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
2013-05-10 15:40:49 +00:00
|
|
|
void WidgetHeightMap::toggleWater(bool enabled)
|
|
|
|
{
|
|
|
|
_water = enabled;
|
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetHeightMap::toggleGrid(bool enabled)
|
|
|
|
{
|
|
|
|
_wireframe = enabled;
|
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
2013-06-20 15:38:23 +00:00
|
|
|
void WidgetHeightMap::togglePaintedArea(bool enabled)
|
|
|
|
{
|
|
|
|
_painted_area = enabled;
|
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
2013-04-28 13:32:10 +00:00
|
|
|
void WidgetHeightMap::keyPressEvent(QKeyEvent* event)
|
|
|
|
{
|
|
|
|
if (event->key() == Qt::Key_Up)
|
|
|
|
{
|
|
|
|
scrollTopCamera(0.0, -1.0);
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_Down)
|
|
|
|
{
|
|
|
|
scrollTopCamera(0.0, 1.0);
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_Left)
|
|
|
|
{
|
|
|
|
scrollTopCamera(-1.0, 0.0);
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_Right)
|
|
|
|
{
|
|
|
|
scrollTopCamera(1.0, 0.0);
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_PageUp)
|
|
|
|
{
|
|
|
|
zoomTopCamera(-3.0);
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_PageDown)
|
|
|
|
{
|
|
|
|
zoomTopCamera(3.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QGLWidget::keyPressEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-27 21:40:31 +00:00
|
|
|
void WidgetHeightMap::wheelEvent(QWheelEvent* event)
|
|
|
|
{
|
2013-05-10 15:40:49 +00:00
|
|
|
if (event->modifiers() == Qt::NoModifier)
|
|
|
|
{
|
|
|
|
if (event->orientation() == Qt::Vertical)
|
|
|
|
{
|
|
|
|
zoomTopCamera(-0.05 * (double) event->delta());
|
|
|
|
}
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
else
|
2013-04-27 21:40:31 +00:00
|
|
|
{
|
2013-05-10 15:40:49 +00:00
|
|
|
event->ignore();
|
2013-04-27 21:40:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-16 20:34:01 +00:00
|
|
|
void WidgetHeightMap::mousePressEvent(QMouseEvent* event)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2012-07-16 20:34:01 +00:00
|
|
|
_last_mouse_x = event->x();
|
|
|
|
_last_mouse_y = event->y();
|
|
|
|
if (event->buttons() & Qt::LeftButton)
|
|
|
|
{
|
|
|
|
_last_brush_action = 1;
|
|
|
|
}
|
|
|
|
else if (event->buttons() & Qt::RightButton)
|
|
|
|
{
|
|
|
|
_last_brush_action = -1;
|
|
|
|
}
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 21:21:56 +00:00
|
|
|
void WidgetHeightMap::mouseReleaseEvent(QMouseEvent*)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2012-07-16 20:34:01 +00:00
|
|
|
_last_brush_action = 0;
|
2013-05-05 13:37:06 +00:00
|
|
|
if (_terrain)
|
|
|
|
{
|
|
|
|
terrainEndBrushStroke(_terrain->height_map);
|
|
|
|
}
|
|
|
|
if (_brush)
|
|
|
|
{
|
|
|
|
_brush->randomizeNoise();
|
|
|
|
}
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event)
|
|
|
|
{
|
2012-07-16 20:34:01 +00:00
|
|
|
if (event->buttons() & Qt::MiddleButton)
|
|
|
|
{
|
|
|
|
// Rotate around the turntable
|
|
|
|
int move_x = event->x() - _last_mouse_x;
|
|
|
|
int move_y = event->y() - _last_mouse_y;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-04-20 11:28:56 +00:00
|
|
|
// TODO
|
|
|
|
/*_angle_h -= (double)move_x * 0.008;
|
|
|
|
_angle_v += (double)move_y * 0.003;*/
|
2012-07-16 20:34:01 +00:00
|
|
|
}
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-16 20:34:01 +00:00
|
|
|
_last_mouse_x = event->x();
|
|
|
|
_last_mouse_y = event->y();
|
2012-07-23 09:58:06 +00:00
|
|
|
_mouse_moved = true;
|
2012-07-16 20:34:01 +00:00
|
|
|
|
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
2012-07-24 14:59:06 +00:00
|
|
|
void WidgetHeightMap::timerEvent(QTimerEvent*)
|
2012-07-16 20:34:01 +00:00
|
|
|
{
|
2013-05-05 13:37:06 +00:00
|
|
|
if (not _terrain)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-24 14:59:06 +00:00
|
|
|
QDateTime new_time = QDateTime::currentDateTime();
|
2013-04-27 19:41:57 +00:00
|
|
|
double duration = 0.001 * (double) _last_time.msecsTo(new_time);
|
2012-07-24 14:59:06 +00:00
|
|
|
_last_time = new_time;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-04-28 13:32:10 +00:00
|
|
|
// Update top camera
|
2013-06-09 21:03:16 +00:00
|
|
|
Vector3 target = {_target_x, terrainGetInterpolatedHeight(_terrain, _target_x, _target_z, 1, 1), _target_z};
|
2013-04-28 13:32:10 +00:00
|
|
|
cameraSetLocationCoords(_top_camera, target.x, target.y + 1.0, target.z + 0.1);
|
|
|
|
cameraSetTarget(_top_camera, target);
|
|
|
|
cameraSetZoomToTarget(_top_camera, _zoom);
|
|
|
|
if (cameraTransitionToAnother(_current_camera, _top_camera, 0.8))
|
|
|
|
{
|
2013-04-28 19:34:35 +00:00
|
|
|
int update_x = (int) (floor(_target_x));
|
|
|
|
int update_z = (int) (floor(_target_z));
|
|
|
|
|
|
|
|
if (update_x - _last_update_x < -10 || update_x - _last_update_x > 10 || update_z - _last_update_z < -10 || update_z - _last_update_z > 10)
|
|
|
|
{
|
|
|
|
_dirty = true;
|
|
|
|
}
|
|
|
|
|
2013-04-28 13:32:10 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
2013-03-01 14:23:21 +00:00
|
|
|
if (not underMouse())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-28 13:32:10 +00:00
|
|
|
// Apply brush action
|
2013-05-05 13:37:06 +00:00
|
|
|
if (_last_brush_action != 0 && _brush)
|
2012-07-16 15:48:05 +00:00
|
|
|
{
|
2013-05-05 13:37:06 +00:00
|
|
|
_brush->applyToTerrain(_terrain, _brush_x + _target_x, _brush_z + _target_z, duration, _last_brush_action < 0);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-24 14:59:06 +00:00
|
|
|
// TODO Only mark dirty the updated area
|
2012-07-16 20:34:01 +00:00
|
|
|
_dirty = true;
|
2012-07-15 14:42:50 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
2013-03-01 14:23:21 +00:00
|
|
|
|
2013-04-28 13:32:10 +00:00
|
|
|
// Edge scrolling
|
|
|
|
double wx = (double) _last_mouse_x / (double) width();
|
|
|
|
double wy = (double) _last_mouse_y / (double) height();
|
|
|
|
double limit = 0.15;
|
|
|
|
double force = 1.0;
|
|
|
|
if (wx < limit)
|
2013-04-27 19:41:57 +00:00
|
|
|
{
|
2013-04-28 13:32:10 +00:00
|
|
|
scrollTopCamera(-(1.0 - wx / limit) * force, 0.0);
|
2013-04-27 19:41:57 +00:00
|
|
|
}
|
2013-04-28 13:32:10 +00:00
|
|
|
else if (wx > 1.0 - limit)
|
2013-03-01 14:23:21 +00:00
|
|
|
{
|
2013-04-28 13:32:10 +00:00
|
|
|
scrollTopCamera(force * (wx - (1.0 - limit)) / limit, 0.0);
|
2013-03-01 14:23:21 +00:00
|
|
|
}
|
2013-04-28 13:32:10 +00:00
|
|
|
if (wy < limit)
|
2013-03-01 14:23:21 +00:00
|
|
|
{
|
2013-04-28 13:32:10 +00:00
|
|
|
scrollTopCamera(0.0, -(1.0 - wy / limit) * force);
|
2013-03-01 14:23:21 +00:00
|
|
|
}
|
2013-04-28 13:32:10 +00:00
|
|
|
else if (wy > 1.0 - limit)
|
2013-03-01 14:23:21 +00:00
|
|
|
{
|
2013-04-28 13:32:10 +00:00
|
|
|
scrollTopCamera(0.0, force * (wy - (1.0 - limit)) / limit);
|
2013-03-01 14:23:21 +00:00
|
|
|
}
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetHeightMap::initializeGL()
|
|
|
|
{
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
|
2013-04-27 19:41:57 +00:00
|
|
|
GLfloat light_diffuse[] = {0.75, 0.74, 0.7, 1.0};
|
|
|
|
GLfloat light_specular[] = {0.0, 0.0, 0.0, 0.0};
|
2012-07-15 14:42:50 +00:00
|
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
|
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
|
2012-08-02 19:26:22 +00:00
|
|
|
light_diffuse[0] = 0.3;
|
|
|
|
light_diffuse[1] = 0.3;
|
|
|
|
light_diffuse[2] = 0.4;
|
|
|
|
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
|
|
|
|
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
|
|
|
|
glShadeModel(GL_SMOOTH);
|
2012-07-15 14:42:50 +00:00
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glEnable(GL_LIGHT0);
|
2012-08-02 19:26:22 +00:00
|
|
|
glEnable(GL_LIGHT1);
|
2012-07-15 14:42:50 +00:00
|
|
|
glEnable(GL_COLOR_MATERIAL);
|
2013-02-07 23:02:16 +00:00
|
|
|
//glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
//glFrontFace(GL_CCW);
|
|
|
|
//glCullFace(GL_BACK);
|
|
|
|
glDisable(GL_CULL_FACE);
|
2012-07-13 12:23:58 +00:00
|
|
|
|
2013-04-27 21:40:31 +00:00
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
glDepthMask(GL_TRUE);
|
2012-07-13 12:23:58 +00:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
2013-04-28 13:32:10 +00:00
|
|
|
glEnable(GL_LINE_SMOOTH);
|
|
|
|
glLineWidth(2.0);
|
2012-07-13 12:23:58 +00:00
|
|
|
|
|
|
|
glDisable(GL_FOG);
|
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetHeightMap::resizeGL(int w, int h)
|
|
|
|
{
|
|
|
|
glViewport(0, 0, w, h);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2012-07-13 21:24:19 +00:00
|
|
|
gluPerspective(1.57 * 180.0 / M_PI, 1.0, 1.0, 1000.0);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-13 12:23:58 +00:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetHeightMap::paintGL()
|
|
|
|
{
|
|
|
|
GLenum error_code;
|
|
|
|
QTime start_time;
|
|
|
|
double frame_time;
|
2012-07-13 21:24:19 +00:00
|
|
|
int rx, rz;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
if (not _terrain)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-08 16:47:49 +00:00
|
|
|
rx = HEIGHTMAP_RESOLUTION;
|
|
|
|
rz = HEIGHTMAP_RESOLUTION;
|
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
// Update vertex cache
|
|
|
|
if (_dirty)
|
|
|
|
{
|
|
|
|
updateVertexInfo();
|
2013-02-03 21:18:32 +00:00
|
|
|
emit heightmapChanged();
|
2012-07-15 14:42:50 +00:00
|
|
|
_dirty = false;
|
|
|
|
}
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-16 20:34:01 +00:00
|
|
|
// Picking mouse position using z-buffer (for brush)
|
2012-07-23 09:58:06 +00:00
|
|
|
if (_mouse_moved)
|
|
|
|
{
|
|
|
|
GLint viewport[4];
|
|
|
|
GLdouble modelview[16];
|
|
|
|
GLdouble projection[16];
|
|
|
|
GLfloat winX, winY, winZ;
|
|
|
|
Vector3 point;
|
2012-07-16 20:34:01 +00:00
|
|
|
|
2012-07-23 09:58:06 +00:00
|
|
|
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
|
|
|
|
glGetDoublev(GL_PROJECTION_MATRIX, projection);
|
|
|
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
2012-07-16 20:34:01 +00:00
|
|
|
|
2013-04-27 19:41:57 +00:00
|
|
|
winX = (float) _last_mouse_x;
|
|
|
|
winY = (float) height() - (float) _last_mouse_y;
|
|
|
|
glReadPixels(_last_mouse_x, (int) winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
|
2012-07-16 20:34:01 +00:00
|
|
|
|
2013-02-08 16:47:49 +00:00
|
|
|
if (winZ > 0.0 && winZ < 1000.0)
|
|
|
|
{
|
|
|
|
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &point.x, &point.y, &point.z);
|
|
|
|
|
2013-04-28 19:34:35 +00:00
|
|
|
_brush_x = point.x - _target_x;
|
|
|
|
_brush_z = point.z - _target_z;
|
2013-02-08 16:47:49 +00:00
|
|
|
}
|
2012-07-16 20:34:01 +00:00
|
|
|
|
2012-07-23 09:58:06 +00:00
|
|
|
_mouse_moved = false;
|
|
|
|
}
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-13 12:23:58 +00:00
|
|
|
// Place camera
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2013-04-27 19:41:57 +00:00
|
|
|
Vector3 camera_location = cameraGetLocation(_current_camera);
|
|
|
|
Vector3 camera_target = cameraGetTarget(_current_camera);
|
|
|
|
Vector3 camera_up = cameraGetUpVector(_current_camera);
|
|
|
|
gluLookAt(camera_location.x, camera_location.y, camera_location.z, camera_target.x, camera_target.y, camera_target.z, camera_up.x, camera_up.y, camera_up.z);
|
2012-07-13 12:23:58 +00:00
|
|
|
|
2012-08-02 19:26:22 +00:00
|
|
|
// Place lights
|
2013-04-27 19:41:57 +00:00
|
|
|
GLfloat light_position[] = {40.0, 40.0, 40.0, 0.0};
|
2012-08-02 19:26:22 +00:00
|
|
|
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
|
|
|
|
light_position[0] = -40.0;
|
|
|
|
light_position[2] = -60.0;
|
|
|
|
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-13 12:23:58 +00:00
|
|
|
// Background
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
// Height map
|
|
|
|
for (int x = 0; x < rx - 1; x++)
|
2012-07-13 21:24:19 +00:00
|
|
|
{
|
2012-07-15 14:42:50 +00:00
|
|
|
glBegin(GL_QUAD_STRIP);
|
2012-07-13 21:24:19 +00:00
|
|
|
for (int z = 0; z < rz; z++)
|
|
|
|
{
|
2013-02-07 16:06:26 +00:00
|
|
|
for (int dx = 1; dx >= 0; dx--)
|
2012-07-15 14:42:50 +00:00
|
|
|
{
|
2013-02-07 16:06:26 +00:00
|
|
|
_VertexInfo* vertex = _vertices + z * rx + x + dx;
|
2013-05-05 13:37:06 +00:00
|
|
|
double brush_influence;
|
2013-02-07 16:06:26 +00:00
|
|
|
|
2013-05-05 13:37:06 +00:00
|
|
|
if (_brush)
|
2013-02-07 16:06:26 +00:00
|
|
|
{
|
2013-05-05 13:37:06 +00:00
|
|
|
double diff_x, diff_z;
|
|
|
|
|
|
|
|
diff_x = vertex->point.x - _target_x - _brush_x;
|
|
|
|
diff_z = vertex->point.z - _target_z - _brush_z;
|
|
|
|
|
|
|
|
brush_influence = _brush->getInfluence(diff_x, diff_z);
|
2013-02-07 16:06:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-05-05 13:37:06 +00:00
|
|
|
brush_influence = 0.0;
|
2013-02-07 16:06:26 +00:00
|
|
|
}
|
2013-05-05 13:37:06 +00:00
|
|
|
|
2013-06-20 15:38:23 +00:00
|
|
|
glColor3f(0.8 + brush_influence, (_painted_area && vertex->painted) ? 1.0 : 0.8, 0.8);
|
2013-02-07 23:02:16 +00:00
|
|
|
glNormal3f(vertex->normal.x, vertex->normal.y, vertex->normal.z);
|
2013-04-28 19:34:35 +00:00
|
|
|
glVertex3f(vertex->point.x, vertex->point.y, vertex->point.z);
|
2012-07-15 14:42:50 +00:00
|
|
|
}
|
2012-07-13 21:24:19 +00:00
|
|
|
}
|
2012-07-15 14:42:50 +00:00
|
|
|
glEnd();
|
2012-07-13 21:24:19 +00:00
|
|
|
}
|
2012-07-13 12:23:58 +00:00
|
|
|
|
2013-04-27 21:40:31 +00:00
|
|
|
// Wireframe
|
|
|
|
if (_wireframe)
|
|
|
|
{
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2013-04-28 13:32:10 +00:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
2013-04-27 21:40:31 +00:00
|
|
|
glColor4f(0.8, 0.0, 0.0, 0.1);
|
|
|
|
for (int z = 0; z < rz; z++)
|
|
|
|
{
|
|
|
|
glBegin(GL_LINE_STRIP);
|
|
|
|
for (int x = 0; x < rx; x++)
|
|
|
|
{
|
|
|
|
_VertexInfo* vertex = _vertices + z * rx + x;
|
2013-04-28 19:34:35 +00:00
|
|
|
glVertex3f(vertex->point.x, vertex->point.y, vertex->point.z);
|
2013-04-27 21:40:31 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
for (int x = 0; x < rx; x++)
|
|
|
|
{
|
|
|
|
glBegin(GL_LINE_STRIP);
|
|
|
|
for (int z = 0; z < rz; z++)
|
|
|
|
{
|
|
|
|
_VertexInfo* vertex = _vertices + z * rx + x;
|
2013-04-28 19:34:35 +00:00
|
|
|
glVertex3f(vertex->point.x, vertex->point.y, vertex->point.z);
|
2013-04-27 21:40:31 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
glEnable(GL_LIGHTING);
|
2013-04-28 13:32:10 +00:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
2013-04-27 21:40:31 +00:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Water
|
|
|
|
if (_water)
|
|
|
|
{
|
2013-04-28 13:32:10 +00:00
|
|
|
glDisable(GL_LIGHTING);
|
2013-04-27 21:40:31 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glColor4f(0.2, 0.3, 0.7, 0.7);
|
|
|
|
glBegin(GL_QUADS);
|
2013-04-28 13:32:10 +00:00
|
|
|
glVertex3f(_target_x - 500.0, _water_height, _target_z - 500.0);
|
|
|
|
glVertex3f(_target_x - 500.0, _water_height, _target_z + 500.0);
|
|
|
|
glVertex3f(_target_x + 500.0, _water_height, _target_z + 500.0);
|
|
|
|
glVertex3f(_target_x + 500.0, _water_height, _target_z - 500.0);
|
2013-04-27 21:40:31 +00:00
|
|
|
glEnd();
|
|
|
|
glDisable(GL_BLEND);
|
2013-04-28 13:32:10 +00:00
|
|
|
glEnable(GL_LIGHTING);
|
2013-04-27 21:40:31 +00:00
|
|
|
}
|
|
|
|
|
2012-07-13 12:23:58 +00:00
|
|
|
// Time stats
|
2013-04-27 19:41:57 +00:00
|
|
|
frame_time = 0.001 * (double) start_time.msecsTo(QTime::currentTime());
|
2012-07-13 12:23:58 +00:00
|
|
|
_average_frame_time = _average_frame_time * 0.8 + frame_time * 0.2;
|
|
|
|
//printf("%d %f\n", quality, average_frame_time);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-13 12:23:58 +00:00
|
|
|
while ((error_code = glGetError()) != GL_NO_ERROR)
|
|
|
|
{
|
2013-04-27 19:41:57 +00:00
|
|
|
logDebug(QString("[OpenGL] ERROR : ") + (const char*) gluErrorString(error_code));
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
}
|
2012-07-15 14:42:50 +00:00
|
|
|
|
2013-04-28 13:32:10 +00:00
|
|
|
void WidgetHeightMap::scrollTopCamera(double dx, double dz)
|
|
|
|
{
|
|
|
|
if (dx != 0.0)
|
|
|
|
{
|
2013-05-05 16:42:55 +00:00
|
|
|
_target_x += dx * _zoom * 0.05;
|
2013-04-28 13:32:10 +00:00
|
|
|
}
|
|
|
|
if (dz != 0.0)
|
|
|
|
{
|
|
|
|
|
2013-05-05 16:42:55 +00:00
|
|
|
_target_z += dz * _zoom * 0.05;
|
2013-04-28 13:32:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetHeightMap::zoomTopCamera(double dzoom)
|
|
|
|
{
|
|
|
|
_zoom += dzoom;
|
|
|
|
if (_zoom < 10.0)
|
|
|
|
{
|
|
|
|
_zoom = 10.0;
|
|
|
|
}
|
2013-04-28 19:34:35 +00:00
|
|
|
else if (_zoom > 80.0)
|
2013-04-28 13:32:10 +00:00
|
|
|
{
|
|
|
|
|
2013-04-28 19:34:35 +00:00
|
|
|
_zoom = 80.0;
|
2013-04-28 13:32:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
void WidgetHeightMap::updateVertexInfo()
|
|
|
|
{
|
2012-12-10 22:05:53 +00:00
|
|
|
int rx = HEIGHTMAP_RESOLUTION;
|
|
|
|
int rz = HEIGHTMAP_RESOLUTION;
|
2013-01-14 13:28:42 +00:00
|
|
|
int dx, dz;
|
2012-08-08 13:30:40 +00:00
|
|
|
|
|
|
|
_VertexInfo* old_vertices = _vertices;
|
|
|
|
_vertices = new _VertexInfo[rx * rz];
|
|
|
|
delete[] old_vertices;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-04-28 19:34:35 +00:00
|
|
|
_last_update_x = (int) (floor(_target_x));
|
|
|
|
_last_update_z = (int) (floor(_target_z));
|
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
// Update positions
|
|
|
|
for (int x = 0; x < rx; x++)
|
|
|
|
{
|
|
|
|
for (int z = 0; z < rz; z++)
|
|
|
|
{
|
2012-08-08 13:30:40 +00:00
|
|
|
_VertexInfo* vertex = _vertices + z * rx + x;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-04-28 19:34:35 +00:00
|
|
|
dx = _last_update_x + x - rx / 2;
|
|
|
|
dz = _last_update_z + z - rz / 2;
|
2013-01-10 21:21:56 +00:00
|
|
|
|
2013-04-27 19:41:57 +00:00
|
|
|
vertex->point.x = (double) dx;
|
|
|
|
vertex->point.z = (double) dz;
|
2013-01-14 13:28:42 +00:00
|
|
|
|
2013-06-09 21:03:16 +00:00
|
|
|
vertex->point.y = terrainGetGridHeight(_terrain, dx, dz, 1) * _terrain->height;
|
2013-02-07 16:06:26 +00:00
|
|
|
|
2013-02-07 23:02:16 +00:00
|
|
|
vertex->painted = terrainIsPainted(_terrain->height_map, dx, dz);
|
2012-07-15 14:42:50 +00:00
|
|
|
}
|
|
|
|
}
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
// Update normals
|
|
|
|
for (int x = 0; x < rx; x++)
|
|
|
|
{
|
|
|
|
for (int z = 0; z < rz; z++)
|
|
|
|
{
|
2012-08-08 13:30:40 +00:00
|
|
|
_VertexInfo* vertex = _vertices + z * rx + x;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
if (x == rx - 1)
|
|
|
|
{
|
|
|
|
vertex->normal = (vertex - 1)->normal;
|
|
|
|
}
|
|
|
|
else if (z == rz - 1)
|
|
|
|
{
|
|
|
|
vertex->normal = (vertex - rx)->normal;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Vector3 dx, dz;
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
dx = v3Sub((vertex + 1)->point, vertex->point);
|
|
|
|
dz = v3Sub((vertex + rx)->point, vertex->point);
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2012-07-15 14:42:50 +00:00
|
|
|
vertex->normal = v3Cross(v3Normalize(dz), v3Normalize(dx));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|