diff options
author | Antti Kokko <antti.kokko@qt.io> | 2020-06-25 07:32:53 +0300 |
---|---|---|
committer | Antti Kokko <antti.kokko@qt.io> | 2020-06-25 07:32:53 +0300 |
commit | dd9baa255af6aff800e536781bce369fcc8a3547 (patch) | |
tree | 224c0d11aa0e82eb609bcff0eacc1d42b95604f9 | |
parent | 02e4d56d055d73340d3af1257b908a52aecc320f (diff) | |
parent | 1c2f256c2afd320bec7e94bfc94760892d6fc9e8 (diff) |
Merge branch '2.7'
Change-Id: I72499b82b0238c09486177f7c022f5d27896a2c8
38 files changed, 384 insertions, 121 deletions
diff --git a/commonplatform.pri b/commonplatform.pri index 732d874..f1a114c 100644 --- a/commonplatform.pri +++ b/commonplatform.pri @@ -62,7 +62,6 @@ linux-clang { macos { DEFINES += _MACOSX _LINUXPLATFORM WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T - INCLUDEPATH += /usr/local/include # macOS builds treat most warnings as errors to prevent slipping more warnings # in to the code @@ -262,7 +261,6 @@ clang { android { QMAKE_CXXFLAGS -= -fstack-protector-strong QMAKE_CFLAGS -= -fstack-protector-strong - INCLUDEPATH += $$(ANDROID_NDK_ROOT)/sysroot/usr/include DEFINES += __BITS_PER_LONG=32 } diff --git a/ogl-runtime.pro b/ogl-runtime.pro index 44d9fd6..0e399c3 100644 --- a/ogl-runtime.pro +++ b/ogl-runtime.pro @@ -8,7 +8,7 @@ integrity { CHECK_INTEGRITY_DIR = $$(INTEGRITY_DIR) } -ios|tvos|watchos|winrt|wasm|*-icc*|contains(CHECK_INTEGRITY_DIR, .*int1144$) { +ios|tvos|watchos|winrt|wasm|*-icc*|contains(CHECK_INTEGRITY_DIR, .*int1144$)|contains(QMAKE_HOST.arch, mips64)|contains(QT_ARCH, mips64) { message("WARNING, target not supported by ogl-runtime") #Exclude non-working cross-compile targets, see: # QT3DS-3647 ogl-runtime doesn't compile on TvOS_ANY in CI @@ -16,6 +16,7 @@ ios|tvos|watchos|winrt|wasm|*-icc*|contains(CHECK_INTEGRITY_DIR, .*int1144$) { # QT3DS-3646 ogl-runtime doesn't compile on IOS_ANY in CI # QT3DS-3649 ogl-runtime doesn't compile on WinRT in CI # QT3DS-3650 ogl-runtime doesn't compile on WebAssembly in CI + # QT3DS-4129 ogl-runtime doesn't compile on Qemu mips64 in CI TEMPLATE = subdirs CONFIG += ordered SUBDIRS += src_dummy diff --git a/src/3rdparty/EASTL b/src/3rdparty/EASTL -Subproject 31697c758f2ed19bd7c6bbe61f1b91f9e12035b +Subproject 0d1d5505c1e6c2af3f77680979d9b237e9fbf35 diff --git a/src/api/studio3d/q3dscommandqueue.cpp b/src/api/studio3d/q3dscommandqueue.cpp index 300c0bf..a839e69 100644 --- a/src/api/studio3d/q3dscommandqueue.cpp +++ b/src/api/studio3d/q3dscommandqueue.cpp @@ -219,6 +219,8 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue) = m_stereoEyeSeparationChanged || fromQueue.m_stereoEyeSeparationChanged; m_stereoProgressiveEnabledChanged = m_stereoProgressiveEnabledChanged || fromQueue.m_stereoProgressiveEnabledChanged; + m_skipFramesIntervalChanged + = m_skipFramesIntervalChanged || fromQueue.m_skipFramesIntervalChanged; m_shadeModeChanged = m_shadeModeChanged || fromQueue.m_shadeModeChanged; m_showRenderStatsChanged = m_showRenderStatsChanged || fromQueue.m_showRenderStatsChanged; m_matteColorChanged = m_matteColorChanged || fromQueue.m_matteColorChanged; @@ -240,6 +242,8 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue) m_stereoEyeSeparation = fromQueue.m_stereoEyeSeparation; if (fromQueue.m_stereoProgressiveEnabledChanged) m_stereoProgressiveEnabled = fromQueue.m_stereoProgressiveEnabled; + if (fromQueue.m_skipFramesIntervalChanged) + m_skipFramesInterval = fromQueue.m_skipFramesInterval; if (fromQueue.m_shadeModeChanged) m_shadeMode = fromQueue.m_shadeMode; if (fromQueue.m_showRenderStatsChanged) @@ -343,6 +347,7 @@ void CommandQueue::clear(bool deleteCommandData) m_stereoModeChanged = false; m_stereoEyeSeparationChanged = false; m_stereoProgressiveEnabledChanged = false; + m_skipFramesIntervalChanged = false; m_shadeModeChanged = false; m_showRenderStatsChanged = false; m_matteColorChanged = false; diff --git a/src/api/studio3d/q3dscommandqueue_p.h b/src/api/studio3d/q3dscommandqueue_p.h index 6096439..9939cb0 100644 --- a/src/api/studio3d/q3dscommandqueue_p.h +++ b/src/api/studio3d/q3dscommandqueue_p.h @@ -144,6 +144,7 @@ public: bool m_stereoModeChanged = false; bool m_stereoEyeSeparationChanged = false; bool m_stereoProgressiveEnabledChanged = false; + bool m_skipFramesIntervalChanged = false; bool m_shadeModeChanged = false; bool m_showRenderStatsChanged = false; bool m_matteColorChanged = false; @@ -159,6 +160,7 @@ public: Q3DSViewerSettings::StereoMode m_stereoMode = Q3DSViewerSettings::StereoModeMono; double m_stereoEyeSeparation = 0.4; bool m_stereoProgressiveEnabled = false; + int m_skipFramesInterval = 0; Q3DSViewerSettings::ShadeMode m_shadeMode = Q3DSViewerSettings::ShadeModeShaded; bool m_showRenderStats = false; QColor m_matteColor = QColor(Qt::black); diff --git a/src/api/studio3d/q3dspresentation.cpp b/src/api/studio3d/q3dspresentation.cpp index f0ca867..c711bbc 100644 --- a/src/api/studio3d/q3dspresentation.cpp +++ b/src/api/studio3d/q3dspresentation.cpp @@ -943,6 +943,22 @@ void Q3DSPresentation::setShaderCacheFile(const QUrl &fileName) */ /*! + \qmlsignal Presentation::shaderCacheLoadErrors(string errors) + \since QtStudio3D.OpenGL 2.7 + + Emitted when a shader cache loading fails. The parameter \a errors contains the error + message(s). + */ + +/*! + \fn Q3DSPresentation::shaderCacheLoadErrors(const QString &errors) + \since Qt 3D Studio 2.7 + + Emitted when a shader cache loading fails. The parameter \a errors contains the error + message(s). + */ + +/*! This function is for backwards compatibility. We recommend using \l{DataInput}s to control slide changes. \l{DataInput} provides stronger contract between the design and code as it avoids use of elementPath (a reference to design's internal structure). @@ -1126,6 +1142,30 @@ void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &a "image://colors/blue" where "image://" tells the runtime to look for an image provider, "colors" is the image provider id and rest are the image id the provider uses to create the image. + + Usage is similar to the examples in https://doc.qt.io/qt-5/qquickimageprovider.html + + \badcode + // Example implementation of a request function + // This returns a 50 x 50 px size green texture as a QPixmap + QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) + { + // Size needs to be more than 0,0 or nothing will be drawn + if (size) + *size = QSize(50, 50); + + QPixmap pixmap(50, 50); + pixmap.fill(QColor("green")); + return pixmap; + } + + // Image providers are added to the presentation after viewer creation + viewer.create(&window, &context); + viewer.presentation()->addImageProvider("green", new ImageProvider()); + + // Use as texture + viewer.presentation()->setAttribute("Scene.Layer.Rectangle.Material.diffusemap", "sourcepath", "image://green"); + \endcode */ void Q3DSPresentation::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) { diff --git a/src/api/studio3d/q3dsviewersettings.cpp b/src/api/studio3d/q3dsviewersettings.cpp index 9025bb8..cbb273a 100644 --- a/src/api/studio3d/q3dsviewersettings.cpp +++ b/src/api/studio3d/q3dsviewersettings.cpp @@ -371,6 +371,44 @@ void Q3DSViewerSettings::setStereoProgressiveEnabled(bool enabled) } /*! + \qmlproperty int ViewerSettings::skipFramesInterval + + \since QtStudio3D.OpenGL 2.7 + + Sets interval for skipping frame rendering. The default value is 0 + meaning all frames are rendered. Setting this to 1 renders every + other frame (30fps on 60Hz screen), 2 every third frame (20fps on + 60Hz screen) etc. This property allows slowing down 3D rendering + while keeping QtQuick UI rendering intact, decreasing the CPU/GPU + usage. + */ +/*! + \property Q3DSViewerSettings::skipFramesInterval + + \since Qt 3D Studio 2.7 + + Sets interval for skipping frame rendering. The default value is 0 + meaning all frames are rendered. Setting this to 1 renders every + other frame (30fps on 60Hz screen), 2 every third frame (20fps on + 60Hz screen) etc. This property allows slowing down 3D rendering + while keeping QtQuick UI rendering intact, decreasing the CPU/GPU + usage. + */ + +int Q3DSViewerSettings::skipFramesInterval() const +{ + return d_ptr->m_skipFramesInterval; +} + +void Q3DSViewerSettings::setSkipFramesInterval(int interval) +{ + if (d_ptr->m_skipFramesInterval != interval) { + d_ptr->setSkipFramesInterval(interval); + Q_EMIT skipFramesIntervalChanged(interval); + } +} + +/*! \qmlproperty bool ViewerSettings::matteEnabled Specifies if the empty area around the presentation (applicable when @@ -450,6 +488,7 @@ Q3DSViewerSettingsPrivate::Q3DSViewerSettingsPrivate(Q3DSViewerSettings *q) , m_stereoMode(Q3DSViewerSettings::StereoModeMono) , m_stereoEyeSeparation(0.4) , m_stereoProgressiveEnabled(false) + , m_skipFramesInterval(0) , m_savedSettings(nullptr) { } @@ -470,6 +509,7 @@ void Q3DSViewerSettingsPrivate::setViewerApp(Q3DSViewer::Q3DSViewerApp *app) setStereoMode(m_stereoMode); setStereoEyeSeparation(m_stereoEyeSeparation); setStereoProgressiveEnabled(m_stereoProgressiveEnabled); + setSkipFramesInterval(m_skipFramesInterval); } } @@ -485,6 +525,7 @@ void Q3DSViewerSettingsPrivate::setCommandQueue(CommandQueue *queue) setStereoMode(m_stereoMode); setStereoEyeSeparation(m_stereoEyeSeparation); setStereoProgressiveEnabled(m_stereoProgressiveEnabled); + setSkipFramesInterval(m_skipFramesInterval); } } @@ -519,6 +560,8 @@ void Q3DSViewerSettingsPrivate::load(const QString &group, const QString &organi m_savedSettings->value(QStringLiteral("stereoEyeSeparation")).toDouble()); q_ptr->setStereoProgressiveEnabled( m_savedSettings->value(QStringLiteral("stereoProgressiveEnabled")).toBool()); + q_ptr->setSkipFramesInterval( + m_savedSettings->value(QStringLiteral("skipFramesInterval")).toInt()); q_ptr->setMatteEnabled(m_savedSettings->value(QStringLiteral("matteEnabled")).toBool()); } @@ -627,6 +670,17 @@ void Q3DSViewerSettingsPrivate::setStereoProgressiveEnabled(bool enabled) } } +void Q3DSViewerSettingsPrivate::setSkipFramesInterval(int interval) +{ + m_skipFramesInterval = interval; + if (m_viewerApp) { + m_viewerApp->SetSkipFramesInterval(interval); + } else if (m_commandQueue) { + m_commandQueue->m_skipFramesInterval = interval; + m_commandQueue->m_skipFramesIntervalChanged = true; + } +} + void Q3DSViewerSettingsPrivate::initSettingsStore(const QString &group, const QString &organization, const QString &application) { diff --git a/src/api/studio3d/q3dsviewersettings.h b/src/api/studio3d/q3dsviewersettings.h index f956649..80b36df 100644 --- a/src/api/studio3d/q3dsviewersettings.h +++ b/src/api/studio3d/q3dsviewersettings.h @@ -53,6 +53,7 @@ class Q_STUDIO3D_EXPORT Q3DSViewerSettings : public QObject Q_PROPERTY(StereoMode stereoMode READ stereoMode WRITE setStereoMode NOTIFY stereoModeChanged REVISION 1) Q_PROPERTY(double stereoEyeSeparation READ stereoEyeSeparation WRITE setStereoEyeSeparation NOTIFY stereoEyeSeparationChanged REVISION 1) Q_PROPERTY(bool stereoProgressiveEnabled READ stereoProgressiveEnabled WRITE setStereoProgressiveEnabled NOTIFY stereoProgressiveEnabledChanged REVISION 2) + Q_PROPERTY(int skipFramesInterval READ skipFramesInterval WRITE setSkipFramesInterval NOTIFY skipFramesIntervalChanged REVISION 2) public: enum ShadeMode { @@ -84,6 +85,7 @@ public: StereoMode stereoMode() const; double stereoEyeSeparation() const; Q_REVISION(2) bool stereoProgressiveEnabled() const; + Q_REVISION(2) int skipFramesInterval() const; Q_INVOKABLE void save(const QString &group, const QString &organization = QString(), const QString &application = QString()); @@ -98,6 +100,7 @@ public Q_SLOTS: void setStereoMode(StereoMode mode); void setStereoEyeSeparation(double separation); Q_REVISION(2) void setStereoProgressiveEnabled(bool enabled); + Q_REVISION(2) void setSkipFramesInterval(int interval); Q_SIGNALS: void matteEnabledChanged(bool enabled); @@ -108,6 +111,7 @@ Q_SIGNALS: void stereoModeChanged(StereoMode mode); void stereoEyeSeparationChanged(double separation); Q_REVISION(2) void stereoProgressiveEnabledChanged(bool enabled); + Q_REVISION(2) void skipFramesIntervalChanged(int interval); private: Q_DISABLE_COPY(Q3DSViewerSettings) diff --git a/src/api/studio3d/q3dsviewersettings_p.h b/src/api/studio3d/q3dsviewersettings_p.h index 44e1227..6a2dc75 100644 --- a/src/api/studio3d/q3dsviewersettings_p.h +++ b/src/api/studio3d/q3dsviewersettings_p.h @@ -70,6 +70,7 @@ public: void setStereoMode(Q3DSViewerSettings::StereoMode mode); void setStereoEyeSeparation(double separation); void setStereoProgressiveEnabled(bool enabled); + void setSkipFramesInterval(int interval); public: Q3DSViewerSettings *q_ptr; @@ -88,6 +89,7 @@ private: Q3DSViewerSettings::StereoMode m_stereoMode; double m_stereoEyeSeparation; bool m_stereoProgressiveEnabled; + int m_skipFramesInterval; QSettings *m_savedSettings; }; diff --git a/src/api/studio3dqml/q3dsrenderer.cpp b/src/api/studio3dqml/q3dsrenderer.cpp index f7bd25b..8f0081e 100644 --- a/src/api/studio3dqml/q3dsrenderer.cpp +++ b/src/api/studio3dqml/q3dsrenderer.cpp @@ -353,6 +353,8 @@ void Q3DSRenderer::processCommands() m_settings->setStereoEyeSeparation(m_commands.m_stereoEyeSeparation); if (m_commands.m_stereoProgressiveEnabledChanged) m_settings->setStereoProgressiveEnabled(m_commands.m_stereoProgressiveEnabled); + if (m_commands.m_skipFramesIntervalChanged) + m_settings->setSkipFramesInterval(m_commands.m_skipFramesInterval); if (m_commands.m_shadeModeChanged) m_settings->setShadeMode(m_commands.m_shadeMode); if (m_commands.m_matteColorChanged) diff --git a/src/engine/Qt3DSRenderRuntimeBinding.cpp b/src/engine/Qt3DSRenderRuntimeBinding.cpp index 7535af6..e099e47 100644 --- a/src/engine/Qt3DSRenderRuntimeBinding.cpp +++ b/src/engine/Qt3DSRenderRuntimeBinding.cpp @@ -254,6 +254,24 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene Q3DStudio::UVariant value; if (theElement.GetAttribute(ATTRIBUTE_SUBPRESENTATION, value)) subs.push_back(m_Context->GetStringTable().HandleToStr(value.m_StringHandle)); + } else if (theTranslator && theTranslator->GetUIPType() + == GraphObjectTypes::CustomMaterial) { + // Add custom material strings to the subpresentation list since any string + // property could be a texture with a subpresentation source. + // Non-subpresentation strings are filtered out by the function caller. + int numProperties = theElement.GetNumProperties(); + for (int i = 0; i < numProperties; ++i) { + auto property = theElement.GetPropertyByIndex(i); + if (property.hasValue()) { + auto value = property.getValue(); + if (value.first.type() == ATTRIBUTETYPE_STRING) { + auto stringValue = m_Context->GetStringTable().HandleToStr( + value.second->m_StringHandle); + if (stringValue.IsValid()) + subs.push_back(stringValue); + } + } + } } } } @@ -275,10 +293,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene TransferDirtyProperties(); m_LastRenderViewport = m_Context->GetRenderList().GetViewport(); if (m_Presentation && m_Presentation->m_Scene) { - NVRenderRect theViewportSize(m_LastRenderViewport); - return m_Presentation->m_Scene->PrepareForRender( - QT3DSVec2(QT3DSF32(theViewportSize.m_Width), QT3DSF32(theViewportSize.m_Height)), - *m_Context); + return m_Presentation->m_Scene->PrepareForRender(*m_Context); } return false; } diff --git a/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp b/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp index 9fda560..e0176c7 100644 --- a/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp +++ b/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp @@ -172,6 +172,12 @@ struct SRenderer : public Q3DStudio::ITegraApplicationRenderEngine return false; } + void SetSkipFramesInterval(int interval) override + { + if (m_BindingCore && m_BindingCore->m_Context) + m_BindingCore->m_Context->SetSkipFramesInterval(interval); + } + void SetShadeMode(Q3DStudio::TegraRenderShadeModes::Enum inShade) override { if (m_BindingCore && m_BindingCore->m_Context) { @@ -204,10 +210,6 @@ struct SRenderer : public Q3DStudio::ITegraApplicationRenderEngine m_Viewport = NVRenderRect(inX, inY, inWidth, inHeight); m_BindingCore->m_RenderContext->SetViewport(m_Viewport); } - void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) override - { - m_BindingCore->m_Context->SetViewport(inViewport); - } void SetMatteColor(Option<QT3DSVec4> inColor) override { m_Context->SetMatteColor(inColor); } void setMatteEnabled(bool enabled) override { m_Context->setMatteEnabled(enabled); }; diff --git a/src/engine/Qt3DSRuntimeView.h b/src/engine/Qt3DSRuntimeView.h index 8690b99..72d8908 100644 --- a/src/engine/Qt3DSRuntimeView.h +++ b/src/engine/Qt3DSRuntimeView.h @@ -132,7 +132,6 @@ protected: public: virtual void SetViewport(INT32 inX, INT32 inY, INT32 inWidth, INT32 inHeight) = 0; - virtual void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) = 0; virtual void ensureRenderTarget() = 0; virtual void CheckResize(bool inForce, IPresentation &inActivePresentation) = 0; virtual QByteArray exportShaderCache(bool binaryShaders) = 0; @@ -149,6 +148,7 @@ public: virtual double GetStereoEyeSeparation() const = 0; virtual void SetStereoProgressiveEnabled(bool enabled) = 0; virtual bool GetStereoProgressiveEnabled() const = 0; + virtual void SetSkipFramesInterval(int interval) = 0; // TODO: To be removed, not used anywhere anymore void CycleScaleMode() diff --git a/src/foundation/Qt3DSAllocator.h b/src/foundation/Qt3DSAllocator.h index cdbbe5f..2c90593 100644 --- a/src/foundation/Qt3DSAllocator.h +++ b/src/foundation/Qt3DSAllocator.h @@ -36,7 +36,11 @@ #include "foundation/Qt3DSAssert.h" #if (defined(QT3DS_WINDOWS) | defined(QT3DS_X360)) +#if _MSC_VER < 1920 // 1920+ = MSVC2019 #include <typeinfo.h> +#else +#include <typeinfo> +#endif #endif #if (defined(QT3DS_APPLE)) #include <typeinfo> diff --git a/src/runtime/Qt3DSActivationManager.cpp b/src/runtime/Qt3DSActivationManager.cpp index e975c7d..ee17f1e 100644 --- a/src/runtime/Qt3DSActivationManager.cpp +++ b/src/runtime/Qt3DSActivationManager.cpp @@ -555,17 +555,24 @@ struct STimeContext inScanBuffer.push_back(SScanBufferEntry(&inNode, parentActive)); } - + bool parentDiActiveChange = false; for (QT3DSU32 idx = 0, end = inScanBuffer.size(); idx < end; ++idx) { SScanBufferEntry theEntry(inScanBuffer[idx]); SElement *theScanNode = theEntry.m_Node; QT3DS_ASSERT(theScanNode->IsIndependent() == false); bool parentActive = theEntry.IsParentActive(); bool wasActive = theScanNode->IsGlobalActive(); - bool isControlledByDi = controlledList.contains(*theScanNode) && theScanNode->m_OnMaster; - + if (!isControlledByDi && parentDiActiveChange && parentActive && !wasActive + && !theScanNode->IsTimeActive() && theScanNode->IsExplicitActive()) { + // Set time active for datainput activated child nodes + theScanNode->m_ActivationManagerNode.m_Flags.SetTimeActive(true); + } + bool diActiveChange = isControlledByDi + && (theScanNode->IsGlobalActive(parentActive) + != theScanNode->IsControlledActive()); + parentDiActiveChange |= diActiveChange; // Override visibility for master slide elements that have datainput eyeball controller. bool isActive = isControlledByDi ? theScanNode->IsControlledActive() : theScanNode->IsGlobalActive(parentActive); @@ -576,9 +583,7 @@ struct STimeContext if (activateChange) { HandleActivationChange(*theScanNode, activateBuffer, deactivateBuffer, scriptBuffer, inElementAccessMutex, scriptBufferRequiresSort, isActive); - } else if (isControlledByDi - && (theScanNode->IsGlobalActive(parentActive) - != theScanNode->IsControlledActive())) { + } else if (diActiveChange) { // Notify only if datainput control actually disagreed with activity value // coming from activity manager. qCInfo(TRACE_INFO) << "Element" << theScanNode->name().c_str() @@ -644,7 +649,7 @@ struct STimeContext TElementNodePtrList &inTempDirtyList, TElementAndSortKeyList &activateBuffer, TElementAndSortKeyList &deactivateBuffer, TElementAndSortKeyList &scriptBuffer, bool &scriptBufferRequiresSort, Q3DStudio::CComponentManager &inComponentManager, - IPerfTimer &inPerfTimer, IActivityZone &inZone) + IPerfTimer &, IActivityZone &inZone) { SComponent &theContextNode = m_Component; bool parentActive = true; diff --git a/src/runtime/Qt3DSApplication.cpp b/src/runtime/Qt3DSApplication.cpp index f7f8b46..7b4d625 100644 --- a/src/runtime/Qt3DSApplication.cpp +++ b/src/runtime/Qt3DSApplication.cpp @@ -658,7 +658,7 @@ struct SApp : public IApplication DataOutputMap m_dataOutputDefs; bool m_initialFrame = true; - + int m_skipFrameCount = 0; SSlideResourceCounter m_resourceCounter; QSet<QString> m_createSet; @@ -1119,6 +1119,23 @@ struct SApp : public IApplication void ResetDirtyCounter() { m_DirtyCountdown = 5; } + // Returns true when skipping the frame, false when rendering it + bool checkSkipFrame() + { + auto &rc = m_RuntimeFactory->GetQt3DSRenderContext(); + int skipFrames = rc.GetSkipFramesInterval(); + if (skipFrames == 0) + return false; + + if (m_skipFrameCount <= 0) { + m_skipFrameCount = skipFrames; + return false; + } + + m_skipFrameCount--; + return true; + } + // Update all the presentations and render them. bool UpdateAndRender() override { @@ -1165,7 +1182,12 @@ struct SApp : public IApplication bool renderNextFrame = false; if (m_LastRenderWasDirty || dirty || m_initialFrame) renderNextFrame = true; - Render(); + + bool skip = checkSkipFrame(); + // If we skip rendering this frame, mark next frame to be rendered + renderNextFrame |= skip; + if (!skip) + Render(); m_InputEnginePtr->ClearInputFrame(); @@ -2255,6 +2277,10 @@ bool AssetHandlers::handlePresentation(SApp &app, SAssetValue &asset, bool initI thePathStr.c_str()); return false; } + + app.GetRuntimeFactory().GetScriptEngineQml() + .initializePresentationDataInputsAndOutputs(*thePresentationAsset.m_Presentation); + return true; } diff --git a/src/runtime/Qt3DSIScriptBridge.h b/src/runtime/Qt3DSIScriptBridge.h index 9eedfc5..cb13fb2 100644 --- a/src/runtime/Qt3DSIScriptBridge.h +++ b/src/runtime/Qt3DSIScriptBridge.h @@ -202,6 +202,7 @@ public: // Components public: // Presentation virtual void SetPresentationAttribute(const char *presId, const char *attName, const char *attValue) = 0; + virtual void initializePresentationDataInputsAndOutputs(CPresentation &presentation) = 0; public: // Multimedia virtual bool PlaySoundFile(const char *soundPath) = 0; diff --git a/src/runtime/Qt3DSQmlEngine.cpp b/src/runtime/Qt3DSQmlEngine.cpp index d063e5e..994f6c1 100644 --- a/src/runtime/Qt3DSQmlEngine.cpp +++ b/src/runtime/Qt3DSQmlEngine.cpp @@ -460,6 +460,7 @@ public: void GotoSlideRelative(const char *, bool, bool, const SScriptEngineGotoSlideArgs &) override; void SetPresentationAttribute(const char *, const char *, const char *) override; + void initializePresentationDataInputsAndOutputs(CPresentation &presentation); // No need to implement here, as sound playing is done in Qt3DSViewerApp bool PlaySoundFile(const char *) override { return false; } @@ -1917,6 +1918,12 @@ void CQmlEngineImpl::SetPresentationAttribute(const char *presId, const char *, } } +void CQmlEngineImpl::initializePresentationDataInputsAndOutputs(CPresentation &presentation) +{ + initializeDataInputsInPresentation(presentation, false); + initializeDataOutputsInPresentation(presentation, false); +} + void CQmlEngineImpl::GotoSlideIndex(const char *component, const Q3DStudio::INT32 slideIndex, const SScriptEngineGotoSlideArgs &inArgs) { @@ -2135,6 +2142,9 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat bool isPrimary, bool isDynamicAdd, QList<TElement *> inElements) { + if (!m_Application) + return; + QList<TElement *> elements; if (!inElements.empty()) { elements = inElements; @@ -2310,6 +2320,9 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat void CQmlEngineImpl::initializeDataOutputsInPresentation(CPresentation &presentation, bool isPrimary) { + if (!m_Application) + return; + TElement *parent = presentation.GetRoot(); QList<TElement *> elements; listAllElements(parent, elements); diff --git a/src/runtimerender/Qt3DSRenderContextCore.cpp b/src/runtimerender/Qt3DSRenderContextCore.cpp index dde70fd..44f10c0 100644 --- a/src/runtimerender/Qt3DSRenderContextCore.cpp +++ b/src/runtimerender/Qt3DSRenderContextCore.cpp @@ -241,14 +241,14 @@ struct SRenderContext : public IQt3DSRenderContext NVScopedRefCounted<IRenderList> m_RenderList; QT3DSU32 m_FrameCount; volatile QT3DSI32 mRefCount; - // Viewport that this render context should use - Option<NVRenderRect> m_Viewport; + QSize m_WindowDimensions; ScaleModes::Enum m_ScaleMode; StereoModes::Enum m_StereoMode; StereoViews::Enum m_StereoView; double m_StereoEyeSeparation; bool m_StereoProgressiveEnabled; + int m_SkipFramesInterval; bool m_WireframeMode; bool m_subPresentationRenderInLayer; Option<QT3DSVec4> m_SceneColor; @@ -291,6 +291,7 @@ struct SRenderContext : public IQt3DSRenderContext , m_StereoView(StereoViews::Mono) , m_StereoEyeSeparation(0.4) , m_StereoProgressiveEnabled(false) + , m_SkipFramesInterval(0) , m_WireframeMode(false) , m_subPresentationRenderInLayer(false) , m_matteEnabled(false) @@ -486,13 +487,19 @@ struct SRenderContext : public IQt3DSRenderContext || m_StereoMode == StereoModes::TopBottom); } + void SetSkipFramesInterval(int interval) override + { + m_SkipFramesInterval = interval; + } + + int GetSkipFramesInterval() const override { + return m_SkipFramesInterval; + } + void SetWireframeMode(bool inEnable) override { m_WireframeMode = inEnable; } bool GetWireframeMode() override { return m_WireframeMode; } - void SetViewport(Option<NVRenderRect> inViewport) override { m_Viewport = inViewport; } - Option<NVRenderRect> GetViewport() const override { return m_Viewport; } - IRenderWidgetContext &GetRenderWidgetContext() override { return m_Renderer->GetRenderWidgetContext(); @@ -545,11 +552,7 @@ struct SRenderContext : public IQt3DSRenderContext NVRenderRect GetContextViewport() const override { NVRenderRect retval; - if (m_Viewport.hasValue()) - retval = *m_Viewport; - else - retval = NVRenderRect(0, 0, m_WindowDimensions.width(), m_WindowDimensions.height()); - + retval = NVRenderRect(0, 0, m_WindowDimensions.width(), m_WindowDimensions.height()); return retval; } @@ -686,12 +689,8 @@ struct SRenderContext : public IQt3DSRenderContext m_PerFrameAllocator.reset(); IRenderList &theRenderList(*m_RenderList); theRenderList.BeginFrame(); - if (m_Viewport.hasValue()) { - theRenderList.SetScissorTestEnabled(true); - theRenderList.SetScissorRect(theContextViewport); - } else { - theRenderList.SetScissorTestEnabled(false); - } + theRenderList.SetScissorRect(theContextViewport); + theRenderList.SetScissorTestEnabled(false); bool renderOffscreen = m_Rotation != RenderRotationValues::NoRotation; eastl::pair<NVRenderRect, NVRenderRect> thePresViewportAndOuterViewport = GetPresentationViewportAndOuterViewport(); @@ -771,11 +770,10 @@ struct SRenderContext : public IQt3DSRenderContext { bool stereoProgressiveEnabled = GetStereoProgressiveEnabled(); // Clearing for matte / scene background - if (m_Viewport.hasValue() || stereoProgressiveEnabled) { + if (stereoProgressiveEnabled) { // With progressive stereoscopic rendering needs to be adjusted to viewport NVRenderRect theContextViewport(GetContextViewport()); - if (stereoProgressiveEnabled) - adjustRectToStereoMode(theContextViewport); + adjustRectToStereoMode(theContextViewport); m_RenderContext->SetScissorTestEnabled(true); m_RenderContext->SetScissorRect(theContextViewport); } else { diff --git a/src/runtimerender/Qt3DSRenderContextCore.h b/src/runtimerender/Qt3DSRenderContextCore.h index 8382fc6..c239d78 100644 --- a/src/runtimerender/Qt3DSRenderContextCore.h +++ b/src/runtimerender/Qt3DSRenderContextCore.h @@ -184,11 +184,6 @@ namespace render { virtual void SetWindowDimensions(const QSize &inWindowDimensions) = 0; virtual QSize GetWindowDimensions() = 0; - // In addition to the window dimensions which really have to be set, you can optionally - // set the viewport which will force the entire viewer to render specifically to this - // viewport. - virtual void SetViewport(Option<NVRenderRect> inViewport) = 0; - virtual Option<NVRenderRect> GetViewport() const = 0; virtual NVRenderRect GetContextViewport() const = 0; // Only valid between calls to Begin,End. virtual NVRenderRect GetPresentationViewport() const = 0; @@ -205,6 +200,8 @@ namespace render { virtual double GetStereoEyeSeparation() const = 0; virtual void SetStereoProgressiveEnabled(bool enabled) = 0; virtual bool GetStereoProgressiveEnabled() const = 0; + virtual void SetSkipFramesInterval(int interval) = 0; + virtual int GetSkipFramesInterval() const = 0; virtual void SetWireframeMode(bool inEnable) = 0; virtual bool GetWireframeMode() = 0; diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp index cb94534..03c1a01 100644 --- a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp +++ b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp @@ -1310,8 +1310,8 @@ struct SMaterialSystem : public ICustomMaterialSystem SImage *image = (*inMaterial.m_imageMaps)[inPropertyName]; if (image) { if (image->m_ImagePath != *theStrPtr) { - image->m_ImagePath = *theStrPtr; - image->m_Flags.SetDirty(true); + // Should not happen + QT3DS_ASSERT(false); } else { IOffscreenRenderManager &offscreenRenderer( m_Context->GetOffscreenRenderManager()); @@ -2008,10 +2008,11 @@ struct SMaterialSystem : public ICustomMaterialSystem { NVConstDataRef<SPropertyDefinition> thePropDefs = inClass.m_Class->GetProperties(); for (QT3DSU32 idx = 0, end = thePropDefs.size(); idx < end; ++idx) { - if (thePropDefs[idx].m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) { + const SPropertyDefinition &def = thePropDefs[idx]; + if (def.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) { SImage *pImage = nullptr; CRegisteredString theStrPtr = *reinterpret_cast<CRegisteredString *>( - inMaterial.GetDataSectionBegin() + thePropDefs[idx].m_Offset); + inMaterial.GetDataSectionBegin() + def.m_Offset); if (theStrPtr.IsValid()) { QT3DSU32 index = FindAllocatedImage(theStrPtr); @@ -2022,46 +2023,51 @@ struct SMaterialSystem : public ICustomMaterialSystem pImage = m_AllocatedImages[index].second; } - switch (thePropDefs[idx].m_TexUsageType) { + switch (def.m_TexUsageType) { case NVRenderTextureTypeValue::Displace: if (inMaterial.m_DisplacementMap != pImage) { inMaterial.m_DisplacementMap = pImage; - inMaterial.m_DisplacementMap->m_ImagePath = - thePropDefs[idx].m_ImagePath; + inMaterial.m_DisplacementMap->m_ImagePath = theStrPtr; inMaterial.m_DisplacementMap->m_ImageShaderName = - thePropDefs[idx].m_Name; // this is our name in the shader + def.m_Name; // this is our name in the shader inMaterial.m_DisplacementMap->m_VerticalTilingMode = - thePropDefs[idx].m_CoordOp; + def.m_CoordOp; inMaterial.m_DisplacementMap->m_HorizontalTilingMode = - thePropDefs[idx].m_CoordOp; + def.m_CoordOp; + pImage->m_Flags.SetDirty(true); + pImage->m_Flags.SetForceLoad(true); } break; case NVRenderTextureTypeValue::Emissive2: if (inMaterial.m_EmissiveMap2 != pImage) { inMaterial.m_EmissiveMap2 = pImage; - inMaterial.m_EmissiveMap2->m_ImagePath = thePropDefs[idx].m_ImagePath; + inMaterial.m_EmissiveMap2->m_ImagePath = theStrPtr; inMaterial.m_EmissiveMap2->m_ImageShaderName = - thePropDefs[idx].m_Name; // this is our name in the shader + def.m_Name; // this is our name in the shader inMaterial.m_EmissiveMap2->m_VerticalTilingMode = - thePropDefs[idx].m_CoordOp; + def.m_CoordOp; inMaterial.m_EmissiveMap2->m_HorizontalTilingMode = - thePropDefs[idx].m_CoordOp; + def.m_CoordOp; + pImage->m_Flags.SetDirty(true); + pImage->m_Flags.SetForceLoad(true); } break; default: if (!inMaterial.m_imageMaps) inMaterial.m_imageMaps = newImageMap(m_CoreContext.GetAllocator()); - if ((*inMaterial.m_imageMaps)[thePropDefs[idx].m_Name] != pImage) { - (*inMaterial.m_imageMaps)[thePropDefs[idx].m_Name] = pImage; - pImage->m_ImagePath = thePropDefs[idx].m_ImagePath; - pImage->m_ImageShaderName = thePropDefs[idx].m_Name; - pImage->m_VerticalTilingMode = thePropDefs[idx].m_CoordOp; - pImage->m_HorizontalTilingMode = thePropDefs[idx].m_CoordOp; + if ((*inMaterial.m_imageMaps)[def.m_Name] != pImage) { + (*inMaterial.m_imageMaps)[def.m_Name] = pImage; + pImage->m_ImagePath = theStrPtr; + pImage->m_ImageShaderName = def.m_Name; + pImage->m_VerticalTilingMode = def.m_CoordOp; + pImage->m_HorizontalTilingMode = def.m_CoordOp; + pImage->m_Flags.SetDirty(true); + pImage->m_Flags.SetForceLoad(true); } break; } } else { - switch (thePropDefs[idx].m_TexUsageType) { + switch (def.m_TexUsageType) { case NVRenderTextureTypeValue::Displace: inMaterial.m_DisplacementMap = nullptr; break; @@ -2071,7 +2077,7 @@ struct SMaterialSystem : public ICustomMaterialSystem default: if (!inMaterial.m_imageMaps) inMaterial.m_imageMaps = newImageMap(m_CoreContext.GetAllocator()); - (*inMaterial.m_imageMaps)[thePropDefs[idx].m_Name] = nullptr; + (*inMaterial.m_imageMaps)[def.m_Name] = nullptr; break; } } diff --git a/src/runtimerender/Qt3DSRenderEffectSystem.cpp b/src/runtimerender/Qt3DSRenderEffectSystem.cpp index faaf4d2..b15d0bc 100644 --- a/src/runtimerender/Qt3DSRenderEffectSystem.cpp +++ b/src/runtimerender/Qt3DSRenderEffectSystem.cpp @@ -1079,8 +1079,8 @@ struct SEffectSystem : public IEffectSystem SImage *image = (*inEffect.m_imageMaps)[inPropertyName]; if (image) { if (image->m_ImagePath != *theStrPtr) { - image->m_ImagePath = *theStrPtr; - image->m_Flags.SetDirty(true); + // Should not happen + QT3DS_ASSERT(false); } else { IOffscreenRenderManager &theOffscreenRenderer( m_Context->GetOffscreenRenderManager()); @@ -1928,10 +1928,12 @@ struct SEffectSystem : public IEffectSystem if ((*inEffect.m_imageMaps)[theDefs[idx].m_Name] != pImage) { (*inEffect.m_imageMaps)[theDefs[idx].m_Name] = pImage; - pImage->m_ImagePath = theDefs[idx].m_ImagePath; + pImage->m_ImagePath = *theStrPtr; pImage->m_ImageShaderName = theDefs[idx].m_Name; pImage->m_VerticalTilingMode = theDefs[idx].m_CoordOp; pImage->m_HorizontalTilingMode = theDefs[idx].m_CoordOp; + pImage->m_Flags.SetDirty(true); + pImage->m_Flags.SetForceLoad(true); } } } else { diff --git a/src/runtimerender/Qt3DSRenderSubpresentation.cpp b/src/runtimerender/Qt3DSRenderSubpresentation.cpp index 64f08be..8b13361 100644 --- a/src/runtimerender/Qt3DSRenderSubpresentation.cpp +++ b/src/runtimerender/Qt3DSRenderSubpresentation.cpp @@ -68,10 +68,7 @@ namespace render { QT3DSVec2 /*inPresScale*/, const SRenderInstanceId instanceId) { - NVRenderRect theViewportSize(m_RenderContext.GetRenderList().GetViewport()); - bool wasDirty = m_Presentation.m_Scene->PrepareForRender( - QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height), - m_RenderContext, instanceId); + bool wasDirty = m_Presentation.m_Scene->PrepareForRender(m_RenderContext, instanceId); // Always transparent return SOffscreenRenderFlags(true, wasDirty); } diff --git a/src/runtimerender/Qt3DSRenderer.h b/src/runtimerender/Qt3DSRenderer.h index 336baab..50c27c3 100644 --- a/src/runtimerender/Qt3DSRenderer.h +++ b/src/runtimerender/Qt3DSRenderer.h @@ -132,7 +132,7 @@ namespace render { virtual void RenderPointsIndirect() = 0; // Returns true if this layer or a sibling was dirty. - virtual bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions, + virtual bool PrepareLayerForRender(SLayer &inLayer, bool inRenderSiblings = true, const SRenderInstanceId id = nullptr) = 0; virtual void RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions, bool clear, diff --git a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp index 1dd352c..8e927fe 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp +++ b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp @@ -125,7 +125,25 @@ void SDynamicObject::SetStrPropertyValueT(dynamic::SPropertyDefinition &inDefini if (inProjectDir == NULL) inProjectDir = ""; if (CFileTools::RequiresCombineBaseAndRelative(inValue)) { - QString path = QDir(inProjectDir).cleanPath(inValue); + QString value(QDir::cleanPath(inValue)); + QString projectDir(inProjectDir); + QString path = value; + + bool tryResolveRelativePath = !projectDir.startsWith(QStringLiteral(":/")); + if (tryResolveRelativePath) + path.prepend(projectDir + QChar('/')); + + if (tryResolveRelativePath) { + bool exists = QFileInfo(path).exists(); + if (!exists && value.startsWith("../")) { + QString tryPath = projectDir + QChar('/') + value.right(value.size() - 3); + exists = QFileInfo(tryPath).exists(); + if (exists) + path = tryPath; + else + path = value; // reset back to initial value if resolve failed + } + } ioWorkspace.assign(path.toLatin1().constData()); SetPropertyValueT(inDefinition, inStrTable.RegisterStr(ioWorkspace.c_str())); // We also adjust the image path in the definition diff --git a/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp b/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp index 69cc35b..44e7f12 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp +++ b/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp @@ -95,7 +95,8 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager if (newImage.m_Texture == nullptr) { m_LastFrameOffscreenRenderer = nullptr; - if (m_ImagePath.IsValid() && !m_OffscreenRendererId.IsValid()) { + if (m_ImagePath.IsValid() && !m_OffscreenRendererId.IsValid() + && !inRenderManager.HasOffscreenRenderer(m_ImagePath)) { // Image has sourcepath set if (!m_LoadedTextureData || m_LoadedTextureData->m_path != QString::fromUtf8(m_ImagePath.c_str())) { @@ -111,6 +112,13 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager newImage.m_Texture = m_LoadedTextureData->m_Texture; newImage.m_TextureFlags = m_LoadedTextureData->m_TextureFlags; newImage.m_BSDFMipMap = m_LoadedTextureData->m_BSDFMipMap; + } else if (m_Flags.IsForceLoad()) { + QSet<QString> ls; + ls.insert(QString(m_ImagePath)); + inBufferManager.loadSet(ls); + newImage.m_Texture = m_LoadedTextureData->m_Texture; + newImage.m_TextureFlags = m_LoadedTextureData->m_TextureFlags; + newImage.m_BSDFMipMap = m_LoadedTextureData->m_BSDFMipMap; } replaceTexture = m_TextureData.m_Texture != newImage.m_Texture; } diff --git a/src/runtimerender/graphobjects/Qt3DSRenderNode.h b/src/runtimerender/graphobjects/Qt3DSRenderNode.h index ea0d481..7f5af1e 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderNode.h +++ b/src/runtimerender/graphobjects/Qt3DSRenderNode.h @@ -81,6 +81,7 @@ namespace render { ///mechanism. This can be usefulf or caching purposes. IgnoreParentTransform = 1 << 13, LayerEnableDepthPrePass = 1 << 14, ///< True when we render a depth pass before + ForceLoad = 1 << 15, }; }; @@ -178,6 +179,14 @@ namespace render { { ClearOrSet(value, NodeFlagValues::LayerEnableDepthPrePass); } + void SetForceLoad(bool value) + { + ClearOrSet(value, NodeFlagValues::ForceLoad); + } + bool IsForceLoad() + { + return this->operator&(NodeFlagValues::ForceLoad); + } }; struct QT3DS_AUTOTEST_EXPORT SNode : public SGraphObject diff --git a/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp b/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp index 2dadc26..afe68d5 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp +++ b/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp @@ -65,7 +65,7 @@ SLayer *SScene::GetLastChild() return child; } -bool SScene::PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, +bool SScene::PrepareForRender(IQt3DSRenderContext &inContext, const SRenderInstanceId id) { // We need to iterate through the layers in reverse order and ask them to render. @@ -74,7 +74,7 @@ bool SScene::PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRende if (m_FirstChild) { wasDirty |= - inContext.GetRenderer().PrepareLayerForRender(*m_FirstChild, inViewportDimensions, + inContext.GetRenderer().PrepareLayerForRender(*m_FirstChild, true, id); } return wasDirty; diff --git a/src/runtimerender/graphobjects/Qt3DSRenderScene.h b/src/runtimerender/graphobjects/Qt3DSRenderScene.h index 8c4d3fe..00a4591 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderScene.h +++ b/src/runtimerender/graphobjects/Qt3DSRenderScene.h @@ -69,7 +69,7 @@ namespace render { inRemapper.Remap(m_FirstChild); } // returns true if any of the layers were dirty or if this object was dirty - bool PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, + bool PrepareForRender(IQt3DSRenderContext &inContext, const SRenderInstanceId id = nullptr); void Render(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, RenderClearCommand command = ClearIsOptional, diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp index 300980c..a8b6a4f 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp @@ -233,11 +233,9 @@ namespace render { } bool Qt3DSRendererImpl::PrepareLayerForRender(SLayer &inLayer, - const QT3DSVec2 &inViewportDimensions, bool inRenderSiblings, const SRenderInstanceId id) { - (void)inViewportDimensions; nvvector<SLayer *> renderableLayers(m_qt3dsContext.GetPerFrameAllocator(), "LayerVector"); // Found by fair roll of the dice. renderableLayers.reserve(4); diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h index 99b0b51..decd7fd 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h @@ -342,8 +342,8 @@ namespace render { // Calls prepare layer for render // and then do render layer. - bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions, - bool inRenderSiblings, const SRenderInstanceId id) override; + bool PrepareLayerForRender(SLayer &inLayer, bool inRenderSiblings, + const SRenderInstanceId id) override; void RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions, bool clear, QT3DSVec4 clearColor, bool inRenderSiblings, const SRenderInstanceId id) override; diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp index 7a7a64c..1a76813 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp @@ -312,6 +312,36 @@ namespace render { } namespace { + NVBounds3 calculateShadowCameraBoundingBox(const QT3DSVec3 *points, + const QT3DSVec3 &forward, + const QT3DSVec3 &up, const QT3DSVec3 &right) + { + float minDistanceZ = std::numeric_limits<float>::max(); + float maxDistanceZ = -std::numeric_limits<float>::max(); + float minDistanceY = std::numeric_limits<float>::max(); + float maxDistanceY = -std::numeric_limits<float>::max(); + float minDistanceX = std::numeric_limits<float>::max(); + float maxDistanceX = -std::numeric_limits<float>::max(); + for (int i = 0; i < 8; ++i) { + float distanceZ = points[i].dot(forward); + if (distanceZ < minDistanceZ) + minDistanceZ = distanceZ; + if (distanceZ > maxDistanceZ) + maxDistanceZ = distanceZ; + float distanceY = points[i].dot(up); + if (distanceY < minDistanceY) + minDistanceY = distanceY; + if (distanceY > maxDistanceY) + maxDistanceY = distanceY; + float distanceX = points[i].dot(right); + if (distanceX < minDistanceX) + minDistanceX = distanceX; + if (distanceX > maxDistanceX) + maxDistanceX = distanceX; + } + return NVBounds3(QT3DSVec3(minDistanceX, minDistanceY, minDistanceZ), + QT3DSVec3(maxDistanceX, maxDistanceY, maxDistanceZ)); + } void computeFrustumBounds(const SCamera &inCamera, const NVRenderRectF &inViewPort, QT3DSVec3 &ctrBound, QT3DSVec3 camVerts[8]) @@ -353,7 +383,8 @@ namespace render { void SetupCameraForShadowMap(const QT3DSVec2 &inCameraVec, NVRenderContext & /*inContext*/, const NVRenderRectF &inViewport, const SCamera &inCamera, - const SLight *inLight, SCamera &theCamera) + const SLight *inLight, SCamera &theCamera, + QT3DSVec3 *scenePoints = nullptr) { // setup light matrix QT3DSU32 mapRes = 1 << inLight->m_ShadowMapRes; @@ -371,8 +402,15 @@ namespace render { theCamera.m_FOV = inLight->m_ShadowMapFov * QT3DS_DEGREES_TO_RADIANS; if (inLight->m_LightType == RenderLightTypes::Directional) { - QT3DSVec3 frustBounds[8], boundCtr; - computeFrustumBounds(inCamera, inViewport, boundCtr, frustBounds); + QT3DSVec3 frustumPoints[8], boundCtr, sceneCtr; + computeFrustumBounds(inCamera, inViewport, boundCtr, frustumPoints); + + if (scenePoints) { + sceneCtr = QT3DSVec3(0, 0, 0); + for (int i = 0; i < 8; ++i) + sceneCtr += scenePoints[i]; + sceneCtr *= 0.125f; + } QT3DSVec3 forward = inLightDir; forward.normalize(); @@ -382,37 +420,26 @@ namespace render { up.normalize(); // Calculate bounding box of the scene camera frustum - float minDistanceZ = std::numeric_limits<float>::max(); - float maxDistanceZ = -std::numeric_limits<float>::max(); - float minDistanceY = std::numeric_limits<float>::max(); - float maxDistanceY = -std::numeric_limits<float>::max(); - float minDistanceX = std::numeric_limits<float>::max(); - float maxDistanceX = -std::numeric_limits<float>::max(); - for (int i = 0; i < 8; ++i) { - float distanceZ = frustBounds[i].dot(forward); - if (distanceZ < minDistanceZ) - minDistanceZ = distanceZ; - if (distanceZ > maxDistanceZ) - maxDistanceZ = distanceZ; - float distanceY = frustBounds[i].dot(up); - if (distanceY < minDistanceY) - minDistanceY = distanceY; - if (distanceY > maxDistanceY) - maxDistanceY = distanceY; - float distanceX = frustBounds[i].dot(right); - if (distanceX < minDistanceX) - minDistanceX = distanceX; - if (distanceX > maxDistanceX) - maxDistanceX = distanceX; + NVBounds3 bounds = calculateShadowCameraBoundingBox(frustumPoints, forward, up, + right); + inLightPos = boundCtr; + if (scenePoints) { + NVBounds3 sceneBounds = calculateShadowCameraBoundingBox(scenePoints, forward, + up, right); + if (sceneBounds.getExtents().x * sceneBounds.getExtents().y + * sceneBounds.getExtents().z < bounds.getExtents().x + * bounds.getExtents().y * bounds.getExtents().z) { + bounds = sceneBounds; + inLightPos = sceneCtr; + } } // Apply bounding box parameters to shadow map camera projection matrix // so that the whole scene is fit inside the shadow map - inLightPos = boundCtr; - theViewport.m_Height = abs(maxDistanceY - minDistanceY); - theViewport.m_Width = abs(maxDistanceX - minDistanceX); - theCamera.m_ClipNear = -abs(maxDistanceZ - minDistanceZ); - theCamera.m_ClipFar = abs(maxDistanceZ - minDistanceZ); + theViewport.m_Height = bounds.getExtents().y * 2; + theViewport.m_Width = bounds.getExtents().x * 2; + theCamera.m_ClipNear = -bounds.getExtents().z * 2; + theCamera.m_ClipFar = bounds.getExtents().z * 2; } theCamera.m_Flags.SetLeftHanded(false); @@ -710,6 +737,18 @@ namespace render { | qt3ds::render::NVRenderClearValues::Stencil | qt3ds::render::NVRenderClearValues::Color); + auto bounds = m_Camera->m_Parent->GetBounds(m_Renderer.GetQt3DSContext().GetBufferManager(), + m_Renderer.GetQt3DSContext().GetPathManager()); + QT3DSVec3 scenePoints[8]; + scenePoints[0] = bounds.minimum; + scenePoints[1] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.minimum.z); + scenePoints[2] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.minimum.z); + scenePoints[3] = QT3DSVec3(bounds.maximum.x, bounds.maximum.y, bounds.minimum.z); + scenePoints[4] = QT3DSVec3(bounds.minimum.x, bounds.minimum.y, bounds.maximum.z); + scenePoints[5] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.maximum.z); + scenePoints[6] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.maximum.z); + scenePoints[7] = bounds.maximum; + for (QT3DSU32 i = 0; i < m_Lights.size(); i++) { // don't render shadows when not casting if (m_Lights[i]->m_CastShadow == false) @@ -721,7 +760,7 @@ namespace render { QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar); SetupCameraForShadowMap(theCameraProps, m_Renderer.GetContext(), __viewport.m_InitialValue, *m_Camera, - m_Lights[i], theCamera); + m_Lights[i], theCamera, scenePoints); // we need this matrix for the final rendering theCamera.CalculateViewProjectionMatrix(pEntry->m_LightVP); pEntry->m_LightView = theCamera.m_GlobalTransform.getInverse(); diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp index 26b0a3c..54cb55f 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp @@ -1414,7 +1414,7 @@ namespace render { NVRenderRect theViewport(theGraph.GetViewport()); NVRenderRect theScissor(theGraph.GetViewport()); if (theGraph.IsScissorTestEnabled()) - theScissor = m_Renderer.GetContext().GetScissorRect(); + theScissor = theGraph.GetScissor(); bool wasDirty = false; bool wasDataDirty = false; wasDirty = m_Layer.m_Flags.IsDirty(); diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp index aea4543..93ad2d4 100644 --- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp +++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp @@ -64,6 +64,8 @@ static inline int blockSizeForTextureFormat(int format) static inline int runtimeFormat(quint32 internalFormat) { switch (internalFormat) { + case QOpenGLTexture::RGBA8_ETC2_EAC: + return NVRenderTextureFormats::RGBA8_ETC2_EAC; case QOpenGLTexture::RGB8_ETC1: return NVRenderTextureFormats::RGB8_ETC1; case QOpenGLTexture::RGB8_ETC2: diff --git a/src/uipparser/Qt3DSUIPParserImpl.cpp b/src/uipparser/Qt3DSUIPParserImpl.cpp index 02bd3ad..4190915 100644 --- a/src/uipparser/Qt3DSUIPParserImpl.cpp +++ b/src/uipparser/Qt3DSUIPParserImpl.cpp @@ -842,16 +842,19 @@ void CUIPParserImpl::AddFloat4Attribute(TPropertyDescAndValueList &outDescList, void CUIPParserImpl::AddStringAttribute(IPresentation &inPresentation, TPropertyDescAndValueList &outDescList, - CRegisteredString inAttStrName, const char *inValue) + CRegisteredString inAttStrName, const char *inValue, + bool addSourceAsString) { qt3ds::foundation::CStringHandle theString = inPresentation.GetStringTable().GetHandle(inValue); UVariant theValue; theValue.m_StringHandle = theString.handle(); outDescList.push_back( eastl::make_pair(SPropertyDesc(inAttStrName, ATTRIBUTETYPE_STRING), theValue)); - if (CHash::HashAttribute(inAttStrName.c_str()) == Q3DStudio::ATTRIBUTE_SOURCEPATH && inValue - && *inValue) + if ((addSourceAsString + || CHash::HashAttribute(inAttStrName.c_str()) == Q3DStudio::ATTRIBUTE_SOURCEPATH) + && inValue && *inValue) { AddSourcePath(inValue, false); + } } void CUIPParserImpl::AddElementRefAttribute(TPropertyDescAndValueList &outDescList, @@ -944,7 +947,10 @@ void CUIPParserImpl::GetAttributeList(IPresentation &inPresentation, const char *theDataPtr = ""; if (!IsTrivial(inValue)) theReader.Read(theDataPtr); - AddStringAttribute(inPresentation, outDescList, inPropNameStrs[0], theDataPtr); + bool addSourceAsString = inAdditionalType + == ERuntimeAdditionalMetaDataType::ERuntimeAdditionalMetaDataTypeTexture; + AddStringAttribute(inPresentation, outDescList, inPropNameStrs[0], theDataPtr, + addSourceAsString); break; } case ERuntimeDataModelDataTypeLong4: { diff --git a/src/uipparser/Qt3DSUIPParserImpl.h b/src/uipparser/Qt3DSUIPParserImpl.h index 85f8c18..939ba35 100644 --- a/src/uipparser/Qt3DSUIPParserImpl.h +++ b/src/uipparser/Qt3DSUIPParserImpl.h @@ -661,7 +661,8 @@ protected: ERuntimeAdditionalMetaDataType inAdditionalType, CRegisteredString *inAttStrNames, qt3dsdm::SFloat4 &inValue); void AddStringAttribute(IPresentation &inPresentation, TPropertyDescAndValueList &outDescList, - CRegisteredString inAttStrName, const char *inValue); + CRegisteredString inAttStrName, const char *inValue, + bool addSourceAsString = false); void AddElementRefAttribute(TPropertyDescAndValueList &outDescList, CRegisteredString inAttStrName, SElement *inElement); diff --git a/src/viewer/Qt3DSViewerApp.cpp b/src/viewer/Qt3DSViewerApp.cpp index 5d8393a..7d94f3a 100644 --- a/src/viewer/Qt3DSViewerApp.cpp +++ b/src/viewer/Qt3DSViewerApp.cpp @@ -886,6 +886,12 @@ bool Q3DSViewerApp::GetStereoProgressiveEnabled() const return 0; } +void Q3DSViewerApp::SetSkipFramesInterval(int interval) +{ + if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine()) + m_Impl.m_view->GetTegraRenderEngine()->SetSkipFramesInterval(interval); +} + void Q3DSViewerApp::setMatteColor(const QColor &color) { if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine()) { diff --git a/src/viewer/Qt3DSViewerApp.h b/src/viewer/Qt3DSViewerApp.h index ab723cd..8aca9e1 100644 --- a/src/viewer/Qt3DSViewerApp.h +++ b/src/viewer/Qt3DSViewerApp.h @@ -328,6 +328,8 @@ public: void SetStereoProgressiveEnabled(bool enabled); bool GetStereoProgressiveEnabled() const; + void SetSkipFramesInterval(int interval); + void setMatteColor(const QColor &color); void setShowOnScreenStats(bool s); |