summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@qt.io>2018-05-23 10:09:50 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2018-05-25 14:52:54 +0000
commitbd9e2b07b297c46b1e0b4a70a25b140ad9efadfd (patch)
treed148d4f7c1d16c0dd1ea58be91729a7e3ef082d7
parent17b1dd544706630c40f8ca75bfff3bf35bf1ec8b (diff)
Add support for using Q3DSViewerSettings in Q3DSEngine
Q3DSEngine has a reference to the Q3DSViewerSettings for usage in generating the viewport for the main presentation. This is used to make sure that the scene is rendered with the correct scale mode and matte if requested on the main presentation. Adds Menu items for scale modes and matte to Q3DSViewer Change-Id: I9f468c42fe846be8170dac01fcdf6d692aae19ab Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
-rw-r--r--src/imports/studio3d/q3dsstudio3ditem.cpp11
-rw-r--r--src/runtime/api/q3dssurfaceviewer.cpp8
-rw-r--r--src/runtime/api/q3dsviewersettings.cpp27
-rw-r--r--src/runtime/api/q3dsviewersettings.h4
-rw-r--r--src/runtime/api/q3dsviewersettings_p.h3
-rw-r--r--src/runtime/api/q3dswidget.cpp8
-rw-r--r--src/runtime/q3dsengine.cpp93
-rw-r--r--src/runtime/q3dsengine_p.h6
-rw-r--r--src/runtime/q3dsinputmanager.cpp16
-rw-r--r--src/runtime/q3dsinputmanager_p.h1
-rw-r--r--src/runtime/q3dsscenemanager.cpp86
-rw-r--r--src/runtime/q3dsscenemanager_p.h22
-rw-r--r--tools/q3dsviewer/q3dsmainwindow.cpp62
13 files changed, 303 insertions, 44 deletions
diff --git a/src/imports/studio3d/q3dsstudio3ditem.cpp b/src/imports/studio3d/q3dsstudio3ditem.cpp
index 1c16b89..7b4c0eb 100644
--- a/src/imports/studio3d/q3dsstudio3ditem.cpp
+++ b/src/imports/studio3d/q3dsstudio3ditem.cpp
@@ -242,10 +242,8 @@ void Q3DSStudio3DItem::componentComplete()
qWarning("Studio3D: Duplicate ViewerSettings");
} else {
m_viewerSettings = viewerSettings;
- connect(m_viewerSettings, &Q3DSViewerSettings::showRenderStatsChanged, m_viewerSettings, [this] {
- if (m_engine)
- m_engine->setProfileUiVisible(m_viewerSettings->isShowingRenderStats());
- });
+ if (m_engine)
+ m_engine->setViewerSettings(m_viewerSettings);
}
}
}
@@ -346,11 +344,12 @@ void Q3DSStudio3DItem::createEngine()
m_engine->setSurface(w);
}
+ if (m_viewerSettings)
+ m_engine->setViewerSettings(m_viewerSettings);
+
qCDebug(lcStudio3D, "created engine %p", m_engine);
connect(m_engine, &Q3DSEngine::presentationLoaded, this, [this]() {
- if (m_viewerSettings && m_viewerSettings->isShowingRenderStats())
- m_engine->setProfileUiVisible(true);
m_presentation->studio3DPresentationLoaded();
if (!m_running) {
m_running = true;
diff --git a/src/runtime/api/q3dssurfaceviewer.cpp b/src/runtime/api/q3dssurfaceviewer.cpp
index bbe6344..8ead5af 100644
--- a/src/runtime/api/q3dssurfaceviewer.cpp
+++ b/src/runtime/api/q3dssurfaceviewer.cpp
@@ -469,11 +469,6 @@ Q3DSSurfaceViewerPrivate::Q3DSSurfaceViewerPrivate()
viewerSettings(new Q3DSViewerSettings)
{
Q3DSPresentationPrivate::get(presentation)->setController(this);
-
- QObject::connect(viewerSettings, &Q3DSViewerSettings::showRenderStatsChanged, viewerSettings, [this] {
- if (engine)
- engine->setProfileUiVisible(viewerSettings->isShowingRenderStats());
- });
}
Q3DSSurfaceViewerPrivate::~Q3DSSurfaceViewerPrivate()
@@ -511,6 +506,7 @@ bool Q3DSSurfaceViewerPrivate::createEngine()
return false;
}
engine->setSurface(windowOrOffscreenSurface);
+ engine->setViewerSettings(viewerSettings);
qCDebug(lc3DSSurface, "Created engine %p", engine);
@@ -528,8 +524,6 @@ bool Q3DSSurfaceViewerPrivate::createEngine()
QObject::connect(engine, &Q3DSEngine::presentationLoaded, engine, [this] {
Q_Q(Q3DSSurfaceViewer);
- if (viewerSettings->isShowingRenderStats())
- engine->setProfileUiVisible(true);
emit q->presentationLoaded();
});
diff --git a/src/runtime/api/q3dsviewersettings.cpp b/src/runtime/api/q3dsviewersettings.cpp
index c6c65fd..26844b4 100644
--- a/src/runtime/api/q3dsviewersettings.cpp
+++ b/src/runtime/api/q3dsviewersettings.cpp
@@ -92,6 +92,19 @@ Q3DSViewerSettings::~Q3DSViewerSettings()
\note This property is currently ignored.
*/
+
+/*!
+ \property Q3DSViewerSettings::matteEnabled
+
+ \note This property is currently ignored.
+ */
+
+bool Q3DSViewerSettings::matteEnabled() const
+{
+ Q_D(const Q3DSViewerSettings);
+ return d->matteEnabled;
+}
+
QColor Q3DSViewerSettings::matteColor() const
{
Q_D(const Q3DSViewerSettings);
@@ -128,8 +141,6 @@ Q3DSViewerSettings::ShadeMode Q3DSViewerSettings::shadeMode() const
/*!
\property Q3DSViewerSettings::scaleMode
-
- \note This property is currently ignored.
*/
Q3DSViewerSettings::ScaleMode Q3DSViewerSettings::scaleMode() const
{
@@ -137,11 +148,20 @@ Q3DSViewerSettings::ScaleMode Q3DSViewerSettings::scaleMode() const
return d->scaleMode;
}
+
+void Q3DSViewerSettings::setMatteEnabled(bool isEnabled)
+{
+ Q_D(Q3DSViewerSettings);
+ if (d->matteEnabled != isEnabled) {
+ d->matteEnabled = isEnabled;
+ emit matteEnabledChanged();
+ }
+}
+
void Q3DSViewerSettings::setMatteColor(const QColor &color)
{
Q_D(Q3DSViewerSettings);
if (d->matteColor != color) {
- qWarning() << Q_FUNC_INFO << "not implemented";
d->matteColor = color;
emit matteColorChanged();
}
@@ -170,7 +190,6 @@ void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode)
{
Q_D(Q3DSViewerSettings);
if (d->scaleMode != mode) {
- qWarning() << Q_FUNC_INFO << "not implemented";
d->scaleMode = mode;
emit scaleModeChanged();
}
diff --git a/src/runtime/api/q3dsviewersettings.h b/src/runtime/api/q3dsviewersettings.h
index de64393..044c436 100644
--- a/src/runtime/api/q3dsviewersettings.h
+++ b/src/runtime/api/q3dsviewersettings.h
@@ -46,6 +46,7 @@ class Q3DSViewerSettingsPrivate;
class Q3DSV_EXPORT Q3DSViewerSettings : public QObject
{
Q_OBJECT
+ Q_PROPERTY(bool matteEnabled READ matteEnabled WRITE setMatteEnabled NOTIFY matteEnabledChanged)
Q_PROPERTY(QColor matteColor READ matteColor WRITE setMatteColor NOTIFY matteColorChanged)
Q_PROPERTY(bool showRenderStats READ isShowingRenderStats WRITE setShowRenderStats NOTIFY showRenderStatsChanged)
Q_PROPERTY(ShadeMode shadeMode READ shadeMode WRITE setShadeMode NOTIFY shadeModeChanged)
@@ -68,6 +69,7 @@ public:
explicit Q3DSViewerSettings(QObject *parent = nullptr);
~Q3DSViewerSettings();
+ bool matteEnabled() const;
QColor matteColor() const;
bool isShowingRenderStats() const;
ShadeMode shadeMode() const;
@@ -81,12 +83,14 @@ public:
const QString &application = QString());
public Q_SLOTS:
+ void setMatteEnabled(bool isEnabled);
void setMatteColor(const QColor &color);
void setShowRenderStats(bool show);
void setShadeMode(ShadeMode mode);
void setScaleMode(ScaleMode mode);
Q_SIGNALS:
+ void matteEnabledChanged();
void matteColorChanged();
void showRenderStatsChanged();
void shadeModeChanged();
diff --git a/src/runtime/api/q3dsviewersettings_p.h b/src/runtime/api/q3dsviewersettings_p.h
index a4464cf..9255d35 100644
--- a/src/runtime/api/q3dsviewersettings_p.h
+++ b/src/runtime/api/q3dsviewersettings_p.h
@@ -54,7 +54,8 @@ class Q3DSV_PRIVATE_EXPORT Q3DSViewerSettingsPrivate : public QObjectPrivate
public:
static Q3DSViewerSettingsPrivate *get(Q3DSViewerSettings *p) { return p->d_func(); }
- QColor matteColor = Qt::black;
+ bool matteEnabled = false;
+ QColor matteColor = QColor(51, 51, 51);
bool showRenderStats = false;
Q3DSViewerSettings::ShadeMode shadeMode = Q3DSViewerSettings::ShadeModeShaded;
Q3DSViewerSettings::ScaleMode scaleMode = Q3DSViewerSettings::ScaleModeFill;
diff --git a/src/runtime/api/q3dswidget.cpp b/src/runtime/api/q3dswidget.cpp
index 56d65d5..7381ce5 100644
--- a/src/runtime/api/q3dswidget.cpp
+++ b/src/runtime/api/q3dswidget.cpp
@@ -325,11 +325,6 @@ Q3DSWidgetPrivate::Q3DSWidgetPrivate(Q3DSWidget *q)
{
Q3DSPresentationPrivate::get(presentation)->setController(this);
- QObject::connect(viewerSettings, &Q3DSViewerSettings::showRenderStatsChanged, viewerSettings, [this] {
- if (engine)
- engine->setProfileUiVisible(viewerSettings->isShowingRenderStats());
- });
-
typedef void (QWidget::*QWidgetVoidSlot)();
QObject::connect(&updateTimer, &QTimer::timeout, q, static_cast<QWidgetVoidSlot>(&QWidget::update));
updateTimer.setInterval(updateInterval);
@@ -355,6 +350,7 @@ void Q3DSWidgetPrivate::createEngine()
engine->setAutoToggleProfileUi(false); // up to the app to control this via the API instead
engine->setSurface(q_ptr->window()->windowHandle());
+ engine->setViewerSettings(viewerSettings);
qCDebug(lc3DSWidget, "Created engine %p", engine);
initializePresentationController(engine, presentation);
@@ -366,8 +362,6 @@ void Q3DSWidgetPrivate::createEngine()
engine->resize(sz);
QObject::connect(engine, &Q3DSEngine::presentationLoaded, engine, [this] {
- if (viewerSettings->isShowingRenderStats())
- engine->setProfileUiVisible(true);
emit q_ptr->presentationLoaded();
});
diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp
index 20d9b0e..b58140b 100644
--- a/src/runtime/q3dsengine.cpp
+++ b/src/runtime/q3dsengine.cpp
@@ -34,12 +34,14 @@
#include "q3dslogging_p.h"
#include "q3dsinputmanager_p.h"
#include "q3dsinlineqmlsubpresentation_p.h"
+#include "q3dsviewersettings.h"
#include <QLoggingCategory>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
+#include <QtMath>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
@@ -158,6 +160,7 @@ Q3DSEngine::Q3DSEngine()
const bool logValueChanges = qEnvironmentVariableIntValue("Q3DS_DEBUG") >= 1;
const_cast<QLoggingCategory &>(lcUipProp()).setEnabled(QtDebugMsg, logValueChanges);
}
+ setViewerSettings(new Q3DSViewerSettings(this));
}
Q3DSEngine::~Q3DSEngine()
@@ -752,6 +755,7 @@ bool Q3DSEngine::buildUipPresentationScene(UipPresentation *pres)
params.outputDpr = effectiveDpr;
params.surface = m_surface;
params.engine = this;
+ params.viewport = calculateViewport(effectiveSize, m_implicitSize);
QScopedPointer<Q3DSSceneManager> sceneManager(new Q3DSSceneManager);
pres->q3dscene = sceneManager->buildScene(pres->presentation, params);
@@ -775,7 +779,11 @@ bool Q3DSEngine::buildUipPresentationScene(UipPresentation *pres)
// Generate a resize to make sure everything size-related gets updated.
// (avoids issues with camera upon loading new scenes)
- pres->sceneManager->updateSizes(effectiveSize, effectiveDpr);
+ pres->sceneManager->updateSizes(effectiveSize, effectiveDpr, params.viewport);
+
+ // Set matte preferences
+ pres->sceneManager->setMatteEnabled(m_viewerSettings->matteEnabled());
+ pres->sceneManager->setMatteColor(m_viewerSettings->matteColor());
// Expose update signal
connect(pres->q3dscene.frameAction, &Qt3DLogic::QFrameAction::triggered, this, [this](float dt) {
@@ -1109,7 +1117,6 @@ void Q3DSEngine::destroy()
// wish I knew why this is needed. Qt 3D tends not to shut down its threads correctly on exit otherwise.
if (m_aspectEngine)
Qt3DCore::QAspectEnginePrivate::get(m_aspectEngine.data())->exitSimulationLoop();
-
m_aspectEngine.reset();
}
@@ -1188,6 +1195,36 @@ Qt3DCore::QEntity *Q3DSEngine::rootEntity() const
return m_uipPresentations.isEmpty() ? nullptr : m_uipPresentations[0].q3dscene.rootEntity;
}
+Q3DSViewerSettings *Q3DSEngine::viewerSettings() const
+{
+ return m_viewerSettings;
+}
+
+void Q3DSEngine::setViewerSettings(Q3DSViewerSettings *viewerSettings)
+{
+ if (m_viewerSettings == viewerSettings)
+ return;
+
+ m_viewerSettings = viewerSettings;
+ connect(m_viewerSettings, &Q3DSViewerSettings::showRenderStatsChanged, [this] {
+ setProfileUiVisible(m_viewerSettings->isShowingRenderStats());
+ });
+ connect(m_viewerSettings, &Q3DSViewerSettings::scaleModeChanged, [this] {
+ // Force a resize
+ resize(m_size, m_dpr);
+ });
+ connect(m_viewerSettings, &Q3DSViewerSettings::matteEnabledChanged, [this] {
+ if (!m_uipPresentations.isEmpty()) {
+ m_uipPresentations[0].sceneManager->setMatteEnabled(m_viewerSettings->matteEnabled());
+ }
+ });
+ connect(m_viewerSettings, &Q3DSViewerSettings::matteColorChanged, [this] {
+ if (!m_uipPresentations.isEmpty()) {
+ m_uipPresentations[0].sceneManager->setMatteColor(m_viewerSettings->matteColor());
+ }
+ });
+}
+
void Q3DSEngine::setOnDemandRendering(bool enabled)
{
if (m_onDemandRendering == enabled)
@@ -1228,8 +1265,13 @@ void Q3DSEngine::resize(const QSize &size, qreal dpr, bool forceSynchronous)
{
m_size = size;
m_dpr = dpr;
- if (!m_uipPresentations.isEmpty())
- m_uipPresentations[0].sceneManager->updateSizes(m_size, m_dpr, forceSynchronous);
+
+ if (!m_uipPresentations.isEmpty()) {
+ const QSize presentationSize(m_uipPresentations[0].presentation->presentationWidth(),
+ m_uipPresentations[0].presentation->presentationHeight());
+ const QRect viewport = calculateViewport(m_size, presentationSize);
+ m_uipPresentations[0].sceneManager->updateSizes(m_size, m_dpr, viewport, forceSynchronous);
+ }
}
void Q3DSEngine::setAutoStart(bool autoStart)
@@ -1644,6 +1686,49 @@ void Q3DSEngine::behaviorFrameUpdate(float dt)
}
}
+QRect Q3DSEngine::calculateViewport(const QSize &surfaceSize, const QSize &presentationSize) const
+{
+ // The top level persentations viewport depends on the scale mode of
+ // the Q3DSViewerSettings. The method returns the viewport rect based
+ // on the current surface size and scale mode.
+
+ // We need to have the presentation size
+ if (presentationSize.isNull())
+ return QRect();
+
+ QRect viewportRect;
+ if (m_viewerSettings->scaleMode() == Q3DSViewerSettings::ScaleModeFill) {
+ // the presentation is always rendered to fill the viewport
+ viewportRect = QRect(0, 0, surfaceSize.width(), surfaceSize.height());
+ } else if (m_viewerSettings->scaleMode() == Q3DSViewerSettings::ScaleModeCenter) {
+ // the presentation is rendered at the size specified in Studio. Additional content is cropped,
+ // additional space is letterboxed.
+ const qreal presHorizontalCenter = presentationSize.width() * 0.5;
+ const qreal presVerticalCenter = presentationSize.height() * 0.5;
+ const qreal surfaceHorizontalCenter = surfaceSize.width() * 0.5;
+ const qreal surfaceVerticalCenter = surfaceSize.height() * 0.5;
+ const qreal x = surfaceHorizontalCenter - presHorizontalCenter;
+ const qreal y = surfaceVerticalCenter - presVerticalCenter;
+ viewportRect = QRect(qFloor(x), qFloor(y), presentationSize.width(), presentationSize.height());
+ } else if (m_viewerSettings->scaleMode() == Q3DSViewerSettings::ScaleModeFit) {
+ // the aspect ratio of the presentation is preserved, letterboxing as needed.
+ const qreal presentationAspectRatio = qreal(presentationSize.width()) / qreal(presentationSize.height());
+ const qreal surfaceAspectRatio = qreal(surfaceSize.width()) / qreal(surfaceSize.height());
+ int width = surfaceSize.width();
+ int height = surfaceSize.height();
+ if (presentationAspectRatio > surfaceAspectRatio)
+ height = int(surfaceSize.width() / presentationAspectRatio);
+ else
+ width = int(surfaceSize.height() * presentationAspectRatio);
+ viewportRect = QRect((surfaceSize.width() - width) / 2,
+ (surfaceSize.height() - height) / 2,
+ width,
+ height);
+ }
+
+ return viewportRect;
+}
+
// Object reference format used by behaviors and some public API:
//
// (presentationName:)?(parent|this|(Scene|Slide)(\..)*|(.)*)
diff --git a/src/runtime/q3dsengine_p.h b/src/runtime/q3dsengine_p.h
index 841e5e1..2a602b9 100644
--- a/src/runtime/q3dsengine_p.h
+++ b/src/runtime/q3dsengine_p.h
@@ -61,6 +61,7 @@ class QTabletEvent;
class QQmlEngine;
class QQmlComponent;
class Q3DSInlineQmlSubPresentation;
+class Q3DSViewerSettings;
namespace Qt3DRender {
class QRenderCapture;
@@ -134,6 +135,9 @@ public:
Qt3DCore::QAspectEngine *aspectEngine() const;
Qt3DCore::QEntity *rootEntity() const;
+ Q3DSViewerSettings *viewerSettings() const;
+ void setViewerSettings(Q3DSViewerSettings *viewerSettings);
+
void setOnDemandRendering(bool enabled);
QSize implicitSize() const;
@@ -244,6 +248,7 @@ private:
void loadBehaviors();
void destroyBehaviorHandle(const Q3DSBehaviorHandle &h);
void behaviorFrameUpdate(float dt);
+ QRect calculateViewport(const QSize &surfaceSize, const QSize &presentationSize) const;
QObject *m_surface = nullptr;
QSize m_implicitSize;
@@ -279,6 +284,7 @@ private:
BehaviorMap m_behaviorHandles;
bool m_onDemandRendering = false;
+ Q3DSViewerSettings *m_viewerSettings = nullptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Q3DSEngine::Flags)
diff --git a/src/runtime/q3dsinputmanager.cpp b/src/runtime/q3dsinputmanager.cpp
index 774ad14..315b27c 100644
--- a/src/runtime/q3dsinputmanager.cpp
+++ b/src/runtime/q3dsinputmanager.cpp
@@ -47,14 +47,14 @@ Q3DSInputManager::Q3DSInputManager(Q3DSSceneManager *sceneManager, QObject *pare
void Q3DSInputManager::handleMousePressEvent(QMouseEvent *e)
{
m_currentState.mousePressed = true;
- PickRequest req(e->pos() * m_sceneManager->m_guiData.outputDpr, m_currentState);
+ PickRequest req(convertToViewportSpace(e->pos()), m_currentState);
m_pickRequests.append(req);
}
void Q3DSInputManager::handleMouseReleaseEvent(QMouseEvent *e)
{
m_currentState.mousePressed = false;
- PickRequest req(e->pos() * m_sceneManager->m_guiData.outputDpr, m_currentState);
+ PickRequest req(convertToViewportSpace(e->pos()), m_currentState);
m_pickRequests.append(req);
}
@@ -63,7 +63,7 @@ void Q3DSInputManager::handleMouseMoveEvent(QMouseEvent *e)
if (!m_isHoverEnabled && !m_currentState.mousePressed)
return;
- PickRequest req(e->pos() * m_sceneManager->m_guiData.outputDpr, m_currentState);
+ PickRequest req(convertToViewportSpace(e->pos()), m_currentState);
m_pickRequests.append(req);
}
@@ -224,6 +224,16 @@ Q3DSGraphObject *Q3DSInputManager::getNodeForEntity(Q3DSLayerNode *layer, Qt3DCo
return nullptr;
}
+QPoint Q3DSInputManager::convertToViewportSpace(const QPoint &point) const
+{
+ QPoint convertedPoint;
+ convertedPoint.setX(point.x() - m_sceneManager->m_viewportData.viewportRect.x());
+ convertedPoint.setY(point.y() - m_sceneManager->m_viewportData.viewportRect.y());
+
+ // adjust point for device pixel ratio
+ return convertedPoint * m_sceneManager->m_viewportData.viewportDpr;
+}
+
void Q3DSInputManager::pick(const QPoint &point, const InputState &inputState)
{
// Get a list of layers in this scene (in order)
diff --git a/src/runtime/q3dsinputmanager_p.h b/src/runtime/q3dsinputmanager_p.h
index 13199f9..b3b8b26 100644
--- a/src/runtime/q3dsinputmanager_p.h
+++ b/src/runtime/q3dsinputmanager_p.h
@@ -85,6 +85,7 @@ private:
void castRayIntoLayer(Q3DSLayerNode *layer, const QPointF &pos, const InputState &inputState, int eventId);
void sendMouseEvent(Q3DSGraphObject *target, const Qt3DRender::QRayCasterHit &hit, const InputState &inputState);
Q3DSGraphObject *getNodeForEntity(Q3DSLayerNode *layer, Qt3DCore::QEntity *entity);
+ QPoint convertToViewportSpace(const QPoint &point) const;
Q3DSSceneManager *m_sceneManager = nullptr;
bool m_isHoverEnabled = false;
diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp
index 6008af5..22b51b2 100644
--- a/src/runtime/q3dsscenemanager.cpp
+++ b/src/runtime/q3dsscenemanager.cpp
@@ -74,6 +74,7 @@
#include <Qt3DRender/QGraphicsApiFilter>
#include <Qt3DRender/QRenderPass>
#include <Qt3DRender/QRenderPassFilter>
+#include <Qt3DRender/QRenderStateSet>
#include <Qt3DRender/QFilterKey>
#include <Qt3DRender/QNoDraw>
#include <Qt3DRender/QFrontFace>
@@ -90,6 +91,7 @@
#include <Qt3DRender/QStencilMask>
#include <Qt3DRender/QStencilOperation>
#include <Qt3DRender/QStencilOperationArguments>
+#include <Qt3DRender/QScissorTest>
#include <Qt3DRender/QRayCaster>
#include <Qt3DAnimation/QClipAnimator>
@@ -466,20 +468,44 @@ Q3DSSceneManager::~Q3DSSceneManager()
delete m_inputManager;
}
-void Q3DSSceneManager::updateSizes(const QSize &size, qreal dpr, bool forceSynchronous)
+void Q3DSSceneManager::updateSizes(const QSize &size, qreal dpr, const QRect &viewport, bool forceSynchronous)
{
if (!m_scene)
return;
- qCDebug(lcScene) << "Resize to" << size << "device pixel ratio" << dpr;
+ // Setup the matte and scene viewport
+ QRectF normalizedViewport;
+ if (viewport.isNull())
+ normalizedViewport = QRectF(0, 0, 1, 1);
+ else
+ normalizedViewport = QRectF(viewport.x() / qreal(size.width()),
+ viewport.y() / qreal(size.height()),
+ viewport.width() / qreal(size.width()),
+ viewport.height() / qreal(size.height()));
+
+ if (m_viewportData.viewport)
+ m_viewportData.viewport->setNormalizedRect(normalizedViewport);
+
+ m_viewportData.viewportRect = viewport;
+ m_viewportData.viewportDpr = dpr;
+ if (m_viewportData.matteScissorTest) {
+ m_viewportData.matteScissorTest->setBottom(qFloor(-(viewport.height() + viewport.y() - size.height()) * dpr));
+ m_viewportData.matteScissorTest->setLeft(qFloor(viewport.x() * dpr));
+ m_viewportData.matteScissorTest->setWidth(qFloor(viewport.width() * dpr));
+ m_viewportData.matteScissorTest->setHeight(qFloor(viewport.height() * dpr));
+ }
+
+ qCDebug(lcScene) << "Resize to" << size << "with viewport" << viewport << "device pixel ratio" << dpr;
+
+ m_outputPixelSize = viewport.size() * dpr;
- m_outputPixelSize = size * dpr;
+ // m_guiData uses the full surface size (not viewport)
m_guiData.outputSize = size;
m_guiData.outputDpr = dpr;
if (m_guiData.camera) {
- m_guiData.camera->setRight(m_outputPixelSize.width());
- m_guiData.camera->setBottom(m_outputPixelSize.height());
+ m_guiData.camera->setRight(size.width() * float(dpr));
+ m_guiData.camera->setBottom(size.height() * float(dpr));
}
for (auto callback : m_compositorOutputSizeChangeCallbacks)
@@ -682,8 +708,10 @@ Q3DSSceneManager::Scene Q3DSSceneManager::buildScene(Q3DSUipPresentation *presen
subPresFrameGraphRoot = nullptr;
Q_ASSERT(frameGraphRoot);
}
-
- m_outputPixelSize = params.outputSize * params.outputDpr;
+ if (params.viewport.isNull())
+ m_outputPixelSize = params.outputSize * params.outputDpr;
+ else
+ m_outputPixelSize = params.viewport.size() * params.outputDpr;
m_guiData.outputSize = params.outputSize;
m_guiData.outputDpr = params.outputDpr;
@@ -3269,8 +3297,18 @@ void Q3DSSceneManager::buildCompositor(Qt3DRender::QFrameGraphNode *parent, Qt3D
// ...
// With standard blend modes only this is simplified to a single LayerFilter and QLayer tag.
- Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(parent);
- viewport->setNormalizedRect(QRectF(0, 0, 1, 1));
+ // If Matte is enabled in the ViewerSettings, then we need clear with the matte color first
+ // then later restrict the scene clear color to the vieport rect with a scissor test
+ m_viewportData.drawMatteNode = new Qt3DRender::QFrameGraphNode(parent);
+ new Qt3DRender::QNoDraw(m_viewportData.drawMatteNode);
+ m_viewportData.dummyMatteRoot = new Qt3DCore::QNode(m_rootEntity);
+ m_viewportData.matteClearBuffers = new Qt3DRender::QClearBuffers(m_viewportData.dummyMatteRoot);
+ m_viewportData.matteClearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthStencilBuffer);
+ m_viewportData.matteClearBuffers->setClearColor(Qt::black);
+ new Qt3DRender::QNoDraw(m_viewportData.matteClearBuffers);
+
+ m_viewportData.viewport = new Qt3DRender::QViewport(parent);
+ m_viewportData.viewport->setNormalizedRect(QRectF(0, 0, 1, 1));
Qt3DRender::QCamera *camera = new Qt3DRender::QCamera;
camera->setObjectName(QLatin1String("compositor camera"));
@@ -3282,10 +3320,15 @@ void Q3DSSceneManager::buildCompositor(Qt3DRender::QFrameGraphNode *parent, Qt3D
camera->setPosition(QVector3D(0, 0, 1));
camera->setViewCenter(QVector3D(0, 0, 0));
- Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector(viewport);
+ Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector(m_viewportData.viewport);
cameraSelector->setCamera(camera);
- Qt3DRender::QClearBuffers *clearBuffers = new Qt3DRender::QClearBuffers(cameraSelector);
+ m_viewportData.matteRenderState = new Qt3DRender::QRenderStateSet(cameraSelector);
+ m_viewportData.matteRenderState->setEnabled(false);
+ m_viewportData.matteScissorTest = new Qt3DRender::QScissorTest(m_viewportData.matteRenderState);
+ m_viewportData.matteRenderState->addRenderState(m_viewportData.matteScissorTest);
+
+ Qt3DRender::QClearBuffers *clearBuffers = new Qt3DRender::QClearBuffers(m_viewportData.matteRenderState);
clearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthStencilBuffer);
QColor clearColor = Qt::transparent;
if (m_scene->useClearColor()) {
@@ -7172,6 +7215,27 @@ void Q3DSSceneManager::configureProfileUi(float scale)
#endif
}
+void Q3DSSceneManager::setMatteEnabled(bool isEnabled)
+{
+ if (!m_viewportData.drawMatteNode)
+ return;
+
+ if (isEnabled) {
+ // Attached the matteClearBuffers to the drawMatteNode placeholder
+ m_viewportData.matteClearBuffers->setParent(m_viewportData.drawMatteNode);
+ m_viewportData.matteRenderState->setEnabled(true);
+ } else {
+ m_viewportData.matteClearBuffers->setParent(m_viewportData.dummyMatteRoot);
+ m_viewportData.matteRenderState->setEnabled(false);
+ }
+}
+
+void Q3DSSceneManager::setMatteColor(const QColor &color)
+{
+ if (m_viewportData.matteClearBuffers)
+ m_viewportData.matteClearBuffers->setClearColor(color);
+}
+
void Q3DSSceneManager::addLog(const QString &msg)
{
#if QT_CONFIG(q3ds_profileui)
diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h
index 1faf985..fd565b9 100644
--- a/src/runtime/q3dsscenemanager_p.h
+++ b/src/runtime/q3dsscenemanager_p.h
@@ -96,6 +96,9 @@ class QTechnique;
class QFilterKey;
class QRenderState;
class QRayCaster;
+class QViewport;
+class QScissorTest;
+class QRenderStateSet;
}
namespace Qt3DExtras {
@@ -611,6 +614,18 @@ struct Q3DSGuiData
qreal outputDpr = 1;
};
+struct Q3DSViewportData
+{
+ Qt3DRender::QFrameGraphNode *drawMatteNode = nullptr;
+ Qt3DRender::QClearBuffers *matteClearBuffers = nullptr;
+ Qt3DRender::QRenderStateSet *matteRenderState = nullptr;
+ Qt3DRender::QScissorTest *matteScissorTest = nullptr;
+ Qt3DCore::QNode *dummyMatteRoot = nullptr;
+ Qt3DRender::QViewport *viewport = nullptr;
+ qreal viewportDpr = 1;
+ QRect viewportRect;
+};
+
class Q3DSV_PRIVATE_EXPORT Q3DSSceneManager
{
public:
@@ -628,6 +643,7 @@ public:
QObject *surface = nullptr; // null for subpresentations that go into a texture
Qt3DRender::QFrameGraphNode *frameGraphRoot = nullptr; // when !window
Q3DSEngine *engine = nullptr;
+ QRect viewport;
};
struct Scene {
@@ -643,7 +659,7 @@ public:
Scene buildScene(Q3DSUipPresentation *presentation, const SceneBuilderParams &params);
void finalizeMainScene(const QVector<Q3DSSubPresentation> &subPresentations);
- void updateSizes(const QSize &size, qreal dpr, bool forceSynchronous = false);
+ void updateSizes(const QSize &size, qreal dpr, const QRect &viewport = QRect(), bool forceSynchronous = false);
void prepareEngineReset();
static void prepareEngineResetGlobal();
@@ -700,6 +716,9 @@ public:
void setProfileUiInputEventSource(QObject *obj);
void configureProfileUi(float scale);
+ void setMatteEnabled(bool isEnabled);
+ void setMatteColor(const QColor &color);
+
Q3DSInputManager *inputManager() { return m_inputManager; }
// for testing from the viewer - to be moved private later
@@ -873,6 +892,7 @@ private:
bool m_layerCaching = true;
bool m_layerUncachePending = false;
QSet<Q3DSSceneManager *> m_layerCacheDeps;
+ Q3DSViewportData m_viewportData;
friend class Q3DSFrameUpdater;
friend class Q3DSProfiler;
diff --git a/tools/q3dsviewer/q3dsmainwindow.cpp b/tools/q3dsviewer/q3dsmainwindow.cpp
index e89c7b8..e91f59d 100644
--- a/tools/q3dsviewer/q3dsmainwindow.cpp
+++ b/tools/q3dsviewer/q3dsmainwindow.cpp
@@ -33,6 +33,7 @@
#include <private/q3dsengine_p.h>
#include <private/q3dsutils_p.h>
#include <private/q3dsslideplayer_p.h>
+#include <Qt3DStudioRuntime2/Q3DSViewerSettings>
#include <QApplication>
#include <QMenuBar>
#include <QMenu>
@@ -106,7 +107,68 @@ Q3DStudioMainWindow::Q3DStudioMainWindow(Q3DSWindow *view, Q3DSRemoteDeploymentM
}
});
}
+ QAction *showMatte = viewMenu->addAction(tr("Show Matte"));
+ showMatte->setCheckable(true);
+ showMatte->setChecked(false);
+ showMatte->setShortcut(QKeySequence(tr("Ctrl+D")));
+ connect(showMatte, &QAction::toggled, [=]() {
+ view->engine()->viewerSettings()->setMatteEnabled(showMatte->isChecked());
+ });
+ QAction *scaleModeAction = new QAction(tr("Scale Mode"));
+ scaleModeAction->setShortcut(QKeySequence(tr("Ctrl+Shift+S")));
+ QMenu *scaleModeMenu = new QMenu();
+ scaleModeAction->setMenu(scaleModeMenu);
+ QAction *scaleModeCenter = new QAction(tr("Center"));
+ scaleModeCenter->setCheckable(true);
+ scaleModeCenter->setChecked(false);
+ scaleModeMenu->addAction(scaleModeCenter);
+
+ QAction *scaleModeFit = new QAction(tr("Scale to Fit"));
+ scaleModeFit->setCheckable(true);
+ scaleModeFit->setChecked(false);
+ scaleModeMenu->addAction(scaleModeFit);
+
+ QAction *scaleModeFill = new QAction(tr("Scale to Fill"));
+ scaleModeFill->setCheckable(true);
+ scaleModeFill->setChecked(true);
+ scaleModeMenu->addAction(scaleModeFill);
+
+ connect(scaleModeFit, &QAction::triggered, [=]() {
+ view->engine()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+ scaleModeCenter->setChecked(false);
+ scaleModeFill->setChecked(false);
+ scaleModeFit->setChecked(true);
+ });
+ connect(scaleModeCenter, &QAction::triggered, [=]() {
+ view->engine()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeCenter);
+ scaleModeCenter->setChecked(true);
+ scaleModeFill->setChecked(false);
+ scaleModeFit->setChecked(false);
+ });
+ connect(scaleModeFill, &QAction::triggered, [=]() {
+ view->engine()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ scaleModeCenter->setChecked(false);
+ scaleModeFill->setChecked(true);
+ scaleModeFit->setChecked(false);
+ });
+ connect(scaleModeAction, &QAction::triggered, [=]() {
+ // toggle between the 3 scale modes
+ if (scaleModeCenter->isChecked()) {
+ scaleModeCenter->setChecked(false);
+ scaleModeFit->setChecked(true);
+ view->engine()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+ } else if (scaleModeFit->isChecked()) {
+ scaleModeFit->setChecked(false);
+ scaleModeFill->setChecked(true);
+ view->engine()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ } else {
+ scaleModeFill->setChecked(false);
+ scaleModeCenter->setChecked(true);
+ view->engine()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeCenter);
+ }
+ });
+ viewMenu->addMenu(scaleModeMenu);
viewMenu->addAction(tr("Toggle Full Scree&n"), this, [this] {
Qt::WindowStates s = windowState();
s.setFlag(Qt::WindowFullScreen, !s.testFlag(Qt::WindowFullScreen));