2012-01-27 14:47:08 +00:00
|
|
|
#include "widgetwanderer.h"
|
|
|
|
|
|
|
|
#include <QGLWidget>
|
2012-01-27 16:01:34 +00:00
|
|
|
#include <QKeyEvent>
|
2012-01-30 13:10:16 +00:00
|
|
|
#include <QTime>
|
2012-01-27 17:21:57 +00:00
|
|
|
#include <math.h>
|
2012-04-27 20:05:33 +00:00
|
|
|
#include <GL/glu.h>
|
2012-05-08 14:07:47 +00:00
|
|
|
#include <QThread>
|
2012-01-27 14:47:08 +00:00
|
|
|
#include "../lib_paysages/scenery.h"
|
2012-05-08 14:07:47 +00:00
|
|
|
#include "../lib_paysages/euclid.h"
|
|
|
|
|
|
|
|
class ChunkMaintenanceThread:public QThread
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ChunkMaintenanceThread(WidgetWanderer* wanderer)
|
|
|
|
{
|
|
|
|
_wanderer = wanderer;
|
|
|
|
_running = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void askStop()
|
|
|
|
{
|
|
|
|
_running = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void usleep(unsigned long us)
|
|
|
|
{
|
|
|
|
QThread::usleep(us);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void run()
|
|
|
|
{
|
|
|
|
while (_running)
|
|
|
|
{
|
|
|
|
_wanderer->performChunksMaintenance();
|
|
|
|
QThread::usleep(10000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool _running;
|
|
|
|
WidgetWanderer* _wanderer;
|
|
|
|
};
|
|
|
|
|
|
|
|
static QVector<ChunkMaintenanceThread*> _threads;
|
2012-01-27 14:47:08 +00:00
|
|
|
|
|
|
|
WidgetWanderer::WidgetWanderer(QWidget *parent, CameraDefinition* camera):
|
|
|
|
QGLWidget(parent)
|
|
|
|
{
|
|
|
|
setMinimumSize(400, 300);
|
2012-01-27 16:01:34 +00:00
|
|
|
setFocusPolicy(Qt::StrongFocus);
|
2012-01-27 14:47:08 +00:00
|
|
|
|
2012-01-27 23:01:21 +00:00
|
|
|
_base_camera = camera;
|
|
|
|
cameraCopyDefinition(camera, &_current_camera);
|
2012-01-27 14:47:08 +00:00
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
_water = waterCreateDefinition();
|
|
|
|
sceneryGetWater(&_water);
|
2012-05-08 14:07:47 +00:00
|
|
|
_sky = skyCreateDefinition();
|
|
|
|
sceneryGetSky(&_sky);
|
2012-05-08 12:07:15 +00:00
|
|
|
|
|
|
|
_renderer = sceneryCreateStandardRenderer();
|
2012-05-08 14:07:47 +00:00
|
|
|
_updated = false;
|
2012-01-27 14:47:08 +00:00
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
int chunks = 16;
|
2012-05-08 14:07:47 +00:00
|
|
|
double size = 150.0;
|
2012-05-08 12:07:15 +00:00
|
|
|
double chunksize = size / (double)chunks;
|
|
|
|
double start = -size / 2.0;
|
|
|
|
for (int i = 0; i < chunks; i++)
|
|
|
|
{
|
|
|
|
for (int j = 0; j < chunks; j++)
|
|
|
|
{
|
2012-05-08 22:03:39 +00:00
|
|
|
WandererChunk* chunk = new WandererChunk(&_renderer, start + chunksize * (double)i, start + chunksize * (double)j, chunksize);
|
2012-05-08 14:07:47 +00:00
|
|
|
_chunks.append(chunk);
|
|
|
|
_updateQueue.append(chunk);
|
2012-05-08 12:07:15 +00:00
|
|
|
}
|
|
|
|
}
|
2012-05-08 14:07:47 +00:00
|
|
|
|
|
|
|
startThreads();
|
|
|
|
startTimer(1000);
|
2012-01-30 13:10:16 +00:00
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
_average_frame_time = 0.05;
|
|
|
|
_quality = 3;
|
|
|
|
_last_mouse_x = 0;
|
|
|
|
_last_mouse_y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
WidgetWanderer::~WidgetWanderer()
|
|
|
|
{
|
2012-05-08 14:07:47 +00:00
|
|
|
stopThreads();
|
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
for (int i = 0; i < _chunks.count(); i++)
|
|
|
|
{
|
|
|
|
delete _chunks[i];
|
|
|
|
}
|
|
|
|
waterDeleteDefinition(&_water);
|
2012-01-27 16:01:34 +00:00
|
|
|
}
|
|
|
|
|
2012-05-08 14:07:47 +00:00
|
|
|
void WidgetWanderer::startThreads()
|
|
|
|
{
|
|
|
|
int nbcore;
|
|
|
|
|
|
|
|
_alive = true;
|
|
|
|
|
|
|
|
nbcore = QThread::idealThreadCount() - 1;
|
|
|
|
if (nbcore < 1)
|
|
|
|
{
|
|
|
|
nbcore = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < nbcore; i++)
|
|
|
|
{
|
|
|
|
_threads.append(new ChunkMaintenanceThread(this));
|
|
|
|
}
|
|
|
|
for (int i = 0; i < _threads.count(); i++)
|
|
|
|
{
|
|
|
|
_threads[i]->start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetWanderer::stopThreads()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < _threads.count(); i++)
|
|
|
|
{
|
|
|
|
_threads[i]->askStop();
|
|
|
|
}
|
|
|
|
_alive = false;
|
|
|
|
for (int i = 0; i < _threads.count(); i++)
|
|
|
|
{
|
|
|
|
_threads[i]->wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-08 22:03:39 +00:00
|
|
|
bool _cmpChunks(const WandererChunk* c1, const WandererChunk* c2)
|
|
|
|
{
|
|
|
|
return c1->_ideal_priority > c2->_ideal_priority;
|
|
|
|
}
|
|
|
|
|
2012-05-08 14:07:47 +00:00
|
|
|
void WidgetWanderer::performChunksMaintenance()
|
|
|
|
{
|
|
|
|
WandererChunk* chunk;
|
|
|
|
|
|
|
|
_lock_chunks.lock();
|
|
|
|
if (_updateQueue.count() > 0)
|
|
|
|
{
|
|
|
|
chunk = _updateQueue.takeFirst();
|
|
|
|
_lock_chunks.unlock();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_lock_chunks.unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-08 22:03:39 +00:00
|
|
|
if (chunk->maintain(_current_camera.location))
|
2012-05-08 14:07:47 +00:00
|
|
|
{
|
|
|
|
if (!_alive)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_updated = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
_lock_chunks.lock();
|
|
|
|
_updateQueue.append(chunk);
|
2012-05-08 22:03:39 +00:00
|
|
|
qSort(_updateQueue.begin(), _updateQueue.end(), _cmpChunks);
|
2012-05-08 14:07:47 +00:00
|
|
|
_lock_chunks.unlock();
|
|
|
|
}
|
|
|
|
|
2012-01-27 23:01:21 +00:00
|
|
|
void WidgetWanderer::resetCamera()
|
|
|
|
{
|
|
|
|
cameraCopyDefinition(_base_camera, &_current_camera);
|
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetWanderer::validateCamera()
|
|
|
|
{
|
|
|
|
cameraCopyDefinition(&_current_camera, _base_camera);
|
|
|
|
}
|
|
|
|
|
2012-01-27 16:01:34 +00:00
|
|
|
void WidgetWanderer::keyPressEvent(QKeyEvent* event)
|
|
|
|
{
|
|
|
|
double factor;
|
|
|
|
|
2012-04-22 17:12:39 +00:00
|
|
|
if (event->modifiers() & Qt::ControlModifier)
|
2012-01-27 16:01:34 +00:00
|
|
|
{
|
|
|
|
factor = 0.1;
|
|
|
|
}
|
2012-04-22 17:12:39 +00:00
|
|
|
else if (event->modifiers() & Qt::ShiftModifier)
|
2012-01-27 16:01:34 +00:00
|
|
|
{
|
|
|
|
factor = 10.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
factor = 1.0;
|
|
|
|
}
|
2012-01-27 17:21:57 +00:00
|
|
|
factor *= 3.0;
|
2012-01-27 16:01:34 +00:00
|
|
|
|
|
|
|
if (event->key() == Qt::Key_Up)
|
|
|
|
{
|
2012-01-27 23:01:21 +00:00
|
|
|
cameraStrafeForward(&_current_camera, 0.1 * factor);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_Down)
|
|
|
|
{
|
2012-01-27 23:01:21 +00:00
|
|
|
cameraStrafeForward(&_current_camera, -0.1 * factor);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_Right)
|
|
|
|
{
|
2012-01-27 23:01:21 +00:00
|
|
|
cameraStrafeRight(&_current_camera, 0.1 * factor);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_Left)
|
|
|
|
{
|
2012-01-27 23:01:21 +00:00
|
|
|
cameraStrafeRight(&_current_camera, -0.1 * factor);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_PageUp)
|
|
|
|
{
|
2012-01-27 23:01:21 +00:00
|
|
|
cameraStrafeUp(&_current_camera, 0.1 * factor);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
else if (event->key() == Qt::Key_PageDown)
|
|
|
|
{
|
2012-01-27 23:01:21 +00:00
|
|
|
cameraStrafeUp(&_current_camera, -0.1 * factor);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QGLWidget::keyPressEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetWanderer::mousePressEvent(QMouseEvent* event)
|
|
|
|
{
|
2012-05-08 12:07:15 +00:00
|
|
|
_last_mouse_x = event->x();
|
|
|
|
_last_mouse_y = event->y();
|
2012-01-27 16:01:34 +00:00
|
|
|
|
|
|
|
event->ignore();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetWanderer::mouseMoveEvent(QMouseEvent* event)
|
|
|
|
{
|
|
|
|
double factor;
|
|
|
|
|
2012-04-22 17:12:39 +00:00
|
|
|
if (event->modifiers() & Qt::ControlModifier)
|
2012-01-27 16:01:34 +00:00
|
|
|
{
|
|
|
|
factor = 0.01;
|
|
|
|
}
|
2012-04-22 17:12:39 +00:00
|
|
|
else if (event->modifiers() & Qt::ShiftModifier)
|
2012-01-27 16:01:34 +00:00
|
|
|
{
|
|
|
|
factor = 1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
factor = 0.1;
|
|
|
|
}
|
|
|
|
factor *= 0.2;
|
|
|
|
|
|
|
|
if (event->buttons() & Qt::LeftButton)
|
|
|
|
{
|
2012-05-08 12:07:15 +00:00
|
|
|
cameraRotateYaw(&_current_camera, (double)(event->x() - _last_mouse_x) * factor * 0.1);
|
|
|
|
cameraRotatePitch(&_current_camera, (double)(event->y() - _last_mouse_y) * factor * 0.1);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
event->accept();
|
|
|
|
}
|
2012-01-27 17:21:57 +00:00
|
|
|
else if (event->buttons() & Qt::RightButton)
|
|
|
|
{
|
2012-05-08 12:07:15 +00:00
|
|
|
cameraStrafeRight(&_current_camera, (double)(_last_mouse_x - event->x()) * factor);
|
|
|
|
cameraStrafeUp(&_current_camera, (double)(event->y() - _last_mouse_y) * factor);
|
2012-01-27 17:21:57 +00:00
|
|
|
updateGL();
|
|
|
|
event->accept();
|
|
|
|
}
|
2012-01-27 16:01:34 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
event->ignore();
|
|
|
|
}
|
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
_last_mouse_x = event->x();
|
|
|
|
_last_mouse_y = event->y();
|
2012-01-27 16:01:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetWanderer::wheelEvent(QWheelEvent* event)
|
|
|
|
{
|
|
|
|
double factor;
|
|
|
|
|
2012-04-22 17:12:39 +00:00
|
|
|
if (event->modifiers() & Qt::ControlModifier)
|
2012-01-27 16:01:34 +00:00
|
|
|
{
|
|
|
|
factor = 0.01;
|
|
|
|
}
|
2012-04-22 17:12:39 +00:00
|
|
|
else if (event->modifiers() & Qt::ShiftModifier)
|
2012-01-27 16:01:34 +00:00
|
|
|
{
|
|
|
|
factor = 1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
factor = 0.1;
|
|
|
|
}
|
2012-01-27 17:21:57 +00:00
|
|
|
factor *= 0.03;
|
2012-01-27 16:01:34 +00:00
|
|
|
|
|
|
|
if (event->orientation() == Qt::Vertical)
|
|
|
|
{
|
2012-01-27 23:01:21 +00:00
|
|
|
cameraStrafeForward(&_current_camera, (double)event->delta() * factor);
|
2012-01-27 16:01:34 +00:00
|
|
|
updateGL();
|
|
|
|
|
|
|
|
}
|
|
|
|
event->accept();
|
2012-01-27 14:47:08 +00:00
|
|
|
}
|
|
|
|
|
2012-05-08 14:07:47 +00:00
|
|
|
void WidgetWanderer::timerEvent(QTimerEvent *event)
|
|
|
|
{
|
|
|
|
if (_updated)
|
|
|
|
{
|
|
|
|
_updated = false;
|
|
|
|
updateGL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-27 14:47:08 +00:00
|
|
|
void WidgetWanderer::initializeGL()
|
|
|
|
{
|
2012-05-08 14:07:47 +00:00
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
2012-01-27 17:21:57 +00:00
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
|
|
|
|
glFrontFace(GL_CCW);
|
|
|
|
glCullFace(GL_BACK);
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
|
2012-01-30 16:40:17 +00:00
|
|
|
glDepthFunc(GL_LESS);
|
2012-01-27 17:21:57 +00:00
|
|
|
glDepthMask(true);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
glEnable(GL_LINE_SMOOTH);
|
|
|
|
glLineWidth(1.0);
|
2012-05-08 12:07:15 +00:00
|
|
|
|
|
|
|
glDisable(GL_FOG);
|
2012-05-08 14:07:47 +00:00
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2012-01-27 14:47:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetWanderer::resizeGL(int w, int h)
|
|
|
|
{
|
2012-01-31 11:20:52 +00:00
|
|
|
cameraSetRenderSize(&_current_camera, w, h);
|
|
|
|
|
2012-01-29 14:23:10 +00:00
|
|
|
glViewport(0, 0, w, h);
|
2012-01-27 14:47:08 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2012-01-31 11:20:52 +00:00
|
|
|
gluPerspective(_current_camera.yfov * 180.0 / M_PI, _current_camera.xratio, _current_camera.znear, _current_camera.zfar);
|
2012-05-08 12:07:15 +00:00
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2012-01-27 17:21:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WidgetWanderer::paintGL()
|
|
|
|
{
|
2012-01-30 13:10:16 +00:00
|
|
|
QTime start_time;
|
|
|
|
double frame_time;
|
|
|
|
|
2012-05-08 14:07:47 +00:00
|
|
|
if (_current_camera.location.y > 30.0)
|
|
|
|
{
|
|
|
|
_current_camera.location.y = 30.0;
|
|
|
|
}
|
|
|
|
|
2012-01-29 11:34:49 +00:00
|
|
|
cameraValidateDefinition(&_current_camera, 1);
|
|
|
|
|
2012-01-30 13:10:16 +00:00
|
|
|
start_time = QTime::currentTime();
|
|
|
|
|
2012-01-27 14:47:08 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2012-01-27 23:01:21 +00:00
|
|
|
gluLookAt(_current_camera.location.x, _current_camera.location.y, _current_camera.location.z, _current_camera.target.x, _current_camera.target.y, _current_camera.target.z, _current_camera.up.x, _current_camera.up.y, _current_camera.up.z);
|
2012-01-27 14:47:08 +00:00
|
|
|
|
2012-05-08 14:07:47 +00:00
|
|
|
// Background
|
|
|
|
Color zenith_color = skyGetZenithColor(&_sky);
|
|
|
|
glClearColor(zenith_color.r, zenith_color.g, zenith_color.b, 0.0);
|
2012-01-27 14:47:08 +00:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2012-05-08 14:07:47 +00:00
|
|
|
|
|
|
|
// Render sun
|
|
|
|
Vector3 sun_location = v3Add(_current_camera.location, v3Scale(skyGetSunDirection(&_sky), 500.0));
|
|
|
|
Color sun_color = skyGetSunColor(&_sky);
|
|
|
|
glDisable(GL_TEXTURE);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glColor3f(sun_color.r, sun_color.g, sun_color.b);
|
|
|
|
glPointSize(15.0 * _sky.sun_radius / 0.02);
|
|
|
|
glEnable(GL_POINT_SMOOTH);
|
|
|
|
glBegin(GL_POINTS);
|
|
|
|
glVertex3f(sun_location.x, sun_location.y, sun_location.z);
|
|
|
|
glEnd();
|
2012-05-08 12:07:15 +00:00
|
|
|
|
|
|
|
// Render water
|
|
|
|
glDisable(GL_TEXTURE);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
2012-05-08 14:07:47 +00:00
|
|
|
glColor3f(_water.material.base.r, _water.material.base.g, _water.material.base.b);
|
2012-01-27 14:47:08 +00:00
|
|
|
glBegin(GL_QUADS);
|
2012-05-08 12:07:15 +00:00
|
|
|
glVertex3f(_current_camera.location.x - 500.0, _water.height, _current_camera.location.z - 500.0);
|
|
|
|
glVertex3f(_current_camera.location.x - 500.0, _water.height, _current_camera.location.z + 500.0);
|
|
|
|
glVertex3f(_current_camera.location.x + 500.0, _water.height, _current_camera.location.z + 500.0);
|
|
|
|
glVertex3f(_current_camera.location.x + 500.0, _water.height, _current_camera.location.z - 500.0);
|
2012-01-27 14:47:08 +00:00
|
|
|
glEnd();
|
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
// Render terrain chunks
|
|
|
|
glEnable(GL_TEXTURE);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
for (int i = 0; i < _chunks.count(); i++)
|
|
|
|
{
|
2012-05-08 14:07:47 +00:00
|
|
|
glColor3f(1.0, 1.0, 1.0);
|
2012-05-08 12:07:15 +00:00
|
|
|
_chunks[i]->render(this);
|
|
|
|
}
|
2012-01-30 13:10:16 +00:00
|
|
|
|
|
|
|
frame_time = 0.001 * (double)start_time.msecsTo(QTime::currentTime());
|
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
_average_frame_time = _average_frame_time * 0.8 + frame_time * 0.2;
|
2012-01-30 13:10:16 +00:00
|
|
|
//printf("%d %f\n", quality, average_frame_time);
|
|
|
|
|
2012-05-08 12:07:15 +00:00
|
|
|
if (_average_frame_time > 0.1 && _quality > 1)
|
2012-01-30 13:10:16 +00:00
|
|
|
{
|
2012-05-08 12:07:15 +00:00
|
|
|
_quality--;
|
2012-01-30 13:10:16 +00:00
|
|
|
}
|
2012-05-08 12:07:15 +00:00
|
|
|
if (_average_frame_time < 0.04 && _quality < 10)
|
2012-01-30 13:10:16 +00:00
|
|
|
{
|
2012-05-08 12:07:15 +00:00
|
|
|
_quality++;
|
2012-01-30 13:10:16 +00:00
|
|
|
}
|
2012-01-27 14:47:08 +00:00
|
|
|
}
|