diff --git a/TODO b/TODO index 18ec120..019b19c 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,7 @@ Technlology Preview 2 : - Implement copy-on-write on definitions (to avoid copying whole heightmaps for instance). - Add clouds to OpenGL with 3d textures. - Fix potential holes in land rendering (OpenGL and software). +- Fix polygon culling near the camera in low-res renders (automatic tessellation ?). Technology Preview 3 : - Alter aerial perspective using estimation of the amount of light left after cloud layers traversal. diff --git a/src/interface/modeler/quickapp/RenderProcess.cpp b/src/interface/modeler/quickapp/RenderProcess.cpp index d9555f4..cdc7020 100644 --- a/src/interface/modeler/quickapp/RenderProcess.cpp +++ b/src/interface/modeler/quickapp/RenderProcess.cpp @@ -1,10 +1,12 @@ #include "RenderProcess.h" #include +#include #include "MainModelerWindow.h" #include "SoftwareCanvasRenderer.h" #include "RenderPreviewProvider.h" #include "RenderConfig.h" +#include "RenderProgress.h" #include "Thread.h" #include "Canvas.h" #include "CanvasPreview.h" @@ -171,6 +173,19 @@ void RenderProcess::timerEvent(QTimerEvent *) if (renderer) { + QTime t = QTime(0, 0, 0).addMSecs(renderer->getProgressHelper()->getDuration()); + QString info = QString("Elapsed time: ") + t.toString("hh:mm:ss"); + if (rendering) + { + unsigned long remaining = renderer->getProgressHelper()->estimateRemainingTime(); + if (remaining > 10000) + { + t = QTime(0, 0, 0).addMSecs(remaining); + info += " - Remaining: ~" + t.toString("hh:mm:ss"); + } + } + window->setQmlProperty("render_timing", "text", info); + window->setQmlProperty("render_progress", "value", renderer->getProgress()); } } diff --git a/src/interface/modeler/quickapp/qml/RenderDialog.qml b/src/interface/modeler/quickapp/qml/RenderDialog.qml index 6263c94..20b2c47 100644 --- a/src/interface/modeler/quickapp/qml/RenderDialog.qml +++ b/src/interface/modeler/quickapp/qml/RenderDialog.qml @@ -37,6 +37,14 @@ BaseRectangle { anchors.topMargin: 20 } + Text { + id: render_timing + objectName: "render_timing" + anchors.top: render_progress.bottom + anchors.horizontalCenter: render_progress.horizontalCenter + anchors.topMargin: 20 + } + Timer { interval: 500 running: true diff --git a/src/render/software/RenderProgress.cpp b/src/render/software/RenderProgress.cpp index 1243f6b..f20eedf 100644 --- a/src/render/software/RenderProgress.cpp +++ b/src/render/software/RenderProgress.cpp @@ -1,12 +1,16 @@ #include "RenderProgress.h" #include "Mutex.h" +#include "Time.h" +#include "Logs.h" RenderProgress::RenderProgress(int count) { lock = new Mutex(); global = 0.0; step = 1.0 / (double)count; + start_time = Time::getRelativeTimeMs(); + end_time = 0; } paysages::software::RenderProgress::~RenderProgress() @@ -24,6 +28,8 @@ void RenderProgress::reset() subs.pop(); } + start_time = Time::getRelativeTimeMs(); + lock->release(); } @@ -65,3 +71,39 @@ void RenderProgress::exitSub() lock->release(); } + +void RenderProgress::end() +{ + if (subs.size() > 0) + { + Logs::error() << subs.size() << " progress subs remaining at the end of render" << std::endl; + } + + end_time = Time::getRelativeTimeMs(); +} + +unsigned long RenderProgress::getDuration() const +{ + if (end_time) + { + return end_time - start_time; + } + else + { + return Time::getRelativeTimeMs() - start_time; + } +} + +unsigned long RenderProgress::estimateRemainingTime() const +{ + if (global < 0.00001) + { + return 0; + } + else + { + unsigned long done = getDuration(); + unsigned long total = (unsigned long)((double)done / global); + return total - done; + } +} diff --git a/src/render/software/RenderProgress.h b/src/render/software/RenderProgress.h index 31b7d1e..875b61f 100644 --- a/src/render/software/RenderProgress.h +++ b/src/render/software/RenderProgress.h @@ -30,11 +30,26 @@ public: void add(int value=1); void enterSub(int count); void exitSub(); + void end(); + + /** + * Get the render duration in milliseconds. + */ + unsigned long getDuration() const; + + /** + * Get the estimated remaining time in milliseconds. + * + * Returns 0 if unknown. + */ + unsigned long estimateRemainingTime() const; private: Mutex *lock; double global; double step; + unsigned long start_time; + unsigned long end_time; std::stack subs; }; diff --git a/src/render/software/SoftwareCanvasRenderer.cpp b/src/render/software/SoftwareCanvasRenderer.cpp index 607b11b..372a113 100644 --- a/src/render/software/SoftwareCanvasRenderer.cpp +++ b/src/render/software/SoftwareCanvasRenderer.cpp @@ -132,6 +132,7 @@ void SoftwareCanvasRenderer::render() } } progress->exitSub(); + progress->end(); finished = true; } diff --git a/src/system/Time.cpp b/src/system/Time.cpp new file mode 100644 index 0000000..d4315e5 --- /dev/null +++ b/src/system/Time.cpp @@ -0,0 +1,11 @@ +#include "Time.h" + +#include + +static QTime EPOCH = QTime::currentTime(); + +unsigned long Time::getRelativeTimeMs() +{ + return EPOCH.msecsTo(QTime::currentTime()); +} + diff --git a/src/system/Time.h b/src/system/Time.h new file mode 100644 index 0000000..42c06c5 --- /dev/null +++ b/src/system/Time.h @@ -0,0 +1,21 @@ +#ifndef TIME_H +#define TIME_H + +#include "system_global.h" + +namespace paysages { +namespace system { + +class SYSTEMSHARED_EXPORT Time +{ +public: + /** + * Get a timestamp in milliseconds. + */ + static unsigned long getRelativeTimeMs(); +}; + +} +} + +#endif // TIME_H diff --git a/src/system/system.pro b/src/system/system.pro index ca6f1aa..36fdf14 100644 --- a/src/system/system.pro +++ b/src/system/system.pro @@ -28,7 +28,8 @@ SOURCES += \ ParallelWorker.cpp \ Semaphore.cpp \ FileSystem.cpp \ - DataFile.cpp + DataFile.cpp \ + Time.cpp HEADERS += \ system_global.h \ @@ -46,7 +47,8 @@ HEADERS += \ ParallelWorker.h \ Semaphore.h \ FileSystem.h \ - DataFile.h + DataFile.h \ + Time.h unix:!symbian { maemo5 { diff --git a/src/system/system_global.h b/src/system/system_global.h index 97ef135..de9142b 100644 --- a/src/system/system_global.h +++ b/src/system/system_global.h @@ -23,6 +23,7 @@ namespace system { class Mutex; class Semaphore; class PictureWriter; + class Time; } } using namespace paysages::system;