2013-12-23 13:09:52 +00:00
|
|
|
#include "OpenGLTerrain.h"
|
|
|
|
|
2015-12-03 22:04:50 +00:00
|
|
|
#include "OpenGLFunctions.h"
|
2013-12-23 13:09:52 +00:00
|
|
|
#include "OpenGLRenderer.h"
|
|
|
|
#include "OpenGLShaderProgram.h"
|
|
|
|
#include "ParallelPool.h"
|
|
|
|
#include "Thread.h"
|
2015-12-07 22:32:55 +00:00
|
|
|
#include "OpenGLTerrainChunk.h"
|
2013-12-23 13:09:52 +00:00
|
|
|
#include "WaterRenderer.h"
|
|
|
|
#include "CameraDefinition.h"
|
2015-08-18 18:31:11 +00:00
|
|
|
#include "AtmosphereDefinition.h"
|
2013-12-23 13:09:52 +00:00
|
|
|
#include "Scenery.h"
|
2015-08-17 20:55:30 +00:00
|
|
|
#include "FloatNode.h"
|
|
|
|
#include "FloatDiff.h"
|
2013-12-23 13:09:52 +00:00
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
class ChunkMaintenanceThreads : public ParallelPool {
|
|
|
|
public:
|
|
|
|
ChunkMaintenanceThreads(OpenGLTerrain *terrain) : terrain(terrain) {
|
2013-12-23 13:09:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
virtual void work() override {
|
|
|
|
while (running) {
|
|
|
|
if (not terrain->isPaused()) {
|
2015-08-18 17:12:54 +00:00
|
|
|
terrain->performChunksMaintenance();
|
|
|
|
}
|
|
|
|
|
2013-12-23 13:09:52 +00:00
|
|
|
Thread::timeSleepMs(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
private:
|
|
|
|
OpenGLTerrain *terrain;
|
2013-12-23 13:09:52 +00:00
|
|
|
};
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
OpenGLTerrain::OpenGLTerrain(OpenGLRenderer *renderer) : OpenGLPart(renderer) {
|
2013-12-23 13:09:52 +00:00
|
|
|
work = new ChunkMaintenanceThreads(this);
|
2015-08-18 17:12:54 +00:00
|
|
|
paused = false;
|
2015-12-07 22:32:55 +00:00
|
|
|
|
|
|
|
program = createShader("terrain");
|
|
|
|
program->addVertexSource("terrain");
|
|
|
|
program->addFragmentSource("atmosphere");
|
|
|
|
program->addFragmentSource("tonemapping");
|
|
|
|
program->addFragmentSource("fadeout");
|
|
|
|
program->addFragmentSource("ui");
|
|
|
|
program->addFragmentSource("terrain");
|
2013-12-23 13:09:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
OpenGLTerrain::~OpenGLTerrain() {
|
2013-12-23 13:09:52 +00:00
|
|
|
delete work;
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
for (int i = 0; i < _chunks.count(); i++) {
|
2013-12-23 13:09:52 +00:00
|
|
|
delete _chunks[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::initialize() {
|
2013-12-23 13:09:52 +00:00
|
|
|
// Add terrain chunks
|
2015-08-12 15:26:17 +00:00
|
|
|
int chunks = 12;
|
2013-12-24 12:22:34 +00:00
|
|
|
double size = 800.0;
|
2015-11-09 21:30:46 +00:00
|
|
|
double chunksize = size / (double)chunks;
|
2013-12-23 13:09:52 +00:00
|
|
|
double start = -size / 2.0;
|
2015-11-09 21:30:46 +00:00
|
|
|
for (int i = 0; i < chunks; i++) {
|
|
|
|
for (int j = 0; j < chunks; j++) {
|
2015-12-07 22:32:55 +00:00
|
|
|
OpenGLTerrainChunk *chunk = new OpenGLTerrainChunk(renderer, start + chunksize * (double)i,
|
2015-11-09 21:30:46 +00:00
|
|
|
start + chunksize * (double)j, chunksize, chunks);
|
2013-12-23 13:09:52 +00:00
|
|
|
_chunks.append(chunk);
|
|
|
|
_updateQueue.append(chunk);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start chunks maintenance
|
|
|
|
work->start();
|
2015-08-17 20:55:30 +00:00
|
|
|
|
|
|
|
// Watch for definition changes
|
|
|
|
renderer->getScenery()->getTerrain()->propWaterHeight()->addWatcher(this);
|
2015-08-18 18:31:11 +00:00
|
|
|
renderer->getScenery()->getAtmosphere()->propDayTime()->addWatcher(this);
|
2013-12-23 13:09:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::update() {
|
|
|
|
for (auto &chunk : _chunks) {
|
2015-08-19 18:06:47 +00:00
|
|
|
chunk->askReset(true, true);
|
|
|
|
}
|
2013-12-23 13:09:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::render() {
|
|
|
|
for (int i = 0; i < _chunks.count(); i++) {
|
2015-12-07 22:32:55 +00:00
|
|
|
_chunks[i]->render(program);
|
2013-12-23 13:09:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::interrupt() {
|
|
|
|
for (auto &chunk : _chunks) {
|
2013-12-30 15:02:33 +00:00
|
|
|
chunk->askInterrupt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::pause() {
|
2015-08-18 17:12:54 +00:00
|
|
|
paused = true;
|
|
|
|
interrupt();
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::resume() {
|
|
|
|
for (auto &chunk : _chunks) {
|
2015-08-18 17:12:54 +00:00
|
|
|
chunk->askResume();
|
|
|
|
}
|
|
|
|
paused = false;
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::resetTextures() {
|
|
|
|
for (auto &chunk : _chunks) {
|
2015-07-26 16:30:30 +00:00
|
|
|
chunk->askReset(false, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-07 22:32:55 +00:00
|
|
|
static bool _cmpChunks(const OpenGLTerrainChunk *c1, const OpenGLTerrainChunk *c2) {
|
2013-12-23 13:09:52 +00:00
|
|
|
return c1->priority > c2->priority;
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::performChunksMaintenance() {
|
|
|
|
CameraDefinition *camera = renderer->getScenery()->getCamera();
|
2015-12-07 22:32:55 +00:00
|
|
|
OpenGLTerrainChunk *chunk;
|
2013-12-23 13:09:52 +00:00
|
|
|
|
|
|
|
_lock_chunks.lock();
|
2015-11-09 21:30:46 +00:00
|
|
|
if (_updateQueue.count() > 0) {
|
2013-12-23 13:09:52 +00:00
|
|
|
chunk = _updateQueue.takeFirst();
|
|
|
|
_lock_chunks.unlock();
|
2015-11-09 21:30:46 +00:00
|
|
|
} else {
|
2013-12-23 13:09:52 +00:00
|
|
|
_lock_chunks.unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
chunk->maintain();
|
|
|
|
|
|
|
|
_lock_chunks.lock();
|
|
|
|
_updateQueue.append(chunk);
|
2015-11-09 21:30:46 +00:00
|
|
|
for (int i = 0; i < _chunks.count(); i++) {
|
2013-12-23 13:09:52 +00:00
|
|
|
_chunks[i]->updatePriority(camera);
|
|
|
|
}
|
|
|
|
qSort(_updateQueue.begin(), _updateQueue.end(), _cmpChunks);
|
|
|
|
_lock_chunks.unlock();
|
|
|
|
}
|
2015-08-17 20:55:30 +00:00
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLTerrain::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) {
|
|
|
|
if (node->getPath() == "/terrain/water_height") {
|
2015-08-17 20:55:30 +00:00
|
|
|
resetTextures();
|
2015-11-09 21:30:46 +00:00
|
|
|
} else if (node->getPath() == "/atmosphere/daytime") {
|
2015-08-18 18:31:11 +00:00
|
|
|
resetTextures();
|
|
|
|
}
|
2015-08-17 20:55:30 +00:00
|
|
|
}
|