Added quick render to QtQuick UI
This commit is contained in:
parent
d0a5f19cc5
commit
06a8227de3
13 changed files with 401 additions and 4 deletions
|
@ -5,6 +5,11 @@
|
|||
#include "OpenGLRenderer.h"
|
||||
#include "AtmosphereModeler.h"
|
||||
#include "WaterModeler.h"
|
||||
#include "RenderPreviewProvider.h"
|
||||
#include "RenderProcess.h"
|
||||
#include "RenderConfig.h"
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
MainModelerWindow::MainModelerWindow()
|
||||
{
|
||||
|
@ -12,8 +17,13 @@ MainModelerWindow::MainModelerWindow()
|
|||
scenery->autoPreset();
|
||||
renderer = new OpenGLRenderer(scenery);
|
||||
|
||||
qmlRegisterType<OpenGLView>("Paysages", 1, 0, "OpenGLView");
|
||||
render_preview_provider = new RenderPreviewProvider();
|
||||
render_process = new RenderProcess(render_preview_provider);
|
||||
|
||||
qmlRegisterType<OpenGLView>("Paysages", 1, 0, "OpenGLView");
|
||||
engine()->addImageProvider("renderpreviewprovider", render_preview_provider);
|
||||
|
||||
setMinimumSize(QSize(1000, 800));
|
||||
setTitle(QObject::tr("Paysages 3D"));
|
||||
setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
setSource(QUrl("qrc:///main.qml"));
|
||||
|
@ -27,6 +37,9 @@ MainModelerWindow::~MainModelerWindow()
|
|||
delete atmosphere;
|
||||
delete water;
|
||||
|
||||
delete render_preview_provider;
|
||||
delete render_process;
|
||||
|
||||
delete renderer;
|
||||
delete scenery;
|
||||
}
|
||||
|
@ -35,3 +48,26 @@ QObject *MainModelerWindow::findQmlObject(const QString &objectName)
|
|||
{
|
||||
return rootObject()->findChild<QObject *>(objectName);
|
||||
}
|
||||
|
||||
void MainModelerWindow::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_F5)
|
||||
{
|
||||
// Start render in a thread
|
||||
render_process->startRender(scenery, RenderConfig(400, 300, 1, 3));
|
||||
|
||||
// Resize preview
|
||||
QSize preview_size = render_process->getPreviewSize();
|
||||
findQmlObject("preview_image")->setProperty("width", preview_size.width());
|
||||
findQmlObject("preview_image")->setProperty("height", preview_size.height());
|
||||
|
||||
// Show render dialog
|
||||
rootObject()->setProperty("state", QString("Render Dialog"));
|
||||
}
|
||||
else if (event->key() == Qt::Key_Escape)
|
||||
{
|
||||
render_process->stopRender();
|
||||
|
||||
rootObject()->setProperty("state", QString("Init"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,18 @@ public:
|
|||
inline Scenery *getScenery() const {return scenery;}
|
||||
inline OpenGLRenderer *getRenderer() const {return renderer;}
|
||||
|
||||
protected:
|
||||
virtual void keyReleaseEvent(QKeyEvent *event) override;
|
||||
|
||||
private:
|
||||
OpenGLRenderer *renderer;
|
||||
Scenery *scenery;
|
||||
|
||||
AtmosphereModeler *atmosphere;
|
||||
WaterModeler *water;
|
||||
|
||||
RenderPreviewProvider *render_preview_provider;
|
||||
RenderProcess *render_process;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
85
src/interface/modeler/quickapp/RenderPreviewProvider.cpp
Normal file
85
src/interface/modeler/quickapp/RenderPreviewProvider.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "RenderPreviewProvider.h"
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "CanvasPreview.h"
|
||||
#include "Color.h"
|
||||
|
||||
static inline QColor colorToQColor(Color color)
|
||||
{
|
||||
color.normalize();
|
||||
return QColor(color.r * 255.0, color.g * 255.0, color.b * 255.0, color.a * 255.0);
|
||||
}
|
||||
|
||||
RenderPreviewProvider::RenderPreviewProvider() :
|
||||
QQuickImageProvider(QQuickImageProvider::Image)
|
||||
{
|
||||
canvas = NULL;
|
||||
pixbuf = new QImage(1, 1, QImage::Format_ARGB32);
|
||||
}
|
||||
|
||||
RenderPreviewProvider::~RenderPreviewProvider()
|
||||
{
|
||||
delete pixbuf;
|
||||
}
|
||||
|
||||
QImage RenderPreviewProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
|
||||
{
|
||||
if (canvas)
|
||||
{
|
||||
canvas->getPreview()->updateLive(this);
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
*size = pixbuf->size();
|
||||
}
|
||||
|
||||
return *pixbuf;
|
||||
}
|
||||
|
||||
void RenderPreviewProvider::setCanvas(const Canvas *canvas)
|
||||
{
|
||||
if (not this->canvas)
|
||||
{
|
||||
this->canvas = canvas;
|
||||
canvas->getPreview()->initLive(this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPreviewProvider::releaseCanvas()
|
||||
{
|
||||
if (canvas)
|
||||
{
|
||||
canvas->getPreview()->updateLive(this);
|
||||
canvas = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPreviewProvider::setToneMapping(const ColorProfile &profile)
|
||||
{
|
||||
if (canvas)
|
||||
{
|
||||
canvas->getPreview()->setToneMapping(profile);
|
||||
canvas->getPreview()->updateLive(this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPreviewProvider::canvasResized(int width, int height)
|
||||
{
|
||||
if (QSize(width, height) != pixbuf->size())
|
||||
{
|
||||
delete pixbuf;
|
||||
pixbuf = new QImage(width, height, QImage::Format_ARGB32);
|
||||
pixbuf->fill(Qt::black);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPreviewProvider::canvasCleared(const Color &col)
|
||||
{
|
||||
pixbuf->fill(colorToQColor(col));
|
||||
}
|
||||
|
||||
void RenderPreviewProvider::canvasPainted(int x, int y, const Color &col)
|
||||
{
|
||||
pixbuf->setPixel(x, pixbuf->height() - 1 - y, colorToQColor(col).rgb());
|
||||
}
|
53
src/interface/modeler/quickapp/RenderPreviewProvider.h
Normal file
53
src/interface/modeler/quickapp/RenderPreviewProvider.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef RENDERPREVIEWPROVIDER_H
|
||||
#define RENDERPREVIEWPROVIDER_H
|
||||
|
||||
#include "modeler_global.h"
|
||||
|
||||
#include <QQuickImageProvider>
|
||||
#include "CanvasLiveClient.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace modeler {
|
||||
|
||||
/**
|
||||
* Provider for a Qml Image content, filled from a canvas rendering.
|
||||
*/
|
||||
class RenderPreviewProvider : public QQuickImageProvider, public CanvasLiveClient
|
||||
{
|
||||
public:
|
||||
RenderPreviewProvider();
|
||||
virtual ~RenderPreviewProvider();
|
||||
|
||||
/**
|
||||
* Set the canvas to watch and display, null to stop watching.
|
||||
*
|
||||
* This function must be called from the graphics thread.
|
||||
*/
|
||||
void setCanvas(const Canvas *canvas);
|
||||
|
||||
/**
|
||||
* Release the bound canvas.
|
||||
*/
|
||||
void releaseCanvas();
|
||||
|
||||
/**
|
||||
* Set the tone mapping to apply to pixel colors.
|
||||
*/
|
||||
void setToneMapping(const ColorProfile &profile);
|
||||
|
||||
protected:
|
||||
virtual QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
|
||||
|
||||
virtual void canvasResized(int width, int height) override;
|
||||
virtual void canvasCleared(const Color &col) override;
|
||||
virtual void canvasPainted(int x, int y, const Color &col) override;
|
||||
|
||||
private:
|
||||
QImage* pixbuf;
|
||||
const Canvas *canvas;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RENDERPREVIEWPROVIDER_H
|
111
src/interface/modeler/quickapp/RenderProcess.cpp
Normal file
111
src/interface/modeler/quickapp/RenderProcess.cpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
#include "RenderProcess.h"
|
||||
|
||||
#include <QSize>
|
||||
#include "SoftwareCanvasRenderer.h"
|
||||
#include "RenderPreviewProvider.h"
|
||||
#include "RenderConfig.h"
|
||||
#include "Thread.h"
|
||||
#include "Canvas.h"
|
||||
#include "CanvasPreview.h"
|
||||
|
||||
class RenderThread: public Thread
|
||||
{
|
||||
public:
|
||||
RenderThread(SoftwareCanvasRenderer *renderer): renderer(renderer)
|
||||
{
|
||||
}
|
||||
virtual void run() override
|
||||
{
|
||||
renderer->render();
|
||||
}
|
||||
private:
|
||||
SoftwareCanvasRenderer *renderer;
|
||||
};
|
||||
|
||||
RenderProcess::RenderProcess(RenderPreviewProvider *destination):
|
||||
destination(destination)
|
||||
{
|
||||
rendering = false;
|
||||
renderer = NULL;
|
||||
render_thread = NULL;
|
||||
|
||||
startTimer(100);
|
||||
}
|
||||
|
||||
RenderProcess::~RenderProcess()
|
||||
{
|
||||
if (rendering)
|
||||
{
|
||||
renderer->interrupt();
|
||||
}
|
||||
|
||||
rendering = false;
|
||||
|
||||
if (render_thread)
|
||||
{
|
||||
render_thread->join();
|
||||
delete render_thread;
|
||||
}
|
||||
|
||||
if (renderer)
|
||||
{
|
||||
delete renderer;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProcess::startRender(Scenery *scenery, const RenderConfig &config)
|
||||
{
|
||||
if (rendering)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rendering = true;
|
||||
|
||||
if (renderer)
|
||||
{
|
||||
delete renderer;
|
||||
}
|
||||
|
||||
renderer = new SoftwareCanvasRenderer();
|
||||
renderer->setScenery(scenery);
|
||||
renderer->setConfig(config);
|
||||
|
||||
destination->setCanvas(renderer->getCanvas());
|
||||
|
||||
render_thread = new RenderThread(renderer);
|
||||
render_thread->start();
|
||||
}
|
||||
|
||||
void RenderProcess::stopRender()
|
||||
{
|
||||
if (rendering)
|
||||
{
|
||||
renderer->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
const QSize RenderProcess::getPreviewSize()
|
||||
{
|
||||
if (renderer)
|
||||
{
|
||||
return QSize(renderer->getCanvas()->getPreview()->getWidth(), renderer->getCanvas()->getPreview()->getHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
return QSize(10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProcess::timerEvent(QTimerEvent *)
|
||||
{
|
||||
if (rendering and renderer->isFinished())
|
||||
{
|
||||
destination->releaseCanvas();
|
||||
rendering = false;
|
||||
|
||||
render_thread->join();
|
||||
delete render_thread;
|
||||
render_thread = NULL;
|
||||
}
|
||||
}
|
47
src/interface/modeler/quickapp/RenderProcess.h
Normal file
47
src/interface/modeler/quickapp/RenderProcess.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef RENDERPROCESS_H
|
||||
#define RENDERPROCESS_H
|
||||
|
||||
#include "modeler_global.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace paysages {
|
||||
namespace modeler {
|
||||
|
||||
class RenderProcess: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RenderProcess(RenderPreviewProvider *destination);
|
||||
virtual ~RenderProcess();
|
||||
|
||||
/**
|
||||
* Start the rendering process in a separate thread.
|
||||
*/
|
||||
void startRender(Scenery *scenery, const RenderConfig &config);
|
||||
|
||||
/**
|
||||
* Stop any currently running render.
|
||||
*/
|
||||
void stopRender();
|
||||
|
||||
/**
|
||||
* Get the size of the preview image.
|
||||
*/
|
||||
const QSize getPreviewSize();
|
||||
|
||||
protected:
|
||||
virtual void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
private:
|
||||
RenderPreviewProvider *destination;
|
||||
bool rendering;
|
||||
SoftwareCanvasRenderer *renderer;
|
||||
Thread *render_thread;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RENDERPROCESS_H
|
|
@ -12,6 +12,9 @@ namespace modeler {
|
|||
|
||||
class AtmosphereModeler;
|
||||
class WaterModeler;
|
||||
|
||||
class RenderPreviewProvider;
|
||||
class RenderProcess;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
27
src/interface/modeler/quickapp/qml/RenderDialog.qml
Normal file
27
src/interface/modeler/quickapp/qml/RenderDialog.qml
Normal file
|
@ -0,0 +1,27 @@
|
|||
import QtQuick 2.2
|
||||
|
||||
Rectangle {
|
||||
width: 400
|
||||
height: 300
|
||||
|
||||
Image {
|
||||
id: preview_image
|
||||
objectName: "preview_image"
|
||||
anchors.centerIn: parent
|
||||
width: 100
|
||||
height: 100
|
||||
source: ""
|
||||
cache: false
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 500
|
||||
running: true
|
||||
repeat: true
|
||||
|
||||
onTriggered: {
|
||||
preview_image.source = "";
|
||||
preview_image.source = "image://renderpreviewprovider/live";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,5 +25,6 @@
|
|||
<file>images/icon_atmosphere_night.png</file>
|
||||
<file>BaseChoice.qml</file>
|
||||
<file>BaseChoiceItem.qml</file>
|
||||
<file>RenderDialog.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -91,6 +91,12 @@ OpenGLView {
|
|||
}
|
||||
}
|
||||
|
||||
RenderDialog {
|
||||
id: render_dialog
|
||||
opacity: 0
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
PanelWaterLevel {
|
||||
id: panel_water_level
|
||||
tool: tool_water_level
|
||||
|
@ -127,6 +133,19 @@ OpenGLView {
|
|||
target: atmosphere_toolbar
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Render Dialog"
|
||||
when: tool_display.selected
|
||||
|
||||
PropertyChanges {
|
||||
target: primary_toolbar
|
||||
opacity: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: render_dialog
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@ SOURCES += main.cpp \
|
|||
OpenGLView.cpp \
|
||||
MainModelerWindow.cpp \
|
||||
WaterModeler.cpp \
|
||||
AtmosphereModeler.cpp
|
||||
AtmosphereModeler.cpp \
|
||||
RenderPreviewProvider.cpp \
|
||||
RenderProcess.cpp
|
||||
|
||||
RESOURCES += \
|
||||
qml/app.qrc
|
||||
|
@ -26,7 +28,9 @@ HEADERS += \
|
|||
modeler_global.h \
|
||||
MainModelerWindow.h \
|
||||
WaterModeler.h \
|
||||
AtmosphereModeler.h
|
||||
AtmosphereModeler.h \
|
||||
RenderPreviewProvider.h \
|
||||
RenderProcess.h
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../../system/release/ -lpaysages_system
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../../system/debug/ -lpaysages_system
|
||||
|
@ -69,4 +73,5 @@ OTHER_FILES += \
|
|||
qml/PanelAtmosphereDaytime.qml \
|
||||
qml/BaseSlider.qml \
|
||||
qml/BaseChoice.qml \
|
||||
qml/BaseChoiceItem.qml
|
||||
qml/BaseChoiceItem.qml \
|
||||
qml/RenderDialog.qml
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
SoftwareCanvasRenderer::SoftwareCanvasRenderer()
|
||||
{
|
||||
started = false;
|
||||
finished = false;
|
||||
interrupted = false;
|
||||
canvas = new Canvas();
|
||||
progress = 0.0;
|
||||
|
@ -95,6 +96,7 @@ void SoftwareCanvasRenderer::render()
|
|||
progress = (double)i / (double)n;
|
||||
}
|
||||
}
|
||||
finished = true;
|
||||
}
|
||||
|
||||
void SoftwareCanvasRenderer::interrupt()
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
|
||||
inline const Canvas *getCanvas() const {return canvas;}
|
||||
inline double getProgress() const {return progress;}
|
||||
inline bool isFinished() const {return finished;}
|
||||
|
||||
/**
|
||||
* Set the renderer configuration.
|
||||
|
@ -78,6 +79,7 @@ private:
|
|||
int samples;
|
||||
std::vector<Rasterizer*> rasterizers;
|
||||
bool started;
|
||||
bool finished;
|
||||
bool interrupted;
|
||||
|
||||
ParallelWork *current_work;
|
||||
|
|
Loading…
Reference in a new issue