summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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));