diff options
Diffstat (limited to 'src/render')
145 files changed, 1080 insertions, 1525 deletions
diff --git a/src/render/backend/backendnode.cpp b/src/render/backend/backendnode.cpp index 188e017e6..642f6e44d 100644 --- a/src/render/backend/backendnode.cpp +++ b/src/render/backend/backendnode.cpp @@ -56,6 +56,12 @@ BackendNode::BackendNode(Mode mode) { } +BackendNode::BackendNode(Qt3DCore::QBackendNodePrivate &dd) + : QBackendNode(dd) + , m_renderer(nullptr) +{ +} + BackendNode::~BackendNode() { } diff --git a/src/render/backend/backendnode_p.h b/src/render/backend/backendnode_p.h index 167cb87f2..37f8305af 100644 --- a/src/render/backend/backendnode_p.h +++ b/src/render/backend/backendnode_p.h @@ -58,6 +58,12 @@ QT_BEGIN_NAMESPACE +namespace Qt3DCore { + +class QBackendNodePrivate; + +} + namespace Qt3DRender { namespace Render { @@ -78,6 +84,7 @@ public: QSharedPointer<RenderBackendResourceAccessor> resourceAccessor(); protected: + explicit BackendNode(Qt3DCore::QBackendNodePrivate &dd); void markDirty(AbstractRenderer::BackendNodeDirtySet changes); AbstractRenderer *m_renderer; }; diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp index 7a5c1f7e6..85c5e9656 100644 --- a/src/render/backend/cameralens.cpp +++ b/src/render/backend/cameralens.cpp @@ -47,7 +47,6 @@ #include <Qt3DRender/private/sphere_p.h> #include <Qt3DRender/private/computefilteredboundingvolumejob_p.h> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qtransform.h> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/computecommand.cpp b/src/render/backend/computecommand.cpp index 386c25fec..df79dcbe8 100644 --- a/src/render/backend/computecommand.cpp +++ b/src/render/backend/computecommand.cpp @@ -102,6 +102,9 @@ void ComputeCommand::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firs m_frameCount = d->m_frameCount; markDirty(AbstractRenderer::ComputeDirty); } + + if (firstTime) + markDirty(AbstractRenderer::ComputeDirty); } // Called from buildComputeRenderCommands in a job diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index 8be58dd46..682dc000e 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "entity_p.h" +#include "entity_p_p.h" #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/qabstractlight.h> @@ -59,10 +60,7 @@ #include <Qt3DRender/qcameralens.h> #include <Qt3DCore/qarmature.h> -#include <Qt3DCore/qcomponentaddedchange.h> -#include <Qt3DCore/qcomponentremovedchange.h> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qtransform.h> #include <Qt3DCore/private/qentity_p.h> #include <Qt3DCore/qnodecreatedchange.h> @@ -77,8 +75,33 @@ using namespace Qt3DCore; namespace Qt3DRender { namespace Render { + +EntityPrivate::EntityPrivate() + : Qt3DCore::QBackendNodePrivate(Entity::ReadOnly) +{ +} + +EntityPrivate *EntityPrivate::get(Entity *node) +{ + return node->d_func(); +} + +void EntityPrivate::componentAdded(Qt3DCore::QNode *frontend) +{ + Q_Q(Entity); + const auto componentIdAndType = QNodeIdTypePair(frontend->id(), QNodePrivate::findStaticMetaObject(frontend->metaObject())); + q->addComponent(componentIdAndType); +} + +void EntityPrivate::componentRemoved(Qt3DCore::QNode *frontend) +{ + Q_Q(Entity); + q->removeComponent(frontend->id()); +} + + Entity::Entity() - : BackendNode() + : BackendNode(*new EntityPrivate) , m_nodeManagers(nullptr) , m_boundingDirty(false) , m_treeEnabled(true) @@ -160,31 +183,6 @@ void Entity::setHandle(HEntity handle) m_handle = handle; } -void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - - case ComponentAdded: { - QComponentAddedChangePtr change = qSharedPointerCast<QComponentAddedChange>(e); - const auto componentIdAndType = QNodeIdTypePair(change->componentId(), change->componentMetaObject()); - addComponent(componentIdAndType); - qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Added. Id =" << change->componentId(); - break; - } - - case ComponentRemoved: { - QComponentRemovedChangePtr change = qSharedPointerCast<QComponentRemovedChange>(e); - removeComponent(change->componentId()); - qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Removed. Id =" << change->componentId(); - break; - } - - default: - break; - } - BackendNode::sceneChangeEvent(e); -} - void Entity::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { const Qt3DCore::QEntity *node = qobject_cast<const Qt3DCore::QEntity *>(frontEnd); @@ -265,16 +263,6 @@ void Entity::removeFromParentChildHandles() p->removeChildHandle(m_handle); } -void Entity::appendChildHandle(HEntity childHandle) -{ - if (!m_childrenHandles.contains(childHandle)) { - m_childrenHandles.append(childHandle); - Entity *child = m_nodeManagers->renderNodesManager()->data(childHandle); - if (child != nullptr) - child->m_parentHandle = m_handle; - } -} - QVector<Entity *> Entity::children() const { QVector<Entity *> childrenVector; diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 403f5568c..d13d96784 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -79,6 +79,7 @@ namespace Render { class Sphere; class Renderer; class NodeManagers; +class EntityPrivate; class Q_AUTOTEST_EXPORT Entity : public BackendNode { @@ -89,7 +90,6 @@ public: void setParentHandle(HEntity parentHandle); void setNodeManagers(NodeManagers *manager); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void dump() const; @@ -176,6 +176,9 @@ public: return containsComponentsOfType<T>() && containsComponentsOfType<Ts, Ts2...>(); } +protected: + Q_DECLARE_PRIVATE(Entity) + private: NodeManagers *m_nodeManagers; HEntity m_handle; diff --git a/src/render/renderers/opengl/renderer/glcommands.cpp b/src/render/backend/entity_p_p.h index fd7ee9fe8..4ac6ab978 100644 --- a/src/render/renderers/opengl/renderer/glcommands.cpp +++ b/src/render/backend/entity_p_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -37,31 +38,50 @@ ** ****************************************************************************/ -#include "glcommands_p.h" -#include <Qt3DRender/private/renderer_p.h> -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> +#ifndef QT3DRENDER_RENDER_ENTITY_P_P_H +#define QT3DRENDER_RENDER_ENTITY_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/private/entity_p.h> +#include <Qt3DCore/private/qbackendnode_p.h> QT_BEGIN_NAMESPACE +namespace Qt3DCore { +class QNode; +} + namespace Qt3DRender { +class QRenderAspect; + namespace Render { -LoadShaderCommand::LoadShaderCommand(Shader *shader) - : m_shader(shader) -{ - Q_ASSERT(m_shader); -} +class Q_AUTOTEST_EXPORT EntityPrivate : public Qt3DCore::QBackendNodePrivate { +public: + EntityPrivate(); -void LoadShaderCommand::execute(Renderer *renderer, GraphicsContext *ctx) -{ - NodeManagers *nodeManagers = renderer->nodeManagers(); - ctx->loadShader(m_shader, nodeManagers->shaderManager()); -} + Q_DECLARE_PUBLIC(Entity) -} // Render + static EntityPrivate *get(Entity *node); -} // Qt3DRender + void componentAdded(Qt3DCore::QNode *frontend) override; + void componentRemoved(Qt3DCore::QNode *frontend) override; +}; + +} // namespace Render +} // namespace Qt3DRender QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_ENTITY_P_P_H diff --git a/src/render/backend/layer.cpp b/src/render/backend/layer.cpp index f0c844906..f1b6d2fc6 100644 --- a/src/render/backend/layer.cpp +++ b/src/render/backend/layer.cpp @@ -41,7 +41,6 @@ #include <Qt3DRender/qlayer.h> #include <Qt3DRender/private/qlayer_p.h> #include <Qt3DRender/private/stringtoint_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QVariant> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/levelofdetail.cpp b/src/render/backend/levelofdetail.cpp index 08410edf9..7f528a9d5 100644 --- a/src/render/backend/levelofdetail.cpp +++ b/src/render/backend/levelofdetail.cpp @@ -41,7 +41,6 @@ #include <Qt3DRender/QLevelOfDetail> #include <Qt3DRender/private/qlevelofdetail_p.h> #include <Qt3DRender/private/stringtoint_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/QCamera> #include <QVariant> @@ -111,14 +110,8 @@ void LevelOfDetail::cleanup() void LevelOfDetail::setCurrentIndex(int currentIndex) { - if (m_currentIndex != currentIndex) { + if (m_currentIndex != currentIndex) m_currentIndex = currentIndex; - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("currentIndex"); - e->setValue(m_currentIndex); - notifyObservers(e); - } } } // namespace Render diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri index 6b60dfcda..9510b9530 100644 --- a/src/render/backend/render-backend.pri +++ b/src/render/backend/render-backend.pri @@ -11,6 +11,7 @@ HEADERS += \ $$PWD/platformsurfacefilter_p.h \ $$PWD/cameralens_p.h \ $$PWD/entity_p.h \ + $$PWD/entity_p_p.h \ $$PWD/entityvisitor_p.h \ $$PWD/entityaccumulator_p.h \ $$PWD/layer_p.h \ diff --git a/src/render/backend/rendersettings.cpp b/src/render/backend/rendersettings.cpp index 702be9c60..487f6e11a 100644 --- a/src/render/backend/rendersettings.cpp +++ b/src/render/backend/rendersettings.cpp @@ -43,7 +43,6 @@ #include <Qt3DRender/private/abstractrenderer_p.h> #include <Qt3DRender/private/qrendersettings_p.h> #include <Qt3DCore/qnodecommand.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/rendertarget.cpp b/src/render/backend/rendertarget.cpp index 206f64e4e..088818c94 100644 --- a/src/render/backend/rendertarget.cpp +++ b/src/render/backend/rendertarget.cpp @@ -41,9 +41,6 @@ #include <Qt3DRender/qrendertarget.h> #include <Qt3DRender/private/qrendertarget_p.h> #include <Qt3DRender/qrendertargetoutput.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <QVariant> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/rendertargetoutput.cpp b/src/render/backend/rendertargetoutput.cpp index edfc7132e..e98acf3b8 100644 --- a/src/render/backend/rendertargetoutput.cpp +++ b/src/render/backend/rendertargetoutput.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include <Qt3DRender/private/rendertargetoutput_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtexture.h> #include <Qt3DRender/private/qrendertargetoutput_p.h> #include <QVariant> diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp index 6659657fa..8e98801b7 100644 --- a/src/render/backend/transform.cpp +++ b/src/render/backend/transform.cpp @@ -88,28 +88,6 @@ QVector3D Transform::translation() const return m_translation; } -// TODOSYNC remove once we've found a way to propagate animation changes -void Transform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - // TODO: Flag the matrix as dirty and update all matrices batched in a job - if (e->type() == PropertyUpdated) { - const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("scale3D")) { - m_scale = propertyChange->value().value<QVector3D>(); - updateMatrix(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) { - m_rotation = propertyChange->value().value<QQuaternion>(); - updateMatrix(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) { - m_translation = propertyChange->value().value<QVector3D>(); - updateMatrix(); - } - } - markDirty(AbstractRenderer::TransformDirty); - - BackendNode::sceneChangeEvent(e); -} - void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { const Qt3DCore::QTransform *transform = qobject_cast<const Qt3DCore::QTransform *>(frontEnd); @@ -131,15 +109,6 @@ void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) BackendNode::syncFromFrontEnd(frontEnd, firstTime); } -void Transform::notifyWorldTransformChanged(const Matrix4x4 &worldMatrix) -{ - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("worldMatrix"); - change->setValue(convertToQMatrix4x4(worldMatrix)); - notifyObservers(change); -} - void Transform::updateMatrix() { QMatrix4x4 m; diff --git a/src/render/backend/transform_p.h b/src/render/backend/transform_p.h index 50857ac94..8c0cd826a 100644 --- a/src/render/backend/transform_p.h +++ b/src/render/backend/transform_p.h @@ -76,9 +76,7 @@ public: QQuaternion rotation() const; QVector3D translation() const; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final; - void notifyWorldTransformChanged(const Matrix4x4 &worldMatrix); private: void updateMatrix(); diff --git a/src/render/framegraph/blitframebuffer.cpp b/src/render/framegraph/blitframebuffer.cpp index c45d3fdbc..0ecfbf5c4 100644 --- a/src/render/framegraph/blitframebuffer.cpp +++ b/src/render/framegraph/blitframebuffer.cpp @@ -39,7 +39,6 @@ #include <Qt3DRender/private/qblitframebuffer_p.h> #include <Qt3DRender/private/blitframebuffer_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/buffercapture.cpp b/src/render/framegraph/buffercapture.cpp index 4e89150df..b5e80eb29 100644 --- a/src/render/framegraph/buffercapture.cpp +++ b/src/render/framegraph/buffercapture.cpp @@ -40,7 +40,6 @@ #include <Qt3DRender/private/qbuffercapture_p.h> #include <Qt3DRender/private/buffercapture_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/cameraselectornode.cpp b/src/render/framegraph/cameraselectornode.cpp index 482429b00..3beb0ef71 100644 --- a/src/render/framegraph/cameraselectornode.cpp +++ b/src/render/framegraph/cameraselectornode.cpp @@ -40,9 +40,7 @@ #include "cameraselectornode_p.h" #include <Qt3DRender/private/qcameraselector_p.h> #include <Qt3DRender/private/renderer_p.h> -#include <Qt3DCore/private/qchangearbiter_p.h> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/renderlogging_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/clearbuffers.cpp b/src/render/framegraph/clearbuffers.cpp index 7d018c935..3f99e0e20 100644 --- a/src/render/framegraph/clearbuffers.cpp +++ b/src/render/framegraph/clearbuffers.cpp @@ -39,7 +39,6 @@ #include "clearbuffers_p.h" #include <Qt3DRender/private/qclearbuffers_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -52,16 +51,16 @@ static QVector4D vec4dFromColor(const QColor &color) { if (!color.isValid()) return QVector4D(0.0f, 0.0f, 0.0f, 1.0f); - return QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + return QVector4D(float(color.redF()), float(color.greenF()), float(color.blueF()), float(color.alphaF())); } ClearBuffers::ClearBuffers() : FrameGraphNode(FrameGraphNode::ClearBuffers) , m_type(QClearBuffers::None) + , m_clearColor(vec4dFromColor(m_clearColorAsColor)) + , m_clearColorAsColor(Qt::black) , m_clearDepthValue(1.f) , m_clearStencilValue(0) - , m_clearColorAsColor(Qt::black) - , m_clearColor(vec4dFromColor(m_clearColorAsColor)) { } @@ -79,7 +78,7 @@ void ClearBuffers::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) markDirty(AbstractRenderer::FrameGraphDirty); } - if (m_clearDepthValue != node->clearDepthValue()) { + if (!qFuzzyCompare(m_clearDepthValue, node->clearDepthValue())) { m_clearDepthValue = node->clearDepthValue(); markDirty(AbstractRenderer::FrameGraphDirty); } diff --git a/src/render/framegraph/dispatchcompute.cpp b/src/render/framegraph/dispatchcompute.cpp index 5eae75bc6..4161d37b5 100644 --- a/src/render/framegraph/dispatchcompute.cpp +++ b/src/render/framegraph/dispatchcompute.cpp @@ -39,7 +39,6 @@ #include "dispatchcompute_p.h" #include <Qt3DRender/private/qdispatchcompute_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/framegraphnode.cpp b/src/render/framegraph/framegraphnode.cpp index 93531fd7d..58ff05dc0 100644 --- a/src/render/framegraph/framegraphnode.cpp +++ b/src/render/framegraph/framegraphnode.cpp @@ -41,7 +41,6 @@ #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/frustumculling.cpp b/src/render/framegraph/frustumculling.cpp index 9f38d6be9..cf3a4ec57 100644 --- a/src/render/framegraph/frustumculling.cpp +++ b/src/render/framegraph/frustumculling.cpp @@ -39,7 +39,6 @@ #include "frustumculling_p.h" #include <Qt3DRender/qfrustumculling.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/layerfilternode.cpp b/src/render/framegraph/layerfilternode.cpp index 5c53fa681..f50fc1306 100644 --- a/src/render/framegraph/layerfilternode.cpp +++ b/src/render/framegraph/layerfilternode.cpp @@ -40,9 +40,6 @@ #include "layerfilternode_p.h" #include "qlayerfilter.h" #include <Qt3DRender/private/qlayerfilter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <algorithm> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/memorybarrier.cpp b/src/render/framegraph/memorybarrier.cpp index 6bfaedda7..bcc81464a 100644 --- a/src/render/framegraph/memorybarrier.cpp +++ b/src/render/framegraph/memorybarrier.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "memorybarrier_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qmemorybarrier_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/nodraw.cpp b/src/render/framegraph/nodraw.cpp index f2020d7ce..f64eb92d7 100644 --- a/src/render/framegraph/nodraw.cpp +++ b/src/render/framegraph/nodraw.cpp @@ -39,7 +39,6 @@ #include "nodraw_p.h" #include <Qt3DRender/qnodraw.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/proximityfilter.cpp b/src/render/framegraph/proximityfilter.cpp index 593e541bc..03dd2a7ec 100644 --- a/src/render/framegraph/proximityfilter.cpp +++ b/src/render/framegraph/proximityfilter.cpp @@ -39,7 +39,6 @@ #include "proximityfilter_p.h" #include <Qt3DRender/private/qproximityfilter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qblitframebuffer.cpp b/src/render/framegraph/qblitframebuffer.cpp index bf9e547cb..3a26e3d56 100644 --- a/src/render/framegraph/qblitframebuffer.cpp +++ b/src/render/framegraph/qblitframebuffer.cpp @@ -40,7 +40,6 @@ #include "qblitframebuffer.h" #include "qblitframebuffer_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qbuffercapture.cpp b/src/render/framegraph/qbuffercapture.cpp index d1d301077..0c12a3aff 100644 --- a/src/render/framegraph/qbuffercapture.cpp +++ b/src/render/framegraph/qbuffercapture.cpp @@ -40,7 +40,6 @@ #include <Qt3DRender/qbuffercapture.h> #include <Qt3DRender/private/qbuffercapture_p.h> #include <Qt3DCore/QSceneChange> -#include <Qt3DCore/QPropertyUpdatedChange> #include <Qt3DRender/QFrameGraphNodeCreatedChange> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qcameraselector.cpp b/src/render/framegraph/qcameraselector.cpp index 45abf638e..af293dc56 100644 --- a/src/render/framegraph/qcameraselector.cpp +++ b/src/render/framegraph/qcameraselector.cpp @@ -41,7 +41,6 @@ #include "qcameraselector_p.h" #include <Qt3DCore/qentity.h> #include <Qt3DCore/private/qentity_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qclearbuffers.cpp b/src/render/framegraph/qclearbuffers.cpp index 4cc4c98b6..31a31420c 100644 --- a/src/render/framegraph/qclearbuffers.cpp +++ b/src/render/framegraph/qclearbuffers.cpp @@ -39,7 +39,6 @@ #include "qclearbuffers.h" #include "qclearbuffers_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp index 1ef81a081..2390cb1c9 100644 --- a/src/render/framegraph/qframegraphnode.cpp +++ b/src/render/framegraph/qframegraphnode.cpp @@ -40,7 +40,6 @@ #include "qframegraphnode.h" #include "qframegraphnode_p.h" #include <Qt3DRender/qframegraphnodecreatedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/QNode> diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp index 8b0dd5669..5080012fd 100644 --- a/src/render/framegraph/qlayerfilter.cpp +++ b/src/render/framegraph/qlayerfilter.cpp @@ -40,9 +40,6 @@ #include "qlayerfilter.h" #include "qlayerfilter_p.h" #include "qlayer.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qrenderpassfilter.cpp b/src/render/framegraph/qrenderpassfilter.cpp index 4ef7e6d2d..778d3fa1f 100644 --- a/src/render/framegraph/qrenderpassfilter.cpp +++ b/src/render/framegraph/qrenderpassfilter.cpp @@ -42,9 +42,6 @@ #include <Qt3DRender/qfilterkey.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qrenderstateset.cpp b/src/render/framegraph/qrenderstateset.cpp index d558a939e..8c2c6ee7f 100644 --- a/src/render/framegraph/qrenderstateset.cpp +++ b/src/render/framegraph/qrenderstateset.cpp @@ -41,9 +41,6 @@ #include "qrenderstateset_p.h" #include <Qt3DRender/qrenderstate.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qrendersurfaceselector.cpp b/src/render/framegraph/qrendersurfaceselector.cpp index 765aa1824..df30663cb 100644 --- a/src/render/framegraph/qrendersurfaceselector.cpp +++ b/src/render/framegraph/qrendersurfaceselector.cpp @@ -44,7 +44,6 @@ #include <QtGui/QScreen> #include <QtGui/QOffscreenSurface> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qrendersettings.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> @@ -252,17 +251,17 @@ void QRenderSurfaceSelector::setSurface(QObject *surfaceObject) d->m_surfaceEventFilter->setSurface(window); if (window) { - d->m_widthConn = QObject::connect(window, &QWindow::widthChanged, [=] (int width) { + d->m_widthConn = QObject::connect(window, &QWindow::widthChanged, [=] (int) { d->update(); }); - d->m_heightConn = QObject::connect(window, &QWindow::heightChanged, [=] (int height) { + d->m_heightConn = QObject::connect(window, &QWindow::heightChanged, [=] (int) { d->update(); }); d->m_screenConn = QObject::connect(window, &QWindow::screenChanged, [=] (QScreen *screen) { - if (screen && surfacePixelRatio() != screen->devicePixelRatio()) - setSurfacePixelRatio(screen->devicePixelRatio()); + if (screen && !qFuzzyCompare(surfacePixelRatio(), float(screen->devicePixelRatio()))) + setSurfacePixelRatio(float(screen->devicePixelRatio())); }); - setSurfacePixelRatio(window->devicePixelRatio()); + setSurfacePixelRatio(float(window->devicePixelRatio())); } break; @@ -292,7 +291,7 @@ QSize QRenderSurfaceSelector::externalRenderTargetSize() const void QRenderSurfaceSelector::setSurfacePixelRatio(float ratio) { Q_D(QRenderSurfaceSelector); - if (d->m_surfacePixelRatio == ratio) + if (qFuzzyCompare(d->m_surfacePixelRatio, ratio)) return; d->m_surfacePixelRatio = ratio; emit surfacePixelRatioChanged(ratio); diff --git a/src/render/framegraph/qrendertargetselector.cpp b/src/render/framegraph/qrendertargetselector.cpp index f4d95d507..c997c23cc 100644 --- a/src/render/framegraph/qrendertargetselector.cpp +++ b/src/render/framegraph/qrendertargetselector.cpp @@ -40,7 +40,6 @@ #include "qrendertargetselector.h" #include "qrendertargetselector_p.h" #include <Qt3DRender/qrendertarget.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderpass_p.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> diff --git a/src/render/framegraph/qsortpolicy.cpp b/src/render/framegraph/qsortpolicy.cpp index c8e3d23c5..a24dd5eae 100644 --- a/src/render/framegraph/qsortpolicy.cpp +++ b/src/render/framegraph/qsortpolicy.cpp @@ -102,6 +102,8 @@ QSortPolicyPrivate::QSortPolicyPrivate() \value FrontToBack sort the objects from front to back. The opposite of BackToFront. + + \value [since 5.14] Texture sort the objects to minimize texture changes. */ /*! @@ -124,6 +126,7 @@ QSortPolicyPrivate::QSortPolicyPrivate() \li Material - sort the objects based on their material value \li FrontToBack - sort the objects from front to back. The opposite of BackToFront. + \li [since 5.14] Texture - sort the objects to minimize texture changes. \endlist */ diff --git a/src/render/framegraph/qtechniquefilter.cpp b/src/render/framegraph/qtechniquefilter.cpp index 28b151fc7..03e6a8ca7 100644 --- a/src/render/framegraph/qtechniquefilter.cpp +++ b/src/render/framegraph/qtechniquefilter.cpp @@ -41,9 +41,6 @@ #include "qtechniquefilter_p.h" #include <Qt3DRender/qfilterkey.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qviewport.cpp b/src/render/framegraph/qviewport.cpp index 539e02d65..34716c5b5 100644 --- a/src/render/framegraph/qviewport.cpp +++ b/src/render/framegraph/qviewport.cpp @@ -40,7 +40,6 @@ #include "qviewport.h" #include "qviewport_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/renderpassfilternode.cpp b/src/render/framegraph/renderpassfilternode.cpp index afc49a563..bcec38fb6 100644 --- a/src/render/framegraph/renderpassfilternode.cpp +++ b/src/render/framegraph/renderpassfilternode.cpp @@ -42,9 +42,6 @@ #include "qrenderpassfilter.h" #include <Qt3DRender/private/qrenderpassfilter_p.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/rendersurfaceselector.cpp b/src/render/framegraph/rendersurfaceselector.cpp index ed8a79eac..a1e639df5 100644 --- a/src/render/framegraph/rendersurfaceselector.cpp +++ b/src/render/framegraph/rendersurfaceselector.cpp @@ -40,7 +40,6 @@ #include "rendersurfaceselector_p.h" #include <Qt3DRender/qrendersurfaceselector.h> #include <Qt3DRender/private/qrendersurfaceselector_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtGui/qwindow.h> #include <QtGui/qscreen.h> diff --git a/src/render/framegraph/rendertargetselectornode.cpp b/src/render/framegraph/rendertargetselectornode.cpp index 871a00154..614a749a5 100644 --- a/src/render/framegraph/rendertargetselectornode.cpp +++ b/src/render/framegraph/rendertargetselectornode.cpp @@ -43,7 +43,6 @@ #include <Qt3DRender/qrendertargetselector.h> #include <Qt3DRender/private/qrendertargetselector_p.h> #include <Qt3DRender/qrendertarget.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/renderlogging_p.h> #include <Qt3DRender/qrendertargetoutput.h> diff --git a/src/render/framegraph/sortpolicy.cpp b/src/render/framegraph/sortpolicy.cpp index 3c7975945..5c61966c0 100644 --- a/src/render/framegraph/sortpolicy.cpp +++ b/src/render/framegraph/sortpolicy.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "sortpolicy_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qsortpolicy_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/statesetnode.cpp b/src/render/framegraph/statesetnode.cpp index 32ac5e569..c494c572b 100644 --- a/src/render/framegraph/statesetnode.cpp +++ b/src/render/framegraph/statesetnode.cpp @@ -43,9 +43,6 @@ #include <Qt3DRender/private/qrenderstateset_p.h> #include <Qt3DRender/private/genericstate_p.h> #include <Qt3DRender/private/renderstateset_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/techniquefilternode.cpp b/src/render/framegraph/techniquefilternode.cpp index 8739143e6..b3b70e9cb 100644 --- a/src/render/framegraph/techniquefilternode.cpp +++ b/src/render/framegraph/techniquefilternode.cpp @@ -43,9 +43,6 @@ #include <Qt3DRender/private/qtechniquefilter_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/viewportnode.cpp b/src/render/framegraph/viewportnode.cpp index c37278817..5396d97e2 100644 --- a/src/render/framegraph/viewportnode.cpp +++ b/src/render/framegraph/viewportnode.cpp @@ -40,7 +40,6 @@ #include "viewportnode_p.h" #include <Qt3DRender/qviewport.h> #include <Qt3DRender/private/qviewport_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/waitfence.cpp b/src/render/framegraph/waitfence.cpp index 68ddda3d7..829730bbf 100644 --- a/src/render/framegraph/waitfence.cpp +++ b/src/render/framegraph/waitfence.cpp @@ -39,7 +39,6 @@ #include "waitfence_p.h" #include <Qt3DRender/private/qwaitfence_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> // // W A R N I N G diff --git a/src/render/frontend/qcameralens_p.h b/src/render/frontend/qcameralens_p.h index 01fcac0e5..5c5a6a42a 100644 --- a/src/render/frontend/qcameralens_p.h +++ b/src/render/frontend/qcameralens_p.h @@ -57,8 +57,6 @@ #include "qcameralens.h" -#include <Qt3DCore/qpropertyupdatedchange.h> - #include <QtGui/qmatrix4x4.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp index b0bec42d4..d040150d5 100644 --- a/src/render/frontend/qcomputecommand.cpp +++ b/src/render/frontend/qcomputecommand.cpp @@ -39,7 +39,6 @@ #include "qcomputecommand.h" #include "qcomputecommand_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp index a3596a518..3d0cb9553 100644 --- a/src/render/frontend/qlevelofdetail.cpp +++ b/src/render/frontend/qlevelofdetail.cpp @@ -40,7 +40,6 @@ #include "qlevelofdetail.h" #include "qlevelofdetail_p.h" #include "qcamera.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -55,6 +54,15 @@ QLevelOfDetailPrivate::QLevelOfDetailPrivate() { } +void QLevelOfDetailPrivate::setCurrentIndex(int currentIndex) +{ + Q_Q(QLevelOfDetail); + if (m_currentIndex != currentIndex) { + m_currentIndex = currentIndex; + emit q->currentIndexChanged(m_currentIndex); + } +} + /*! \class Qt3DRender::QLevelOfDetail \inmodule Qt3DRender @@ -317,20 +325,6 @@ Qt3DCore::QNodeCreatedChangeBasePtr QLevelOfDetail::createNodeCreationChange() c return creationChange; } -/*! \internal */ -void QLevelOfDetail::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QLevelOfDetail); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("currentIndex")) { - int ndx = e->value().value<int>(); - d->m_currentIndex = ndx; - emit currentIndexChanged(ndx); - } - } -} - QCamera *QLevelOfDetail::camera() const { Q_D(const QLevelOfDetail); @@ -367,10 +361,7 @@ int QLevelOfDetail::currentIndex() const void QLevelOfDetail::setCurrentIndex(int currentIndex) { Q_D(QLevelOfDetail); - if (d->m_currentIndex != currentIndex) { - d->m_currentIndex = currentIndex; - emit currentIndexChanged(d->m_currentIndex); - } + d->setCurrentIndex(currentIndex); } QLevelOfDetail::ThresholdType QLevelOfDetail::thresholdType() const diff --git a/src/render/frontend/qlevelofdetail.h b/src/render/frontend/qlevelofdetail.h index 308a4d3c0..f6c09a287 100644 --- a/src/render/frontend/qlevelofdetail.h +++ b/src/render/frontend/qlevelofdetail.h @@ -97,7 +97,6 @@ Q_SIGNALS: protected: explicit QLevelOfDetail(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr); Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QLevelOfDetail) diff --git a/src/render/frontend/qlevelofdetail_p.h b/src/render/frontend/qlevelofdetail_p.h index 7b409e4ca..429128427 100644 --- a/src/render/frontend/qlevelofdetail_p.h +++ b/src/render/frontend/qlevelofdetail_p.h @@ -72,6 +72,8 @@ public: void _q_radiusChanged(float radius); void _q_centerChanged(const QVector3D ¢er); + virtual void setCurrentIndex(int currentIndex); + QCamera *m_camera; int m_currentIndex; QLevelOfDetail::ThresholdType m_thresholdType; diff --git a/src/render/frontend/qlevelofdetailswitch.cpp b/src/render/frontend/qlevelofdetailswitch.cpp index 845fdd5a6..7b888fe98 100644 --- a/src/render/frontend/qlevelofdetailswitch.cpp +++ b/src/render/frontend/qlevelofdetailswitch.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qlevelofdetailswitch.h" +#include "qlevelofdetailswitch_p.h" #include "qlevelofdetail_p.h" #include "qglobal.h" #include <Qt3DCore/QEntity> @@ -47,6 +48,38 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +QLevelOfDetailSwitchPrivate::QLevelOfDetailSwitchPrivate() + : QLevelOfDetailPrivate() +{ + +} + +void QLevelOfDetailSwitchPrivate::setCurrentIndex(int currentIndex) +{ + Q_Q(QLevelOfDetailSwitch); + + bool changed = m_currentIndex != currentIndex; + QLevelOfDetailPrivate::setCurrentIndex(currentIndex); + + if (!changed) + return; + + int entityIndex = 0; + const auto entities = q->entities(); + for (Qt3DCore::QEntity *entity : entities) { + const auto childNodes = entity->childNodes(); + for (Qt3DCore::QNode *childNode : childNodes) { + Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(childNode); + if (childEntity) { + childEntity->setEnabled(entityIndex == currentIndex); + entityIndex++; + } + } + + break; // only work on the first entity, LOD should not be shared + } +} + /*! \class Qt3DRender::QLevelOfDetailSwitch \inmodule Qt3DRender @@ -84,9 +117,9 @@ namespace Qt3DRender { Constructs a new QLevelOfDetailSwitch with the specified \a parent. */ QLevelOfDetailSwitch::QLevelOfDetailSwitch(QNode *parent) - : QLevelOfDetail(parent) + : QLevelOfDetail(*new QLevelOfDetailSwitchPrivate(), parent) { - Q_D(QLevelOfDetail); + Q_D(QLevelOfDetailSwitch); d->m_currentIndex = -1; } @@ -101,34 +134,6 @@ QLevelOfDetailSwitch::QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, QNode *par { } -/*! \internal */ -void QLevelOfDetailSwitch::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QLevelOfDetail); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("currentIndex")) { - int ndx = e->value().value<int>(); - d->m_currentIndex = ndx; - emit currentIndexChanged(ndx); - - int entityIndex = 0; - const auto entities = this->entities(); - for (Qt3DCore::QEntity *entity : entities) { - const auto childNodes = entity->childNodes(); - for (Qt3DCore::QNode *childNode : childNodes) { - Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(childNode); - if (childEntity) { - childEntity->setEnabled(entityIndex == ndx); - entityIndex++; - } - } - break; // only work on the first entity, LOD should not be shared - } - } - } -} - } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/render/frontend/qlevelofdetailswitch.h b/src/render/frontend/qlevelofdetailswitch.h index 1615d16e6..90f4ee3e2 100644 --- a/src/render/frontend/qlevelofdetailswitch.h +++ b/src/render/frontend/qlevelofdetailswitch.h @@ -45,6 +45,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +class QLevelOfDetailSwitchPrivate; class Q_3DRENDERSHARED_EXPORT QLevelOfDetailSwitch : public QLevelOfDetail { @@ -56,10 +57,9 @@ public: protected: explicit QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: - Q_DECLARE_PRIVATE(QLevelOfDetail) + Q_DECLARE_PRIVATE(QLevelOfDetailSwitch) }; } // namespace Qt3DRender diff --git a/src/render/renderers/opengl/renderer/glcommands_p.h b/src/render/frontend/qlevelofdetailswitch_p.h index 5ed360759..51321c986 100644 --- a/src/render/renderers/opengl/renderer/glcommands_p.h +++ b/src/render/frontend/qlevelofdetailswitch_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QT3DRENDER_RENDER_GLCOMMANDS_P_H -#define QT3DRENDER_RENDER_GLCOMMANDS_P_H +#ifndef QT3DRENDER_QLEVELOFDETAILSWITCH_P_H +#define QT3DRENDER_QLEVELOFDETAILSWITCH_P_H // // W A R N I N G @@ -51,39 +51,27 @@ // We mean it. // -#include <Qt3DRender/qt3drender_global.h> +#include <Qt3DRender/private/qlevelofdetail_p.h> +#include <Qt3DRender/qlevelofdetailswitch.h> -QT_BEGIN_NAMESPACE +#include <QVector3D> +QT_BEGIN_NAMESPACE namespace Qt3DRender { -namespace Render { - -class GraphicsContext; -class Renderer; -class Shader; - -class GLCommand +class Q_3DRENDERSHARED_PRIVATE_EXPORT QLevelOfDetailSwitchPrivate : public QLevelOfDetailPrivate { public: - virtual void execute(Renderer *renderer, GraphicsContext *ctx) = 0; -}; + QLevelOfDetailSwitchPrivate(); -class Q_AUTOTEST_EXPORT LoadShaderCommand : public GLCommand -{ -public: - explicit LoadShaderCommand(Shader *shader); - Shader *shader() const { return m_shader; } - void execute(Renderer *renderer, GraphicsContext *ctx) Q_DECL_OVERRIDE; + Q_DECLARE_PUBLIC(QLevelOfDetailSwitch) -private: - Shader *m_shader = nullptr; + void setCurrentIndex(int currentIndex) override; }; -} // Render -} // Qt3DRender +} // namespace Qt3DRender QT_END_NAMESPACE -#endif // QT3DRENDER_RENDER_GLCOMMANDS_P_H +#endif // QT3DRENDER_QLEVELOFDETAILSWITCH_P_H diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 70ec70b2b..159c11981 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -288,7 +288,7 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<QMaterial, true>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer)); q->registerBackendType<QParameter, true>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer)); q->registerBackendType<QRenderPass, true>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer)); - q->registerBackendType<QShaderData>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<QShaderData, true>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<QShaderProgram, true>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer)); q->registerBackendType<QShaderProgramBuilder, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer)); q->registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers)); diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp index 2a74db775..7269a8067 100644 --- a/src/render/frontend/qrendertarget.cpp +++ b/src/render/frontend/qrendertarget.cpp @@ -40,9 +40,6 @@ #include "qrendertarget.h" #include "qrendertarget_p.h" #include "qrendertargetoutput.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/qrendertargetoutput.cpp b/src/render/frontend/qrendertargetoutput.cpp index 14ac9c817..8c0d86134 100644 --- a/src/render/frontend/qrendertargetoutput.cpp +++ b/src/render/frontend/qrendertargetoutput.cpp @@ -40,7 +40,6 @@ #include "qrendertargetoutput.h" #include "qrendertargetoutput_p.h" #include "qtexture.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri index 1fafcc294..0153e9c97 100644 --- a/src/render/frontend/render-frontend.pri +++ b/src/render/frontend/render-frontend.pri @@ -9,6 +9,7 @@ HEADERS += \ $$PWD/qlevelofdetail.h \ $$PWD/qlevelofdetail_p.h \ $$PWD/qlevelofdetailswitch.h \ + $$PWD/qlevelofdetailswitch_p.h \ $$PWD/qrendertarget.h \ $$PWD/qrendertarget_p.h \ $$PWD/sphere_p.h \ diff --git a/src/render/geometry/armature.cpp b/src/render/geometry/armature.cpp index cfa2e572a..6e417952b 100644 --- a/src/render/geometry/armature.cpp +++ b/src/render/geometry/armature.cpp @@ -38,7 +38,6 @@ #include <Qt3DCore/qarmature.h> #include <Qt3DCore/qabstractskeleton.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qarmature_p.h> diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp index f241a85e5..de44c5fe3 100644 --- a/src/render/geometry/attribute.cpp +++ b/src/render/geometry/attribute.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "attribute_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qbuffer.h> #include <Qt3DRender/private/qattribute_p.h> #include <Qt3DRender/private/stringtoint_p.h> diff --git a/src/render/geometry/geometry.cpp b/src/render/geometry/geometry.cpp index cb401df5b..56ea936be 100644 --- a/src/render/geometry/geometry.cpp +++ b/src/render/geometry/geometry.cpp @@ -42,8 +42,6 @@ #include <Qt3DRender/qgeometry.h> #include <Qt3DRender/private/qgeometry_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <algorithm> diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp index b5c741659..3b460f48c 100644 --- a/src/render/geometry/geometryrenderer.cpp +++ b/src/render/geometry/geometryrenderer.cpp @@ -43,8 +43,6 @@ #include <Qt3DRender/private/qgeometryrenderer_p.h> #include <Qt3DRender/private/qmesh_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qtypedpropertyupdatechange_p.h> #include <Qt3DCore/private/qservicelocator_p.h> @@ -148,7 +146,7 @@ void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) markDirty(AbstractRenderer::GeometryDirty); } -void GeometryRenderer::executeFunctor() +GeometryFunctorResult GeometryRenderer::executeFunctor() { Q_ASSERT(m_geometryFactory); @@ -169,7 +167,8 @@ void GeometryRenderer::executeFunctor() } // Load geometry - std::unique_ptr<QGeometry> geometry((*m_geometryFactory)()); + QGeometry *geometry = (*m_geometryFactory)(); + QMesh::Status meshLoaderStatus = QMesh::None; // If the geometry is null, then we were either unable to load it (Error) // or the mesh is located at a remote url and needs to be downloaded first (Loading) @@ -178,24 +177,15 @@ void GeometryRenderer::executeFunctor() // corresponding QGeometryRenderer const auto appThread = QCoreApplication::instance()->thread(); geometry->moveToThread(appThread); - - auto e = QGeometryChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - e->setPropertyName("geometry"); - e->data = std::move(geometry); - notifyObservers(e); } // Send Status if (isQMeshFunctor) { QSharedPointer<MeshLoaderFunctor> meshLoader = qSharedPointerCast<MeshLoaderFunctor>(m_geometryFactory); - - auto e = QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - e->setPropertyName("status"); - e->setValue(meshLoader->status()); - notifyObservers(e); + meshLoaderStatus = meshLoader->status(); } + + return { geometry, meshLoaderStatus }; } void GeometryRenderer::unsetDirty() diff --git a/src/render/geometry/geometryrenderer_p.h b/src/render/geometry/geometryrenderer_p.h index da538a00d..d2ddad4bb 100644 --- a/src/render/geometry/geometryrenderer_p.h +++ b/src/render/geometry/geometryrenderer_p.h @@ -54,6 +54,7 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/qgeometryfactory.h> +#include <Qt3DRender/qmesh.h> QT_BEGIN_NAMESPACE @@ -66,6 +67,12 @@ namespace Render { class GeometryRendererManager; +struct GeometryFunctorResult +{ + QGeometry *geometry; + QMesh::Status status; +}; + class Q_AUTOTEST_EXPORT GeometryRenderer : public BackendNode { public: @@ -75,7 +82,7 @@ public: void cleanup(); void setManager(GeometryRendererManager *manager); void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; - void executeFunctor(); + GeometryFunctorResult executeFunctor(); inline Qt3DCore::QNodeId geometryId() const { return m_geometryId; } inline int instanceCount() const { return m_instanceCount; } diff --git a/src/render/geometry/joint.cpp b/src/render/geometry/joint.cpp index 86d583f51..9791f6c52 100644 --- a/src/render/geometry/joint.cpp +++ b/src/render/geometry/joint.cpp @@ -41,9 +41,6 @@ #include <Qt3DRender/private/managers_p.h> #include <Qt3DCore/QJoint> #include <Qt3DCore/private/qjoint_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <algorithm> @@ -72,69 +69,24 @@ void Joint::cleanup() setEnabled(false); } -// TODOSYNC remove once animation changes don't use messages anymore -void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("scale")) { - m_localPose.scale = propertyChange->value().value<QVector3D>(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) { - m_localPose.rotation = propertyChange->value().value<QQuaternion>(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) { - m_localPose.translation = propertyChange->value().value<QVector3D>(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("inverseBindMatrix")) { - // Setting the inverse bind matrix should be a rare operation. Usually it is - // set once and then remains constant for the duration of the skeleton. So just - // trigger a rebuild of the skeleton's SkeletonData which will include obtaining - // the inverse bind matrix. - m_inverseBindMatrix = propertyChange->value().value<QMatrix4x4>(); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_owningSkeleton); - } else if (propertyChange->propertyName() == QByteArrayLiteral("name")) { - // Joint name doesn't affect anything in the render aspect so no need - // to mark anything as dirty. - m_name = propertyChange->value().toString(); - - // TODO: Notify other aspects (animation) about the name change. - } - } else if (e->type() == PropertyValueAdded) { - const auto addedChange = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (addedChange->propertyName() == QByteArrayLiteral("childJoint")) - m_childJointIds.push_back(addedChange->addedNodeId()); - } else if (e->type() == PropertyValueRemoved) { - const auto removedChange = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (removedChange->propertyName() == QByteArrayLiteral("childJoint")) - m_childJointIds.removeOne(removedChange->removedNodeId()); - } - BackendNode::sceneChangeEvent(e); -} - void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { const Qt3DCore::QJoint *joint = qobject_cast<const Qt3DCore::QJoint *>(frontEnd); if (!joint) return; + bool jointDirty = firstTime; if (m_localPose.scale != joint->scale()) { m_localPose.scale = joint->scale(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); + jointDirty = true; } if (m_localPose.rotation != joint->rotation()) { m_localPose.rotation = joint->rotation(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); + jointDirty = true; } if (m_localPose.translation != joint->translation()) { m_localPose.translation = joint->translation(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); + jointDirty = true; } if (m_inverseBindMatrix != joint->inverseBindMatrix()) { // Setting the inverse bind matrix should be a rare operation. Usually it is @@ -154,11 +106,10 @@ void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) Qt3DCore::QNodeIdVector childIds = qIdsForNodes(joint->childJoints()); std::sort(std::begin(childIds), std::end(childIds)); - if (m_childJointIds != childIds) { + if (m_childJointIds != childIds) m_childJointIds = childIds; - } - if (firstTime) { + if (jointDirty) { markDirty(AbstractRenderer::JointDirty); m_jointManager->addDirtyJoint(peerId()); } diff --git a/src/render/geometry/joint_p.h b/src/render/geometry/joint_p.h index d0530ac04..de875459e 100644 --- a/src/render/geometry/joint_p.h +++ b/src/render/geometry/joint_p.h @@ -69,7 +69,6 @@ public: Joint(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::Sqt localPose() const { return m_localPose; } diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp index a28d0baa6..84d14cfe1 100644 --- a/src/render/geometry/qattribute.cpp +++ b/src/render/geometry/qattribute.cpp @@ -41,8 +41,6 @@ #include "qattribute_p.h" #include <Qt3DRender/qbuffer.h> -#include <Qt3DCore/qpropertyupdatedchange.h> - QT_BEGIN_NAMESPACE namespace Qt3DRender { diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp index 47fad4302..4b0bca3b3 100644 --- a/src/render/geometry/qgeometry.cpp +++ b/src/render/geometry/qgeometry.cpp @@ -43,8 +43,6 @@ #include <private/qnode_p.h> #include <Qt3DRender/qattribute.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp index ddea873a7..6e0a24f61 100644 --- a/src/render/geometry/qgeometryrenderer.cpp +++ b/src/render/geometry/qgeometryrenderer.cpp @@ -41,9 +41,6 @@ #include "qgeometryrenderer_p.h" #include <private/qcomponent_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE @@ -483,19 +480,6 @@ void QGeometryRenderer::setGeometryFactory(const QGeometryFactoryPtr &factory) d->update(); } -/*! - \internal - */ -void QGeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - auto change = qSharedPointerCast<QStaticPropertyUpdatedChangeBase>(e); - if (change->type() == PropertyUpdated && change->propertyName() == QByteArrayLiteral("geometry")) { - auto typedChange = qSharedPointerCast<QGeometryChange>(e); - auto geometry = std::move(typedChange->data); - setGeometry(geometry.release()); - } -} - Qt3DCore::QNodeCreatedChangeBasePtr QGeometryRenderer::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QGeometryRendererData>::create(this); diff --git a/src/render/geometry/qgeometryrenderer.h b/src/render/geometry/qgeometryrenderer.h index 81bd1ff67..eceeb9173 100644 --- a/src/render/geometry/qgeometryrenderer.h +++ b/src/render/geometry/qgeometryrenderer.h @@ -134,7 +134,6 @@ Q_SIGNALS: protected: explicit QGeometryRenderer(QGeometryRendererPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QGeometryRenderer) diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp index 66c4a69bc..1d7d33f9a 100644 --- a/src/render/geometry/qmesh.cpp +++ b/src/render/geometry/qmesh.cpp @@ -215,18 +215,6 @@ QMesh::QMesh(QMeshPrivate &dd, QNode *parent) { } -/*! \internal */ -void QMesh::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QMesh); - if (change->type() == Qt3DCore::PropertyUpdated) { - const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->propertyName() == QByteArrayLiteral("status")) - d->setStatus(e->value().value<QMesh::Status>()); - } - Qt3DRender::QGeometryRenderer::sceneChangeEvent(change); -} - void QMesh::setSource(const QUrl& source) { Q_D(QMesh); diff --git a/src/render/geometry/qmesh.h b/src/render/geometry/qmesh.h index 458a21fa4..04fdedc20 100644 --- a/src/render/geometry/qmesh.h +++ b/src/render/geometry/qmesh.h @@ -88,7 +88,6 @@ Q_SIGNALS: protected: explicit QMesh(QMeshPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QMesh) diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp index d4af1fe3c..839a1a056 100644 --- a/src/render/geometry/skeleton.cpp +++ b/src/render/geometry/skeleton.cpp @@ -36,24 +36,19 @@ #include "skeleton_p.h" -#include <Qt3DCore/qjoint.h> -#include <Qt3DCore/qpropertyupdatedchange.h> - #include <QCoreApplication> #include <QFile> #include <QFileInfo> +#include <Qt3DCore/qjoint.h> #include <Qt3DRender/private/abstractrenderer_p.h> -#include <Qt3DRender/private/gltfskeletonloader_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/renderlogging_p.h> -#include <Qt3DRender/private/qurlhelper_p.h> #include <Qt3DCore/private/qskeletoncreatedchange_p.h> #include <Qt3DCore/private/qskeleton_p.h> #include <Qt3DCore/private/qskeletonloader_p.h> #include <Qt3DCore/private/qmath3d_p.h> -#include <Qt3DCore/private/qabstractnodefactory_p.h> QT_BEGIN_NAMESPACE @@ -119,9 +114,9 @@ void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) } m_createJoints = loaderNode->isCreateJointsEnabled(); - if ((loaderNode->rootJoint() && loaderNode->rootJoint()->id() != m_rootJointId) || - (!loaderNode->rootJoint() && !m_rootJointId.isNull())) { - m_rootJointId = loaderNode->rootJoint() ? loaderNode->rootJoint()->id() : Qt3DCore::QNodeId{}; + auto newJointId = Qt3DCore::qIdForNode(loaderNode->rootJoint()); + if (newJointId != m_rootJointId) { + m_rootJointId = newJointId; // If using a QSkeletonLoader to create frontend QJoints, when those joints are // set on the skeleton, we end up here. In order to allow the subsequent call @@ -139,239 +134,15 @@ void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) } } } -} - -// TODOSYNC remove once animation aspect no longer requires messages -void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case Qt3DCore::PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("localPoses")) { - // When the animation aspect sends us a new set of local poses, all we - // need to do is copy them into place. The existing jobs will then update - // the skinning matrix palette. - m_skeletonData.localPoses = change->value().value<QVector<Qt3DCore::Sqt>>(); - } - - break; - } - default: - break; - } - QBackendNode::sceneChangeEvent(e); + auto d = Qt3DCore::QAbstractSkeletonPrivate::get(node); + m_skeletonData.localPoses = d->m_localPoses; } void Skeleton::setStatus(QSkeletonLoader::Status status) { - if (status != m_status) { + if (status != m_status) m_status = status; - Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("status"); - e->setValue(QVariant::fromValue(m_status)); - notifyObservers(e); - } -} - -void Skeleton::notifyJointCount() -{ - Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("jointCount"); - e->setValue(jointCount()); - notifyObservers(e); -} - -void Skeleton::notifyJointNamesAndPoses() -{ - auto e = QPropertyUpdatedChangePtr::create(peerId()); - JointNamesAndLocalPoses payload{m_skeletonData.jointNames, m_skeletonData.localPoses}; - e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes); - e->setPropertyName("jointNamesAndLocalPoses"); - e->setValue(QVariant::fromValue(payload)); - notifyObservers(e); -} - -void Skeleton::loadSkeleton() -{ - qCDebug(Jobs) << Q_FUNC_INFO << m_source; - clearData(); - - // Load the data - switch (m_dataType) { - case File: - loadSkeletonFromUrl(); - break; - - case Data: - loadSkeletonFromData(); - break; - - default: - Q_UNREACHABLE(); - } - - // If using a loader inform the frontend of the status change. - // Don't bother if asked to create frontend joints though. When - // the backend gets notified of those joints we'll update the - // status at that point. - if (m_dataType == File && !m_createJoints) { - if (jointCount() == 0) - setStatus(QSkeletonLoader::Error); - else - setStatus(QSkeletonLoader::Ready); - } - notifyJointCount(); - notifyJointNamesAndPoses(); - - qCDebug(Jobs) << "Loaded skeleton data:" << *this; -} - -void Skeleton::loadSkeletonFromUrl() -{ - // TODO: Handle remote files - QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_source); - QFileInfo info(filePath); - if (!info.exists()) { - qWarning() << "Could not open skeleton file:" << filePath; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "Could not open skeleton file:" << filePath; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - - // TODO: Make plugin based for more file type support. For now gltf or native - const QString ext = info.suffix(); - if (ext == QLatin1String("gltf")) { - GLTFSkeletonLoader loader; - loader.load(&file); - m_skeletonData = loader.createSkeleton(m_name); - - // If the user has requested it, create the frontend nodes for the joints - // and send them to the (soon to be owning) QSkeletonLoader. - if (m_createJoints) { - std::unique_ptr<QJoint> rootJoint(createFrontendJoints(m_skeletonData)); - if (!rootJoint) { - qWarning() << "Failed to create frontend joints"; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - - // Move the QJoint tree to the main thread and notify the - // corresponding QSkeletonLoader - const auto appThread = QCoreApplication::instance()->thread(); - rootJoint->moveToThread(appThread); - - auto e = QJointChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - e->setPropertyName("rootJoint"); - e->data = std::move(rootJoint); - notifyObservers(e); - - // Clear the skeleton data. It will be recreated from the - // frontend joints. A little bit inefficient but ensures - // that joints created this way and via QSkeleton go through - // the same code path. - m_skeletonData = SkeletonData(); - } - } else if (ext == QLatin1String("json")) { - // TODO: Support native skeleton type - } else { - qWarning() << "Unknown skeleton file type:" << ext; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - m_skinningPalette.resize(m_skeletonData.joints.size()); -} - -void Skeleton::loadSkeletonFromData() -{ - // Recurse down through the joint hierarchy and process it into - // the vector of joints used within SkeletonData. The recursion - // ensures that a parent always appears before its children in - // the vector of JointInfo objects. - // - // In addition, we set up a mapping from the joint ids to the - // index of the corresponding JointInfo object in the vector. - // This will allow us to easily update entries in the vector of - // JointInfos when a Joint node marks itself as dirty. - const int rootParentIndex = -1; - processJointHierarchy(m_rootJointId, rootParentIndex, m_skeletonData); - m_skinningPalette.resize(m_skeletonData.joints.size()); -} - -Qt3DCore::QJoint *Skeleton::createFrontendJoints(const SkeletonData &skeletonData) const -{ - if (skeletonData.joints.isEmpty()) - return nullptr; - - // Create frontend joints from the joint info objects - QVector<QJoint *> frontendJoints; - const int jointCount = skeletonData.joints.size(); - frontendJoints.reserve(jointCount); - for (int i = 0; i < jointCount; ++i) { - const QMatrix4x4 &inverseBindMatrix = skeletonData.joints[i].inverseBindPose; - const QString &jointName = skeletonData.jointNames[i]; - const Qt3DCore::Sqt &localPose = skeletonData.localPoses[i]; - frontendJoints.push_back(createFrontendJoint(jointName, localPose, inverseBindMatrix)); - } - - // Now go through and resolve the parent for each joint - for (int i = 0; i < frontendJoints.size(); ++i) { - const auto parentIndex = skeletonData.joints[i].parentIndex; - if (parentIndex == -1) - continue; - - // It's not enough to just set up the QObject parent-child relationship. - // We need to explicitly add the child to the parent's list of joints so - // that information is then propagated to the backend. - frontendJoints[parentIndex]->addChildJoint(frontendJoints[i]); - } - - return frontendJoints[0]; -} - -Qt3DCore::QJoint *Skeleton::createFrontendJoint(const QString &jointName, - const Qt3DCore::Sqt &localPose, - const QMatrix4x4 &inverseBindMatrix) const -{ - auto joint = QAbstractNodeFactory::createNode<QJoint>("QJoint"); - joint->setTranslation(localPose.translation); - joint->setRotation(localPose.rotation); - joint->setScale(localPose.scale); - joint->setInverseBindMatrix(inverseBindMatrix); - joint->setName(jointName); - return joint; -} - -void Skeleton::processJointHierarchy(Qt3DCore::QNodeId jointId, - int parentJointIndex, - SkeletonData &skeletonData) -{ - // Lookup the joint, create a JointInfo, and add an entry to the index map - Joint *joint = m_renderer->nodeManagers()->jointManager()->lookupResource(jointId); - Q_ASSERT(joint); - joint->setOwningSkeleton(m_skeletonHandle); - const JointInfo jointInfo(joint, parentJointIndex); - skeletonData.joints.push_back(jointInfo); - skeletonData.localPoses.push_back(joint->localPose()); - skeletonData.jointNames.push_back(joint->name()); - - const int jointIndex = skeletonData.joints.size() - 1; - const HJoint jointHandle = m_jointManager->lookupHandle(jointId); - skeletonData.jointIndices.insert(jointHandle, jointIndex); - - // Recurse to the children - const auto childIds = joint->childJointIds(); - for (const auto childJointId : childIds) - processJointHierarchy(childJointId, jointIndex, skeletonData); } void Skeleton::clearData() @@ -383,6 +154,12 @@ void Skeleton::clearData() m_skeletonData.jointIndices.clear(); } +void Skeleton::setSkeletonData(const SkeletonData &data) +{ + m_skeletonData = data; + m_skinningPalette.resize(m_skeletonData.joints.size()); +} + // Called from UpdateSkinningPaletteJob void Skeleton::setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose) { diff --git a/src/render/geometry/skeleton_p.h b/src/render/geometry/skeleton_p.h index 8247bb317..7a5299944 100644 --- a/src/render/geometry/skeleton_p.h +++ b/src/render/geometry/skeleton_p.h @@ -75,6 +75,12 @@ class SkeletonManager; class Q_AUTOTEST_EXPORT Skeleton : public BackendNode { public: + enum SkeletonDataType { + Unknown, + File, + Data + }; + Skeleton(); void setSkeletonManager(SkeletonManager *skeletonManager) { m_skeletonManager = skeletonManager; } @@ -84,52 +90,40 @@ public: JointManager *jointManager() const { return m_jointManager; } void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void setStatus(Qt3DCore::QSkeletonLoader::Status status); Qt3DCore::QSkeletonLoader::Status status() const { return m_status; } QUrl source() const { return m_source; } + SkeletonDataType dataType() const { return m_dataType; } + bool createJoints() const { return m_createJoints; } void setName(const QString &name) { m_name = name; } QString name() const { return m_name; } int jointCount() const { return m_skeletonData.joints.size(); } - void notifyJointCount(); - void notifyJointNamesAndPoses(); QVector<JointInfo> joints() const { return m_skeletonData.joints; } + QVector<QString> jointNames() const { return m_skeletonData.jointNames; } + QVector<Qt3DCore::Sqt> localPoses() const { return m_skeletonData.localPoses; } Qt3DCore::QNodeId rootJointId() const { return m_rootJointId; } // Called from jobs - void loadSkeleton(); void setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose); QVector<QMatrix4x4> calculateSkinningMatrixPalette(); + void clearData(); + void setSkeletonData(const SkeletonData &data); + const SkeletonData &skeletonData() const { return m_skeletonData; } + SkeletonData skeletonData() { return m_skeletonData; } + // Allow unit tests to set the data type -#if !defined(QT_BUILD_INTERNAL) -private: -#endif - enum SkeletonDataType { - Unknown, - File, - Data - }; #if defined(QT_BUILD_INTERNAL) public: void setDataType(SkeletonDataType dataType) { m_dataType = dataType; } #endif private: - void loadSkeletonFromUrl(); - void loadSkeletonFromData(); - Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const; - Qt3DCore::QJoint *createFrontendJoint(const QString &jointName, - const Qt3DCore::Sqt &localPose, - const QMatrix4x4 &inverseBindMatrix) const; - void processJointHierarchy(Qt3DCore::QNodeId jointId, int parentJointIndex, SkeletonData &skeletonData); - void clearData(); - QVector<QMatrix4x4> m_skinningPalette; // QSkeletonLoader Properties diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp index d66fe3080..cf1e45355 100644 --- a/src/render/io/qsceneloader.cpp +++ b/src/render/io/qsceneloader.cpp @@ -219,6 +219,27 @@ void QSceneLoaderPrivate::setStatus(QSceneLoader::Status status) } } +void QSceneLoaderPrivate::setSceneRoot(QEntity *root) +{ + // If we already have a scene sub tree, delete it + if (m_subTreeRoot) { + delete m_subTreeRoot; + m_subTreeRoot = nullptr; + } + + // If we have successfully loaded a scene, graft it in + if (root) { + // Get the entity to which this component is attached + const Qt3DCore::QNodeIdVector entities = m_scene->entitiesForComponent(m_id); + Q_ASSERT(entities.size() == 1); + Qt3DCore::QNodeId parentEntityId = entities.first(); + QEntity *parentEntity = qobject_cast<QEntity *>(m_scene->lookupNode(parentEntityId)); + root->setParent(parentEntity); + m_subTreeRoot = root; + populateEntityMap(m_subTreeRoot); + } +} + /*! The constructor creates an instance with the specified \a parent. */ @@ -238,38 +259,6 @@ QSceneLoader::QSceneLoader(QSceneLoaderPrivate &dd, QNode *parent) { } -// Called in main thread -/*! \internal */ -void QSceneLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QSceneLoader); - QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change); - if (e->type() == PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("scene")) { - // If we already have a scene sub tree, delete it - if (d->m_subTreeRoot) { - delete d->m_subTreeRoot; - d->m_subTreeRoot = nullptr; - } - - // If we have successfully loaded a scene, graft it in - auto *subTreeRoot = e->value().value<Qt3DCore::QEntity *>(); - if (subTreeRoot) { - // Get the entity to which this component is attached - const Qt3DCore::QNodeIdVector entities = d->m_scene->entitiesForComponent(d->m_id); - Q_ASSERT(entities.size() == 1); - Qt3DCore::QNodeId parentEntityId = entities.first(); - QEntity *parentEntity = qobject_cast<QEntity *>(d->m_scene->lookupNode(parentEntityId)); - subTreeRoot->setParent(parentEntity); - d->m_subTreeRoot = subTreeRoot; - d->populateEntityMap(d->m_subTreeRoot); - } - } else if (e->propertyName() == QByteArrayLiteral("status")) { - d->setStatus(e->value().value<QSceneLoader::Status>()); - } - } -} - QUrl QSceneLoader::source() const { Q_D(const QSceneLoader); diff --git a/src/render/io/qsceneloader.h b/src/render/io/qsceneloader.h index 4cb743333..6842a6926 100644 --- a/src/render/io/qsceneloader.h +++ b/src/render/io/qsceneloader.h @@ -60,7 +60,6 @@ public: explicit QSceneLoader(Qt3DCore::QNode *parent = nullptr); ~QSceneLoader(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; enum Status { None = 0, Loading, diff --git a/src/render/io/qsceneloader_p.h b/src/render/io/qsceneloader_p.h index 50745c66f..213bc1104 100644 --- a/src/render/io/qsceneloader_p.h +++ b/src/render/io/qsceneloader_p.h @@ -67,6 +67,7 @@ public: QSceneLoaderPrivate(); void setStatus(QSceneLoader::Status status); + void setSceneRoot(Qt3DCore::QEntity *root); Q_DECLARE_PUBLIC(QSceneLoader) diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp index e7f289f8a..089091701 100644 --- a/src/render/io/scene.cpp +++ b/src/render/io/scene.cpp @@ -66,16 +66,6 @@ void Scene::cleanup() m_source.clear(); } -void Scene::setStatus(QSceneLoader::Status status) -{ - // Send the new subtree to the frontend or notify failure - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("status"); - e->setValue(QVariant::fromValue(status)); - notifyObservers(e); -} - void Scene::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { const QSceneLoader *node = qobject_cast<const QSceneLoader *>(frontEnd); @@ -99,22 +89,6 @@ QUrl Scene::source() const return m_source; } -void Scene::setSceneSubtree(Qt3DCore::QEntity *subTree) -{ - if (subTree) { - // Move scene sub tree to the application thread so that it can be grafted in. - const auto appThread = QCoreApplication::instance()->thread(); - subTree->moveToThread(appThread); - } - - // Send the new subtree to the frontend or notify failure - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("scene"); - e->setValue(QVariant::fromValue(subTree)); - notifyObservers(e); -} - void Scene::setSceneManager(SceneManager *manager) { if (m_sceneManager != manager) diff --git a/src/render/io/scene_p.h b/src/render/io/scene_p.h index 04b9bba1a..bf625b369 100644 --- a/src/render/io/scene_p.h +++ b/src/render/io/scene_p.h @@ -74,7 +74,6 @@ public: void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QUrl source() const; - void setSceneSubtree(Qt3DCore::QEntity *subTree); void setSceneManager(SceneManager *manager); void cleanup(); diff --git a/src/render/jobs/abstractpickingjob.cpp b/src/render/jobs/abstractpickingjob.cpp index 74e6a7f80..35e658535 100644 --- a/src/render/jobs/abstractpickingjob.cpp +++ b/src/render/jobs/abstractpickingjob.cpp @@ -58,13 +58,24 @@ namespace Qt3DRender { namespace Render { AbstractPickingJob::AbstractPickingJob() - : m_manager(nullptr) + : Qt3DCore::QAspectJob() + , m_manager(nullptr) , m_node(nullptr) , m_frameGraphRoot(nullptr) , m_renderSettings(nullptr) { } +AbstractPickingJob::AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd) + : Qt3DCore::QAspectJob(dd) + , m_manager(nullptr) + , m_node(nullptr) + , m_frameGraphRoot(nullptr) + , m_renderSettings(nullptr) +{ + +} + void AbstractPickingJob::setRoot(Entity *root) { m_node = root; diff --git a/src/render/jobs/abstractpickingjob_p.h b/src/render/jobs/abstractpickingjob_p.h index 059c87aa7..c0c6ed7e9 100644 --- a/src/render/jobs/abstractpickingjob_p.h +++ b/src/render/jobs/abstractpickingjob_p.h @@ -90,6 +90,8 @@ public: const QRect &viewport); protected: + AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd); + void run() final; NodeManagers *m_manager; diff --git a/src/render/jobs/genericlambdajob_p.h b/src/render/jobs/genericlambdajob_p.h index d72975761..4d93f0f8d 100644 --- a/src/render/jobs/genericlambdajob_p.h +++ b/src/render/jobs/genericlambdajob_p.h @@ -84,6 +84,49 @@ private: template<typename T> using GenericLambdaJobPtr = QSharedPointer<GenericLambdaJob<T>>; +template<typename T, typename U> +class GenericLambdaJobAndPostFramePrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + explicit GenericLambdaJobAndPostFramePrivate(U postFrameCallable) + : m_postFrameCallable(postFrameCallable) + {} + + ~GenericLambdaJobAndPostFramePrivate() override {} + + void postFrame(Qt3DCore::QAspectManager *manager) override + { + m_postFrameCallable(manager); + } + +private: + U m_postFrameCallable; +}; + +template<typename T, typename U> +class GenericLambdaJobAndPostFrame : public Qt3DCore::QAspectJob +{ +public: + explicit GenericLambdaJobAndPostFrame(T runCallable, U postFrameCallable, JobTypes::JobType type = JobTypes::GenericLambda) + : Qt3DCore::QAspectJob(*new GenericLambdaJobAndPostFramePrivate<T, U>(postFrameCallable)) + , m_runCallable(runCallable) + { + SET_JOB_RUN_STAT_TYPE(this, type, 0); + } + + // QAspectJob interface + void run() final + { + m_runCallable(); + } + +private: + T m_runCallable; +}; + +template<typename T, typename U> +using GenericLambdaJobAndPostFramePtr = QSharedPointer<GenericLambdaJobAndPostFrame<T, U>>; + } // Render } // Qt3DRender diff --git a/src/render/jobs/loadgeometryjob.cpp b/src/render/jobs/loadgeometryjob.cpp index d28b15a7c..88930038a 100644 --- a/src/render/jobs/loadgeometryjob.cpp +++ b/src/render/jobs/loadgeometryjob.cpp @@ -41,6 +41,8 @@ #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/geometryrenderermanager_p.h> #include <Qt3DRender/private/job_common_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DRender/private/qmesh_p.h> QT_BEGIN_NAMESPACE @@ -48,8 +50,19 @@ namespace Qt3DRender { namespace Render { +class LoadGeometryJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + LoadGeometryJobPrivate() {} + ~LoadGeometryJobPrivate() {} + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<std::pair<Qt3DCore::QNodeId, GeometryFunctorResult>> m_updates; +}; + LoadGeometryJob::LoadGeometryJob(const HGeometryRenderer &handle) - : QAspectJob() + : QAspectJob(*new LoadGeometryJobPrivate) , m_handle(handle) , m_nodeManagers(nullptr) { @@ -62,9 +75,27 @@ LoadGeometryJob::~LoadGeometryJob() void LoadGeometryJob::run() { + Q_D(LoadGeometryJob); GeometryRenderer *geometryRenderer = m_nodeManagers->geometryRendererManager()->data(m_handle); if (geometryRenderer != nullptr) - geometryRenderer->executeFunctor(); + d->m_updates.push_back({ geometryRenderer->peerId(), geometryRenderer->executeFunctor() }); +} + +void LoadGeometryJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + const auto updates = std::move(m_updates); + for (const auto &update : updates) { + QGeometryRenderer *gR = static_cast<decltype(gR)>(manager->lookupNode(update.first)); + const GeometryFunctorResult &result = update.second; + gR->setGeometry(result.geometry); + + // Set status if gR is a QMesh instance + QMesh *mesh = qobject_cast<QMesh *>(gR); + if (mesh) { + QMeshPrivate *dMesh = static_cast<decltype(dMesh)>(Qt3DCore::QNodePrivate::get(mesh)); + dMesh->setStatus(result.status); + } + } } } // namespace Render diff --git a/src/render/jobs/loadgeometryjob_p.h b/src/render/jobs/loadgeometryjob_p.h index c02739647..998d543ac 100644 --- a/src/render/jobs/loadgeometryjob_p.h +++ b/src/render/jobs/loadgeometryjob_p.h @@ -62,6 +62,7 @@ namespace Qt3DRender { namespace Render { class NodeManagers; +class LoadGeometryJobPrivate; class Q_AUTOTEST_EXPORT LoadGeometryJob : public Qt3DCore::QAspectJob { @@ -75,6 +76,9 @@ protected: void run() override; HGeometryRenderer m_handle; NodeManagers *m_nodeManagers; + +private: + Q_DECLARE_PRIVATE(LoadGeometryJob) }; typedef QSharedPointer<LoadGeometryJob> LoadGeometryJobPtr; diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp index 9885d3225..f858f82e3 100644 --- a/src/render/jobs/loadscenejob.cpp +++ b/src/render/jobs/loadscenejob.cpp @@ -42,10 +42,12 @@ #include <private/nodemanagers_p.h> #include <private/scenemanager_p.h> #include <Qt3DCore/qentity.h> +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/private/job_common_p.h> #include <Qt3DRender/private/qsceneimporter_p.h> #include <Qt3DRender/private/qurlhelper_p.h> #include <Qt3DRender/qsceneloader.h> +#include <Qt3DRender/private/qsceneloader_p.h> #include <Qt3DRender/private/renderlogging_p.h> #include <QFileInfo> #include <QMimeDatabase> @@ -55,10 +57,10 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { -LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId m_sceneComponent) - : QAspectJob() +LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId sceneComponent) + : QAspectJob(*new LoadSceneJobPrivate(this)) , m_source(source) - , m_sceneComponent(m_sceneComponent) + , m_sceneComponent(sceneComponent) , m_managers(nullptr) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0); @@ -97,7 +99,6 @@ void LoadSceneJob::run() Q_ASSERT(scene); // Reset status - scene->setStatus(QSceneLoader::None); QSceneLoader::Status finalStatus = QSceneLoader::None; // Perform the loading only if the source wasn't explicitly set to empty @@ -110,8 +111,7 @@ void LoadSceneJob::run() qCDebug(SceneLoaders) << Q_FUNC_INFO << "Attempting to load" << finfo.filePath(); if (finfo.exists()) { const QStringList extensions(finfo.suffix()); - sceneSubTree = tryLoadScene(scene, - finalStatus, + sceneSubTree = tryLoadScene(finalStatus, extensions, [this] (QSceneImporter *importer) { importer->setSource(m_source); @@ -131,8 +131,7 @@ void LoadSceneJob::run() const QString basePath = m_source.adjusted(QUrl::RemoveFilename).toString(); - sceneSubTree = tryLoadScene(scene, - finalStatus, + sceneSubTree = tryLoadScene(finalStatus, extensions, [this, basePath] (QSceneImporter *importer) { importer->setData(m_data, basePath); @@ -140,19 +139,18 @@ void LoadSceneJob::run() } } - // If the sceneSubTree is null it will trigger the frontend to unload - // any subtree it may hold - // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree - // to the QCoreApplication thread which is where the frontend object tree lives. - scene->setSceneSubtree(sceneSubTree); + Q_D(LoadSceneJob); + d->m_sceneSubtree = sceneSubTree; + d->m_status = finalStatus; - // Note: the status is set after the subtree so that bindinds depending on the status - // in the frontend will be consistent - scene->setStatus(finalStatus); + if (d->m_sceneSubtree) { + // Move scene sub tree to the application thread so that it can be grafted in. + const auto appThread = QCoreApplication::instance()->thread(); + d->m_sceneSubtree->moveToThread(appThread); + } } -Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene, - QSceneLoader::Status &finalStatus, +Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(QSceneLoader::Status &finalStatus, const QStringList &extensions, const std::function<void (QSceneImporter *)> &importerSetupFunc) { @@ -165,9 +163,6 @@ Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene, foundSuitableLoggerPlugin = true; - // If the file type is supported -> enter Loading status - scene->setStatus(QSceneLoader::Loading); - // Set source file or data on importer importerSetupFunc(sceneImporter); @@ -188,6 +183,27 @@ Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene, return sceneSubTree; } +void LoadSceneJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + Q_Q(LoadSceneJob); + QSceneLoader *node = + qobject_cast<QSceneLoader *>(manager->lookupNode(q->sceneComponentId())); + if (!node) + return; + Qt3DRender::QSceneLoaderPrivate *dNode = + static_cast<decltype(dNode)>(Qt3DCore::QNodePrivate::get(node)); + + // If the sceneSubTree is null it will trigger the frontend to unload + // any subtree it may hold + // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree + // to the QCoreApplication thread which is where the frontend object tree lives. + dNode->setSceneRoot(m_sceneSubtree); + + // Note: the status is set after the subtree so that bindinds depending on the status + // in the frontend will be consistent + dNode->setStatus(m_status); +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/jobs/loadscenejob_p.h b/src/render/jobs/loadscenejob_p.h index 0c77dc6e8..3675d94c1 100644 --- a/src/render/jobs/loadscenejob_p.h +++ b/src/render/jobs/loadscenejob_p.h @@ -52,6 +52,7 @@ // #include <Qt3DCore/qaspectjob.h> +#include <Qt3DCore/private/qaspectjob_p.h> #include <Qt3DCore/qnodeid.h> #include <Qt3DRender/qsceneloader.h> #include <QSharedPointer> @@ -69,6 +70,24 @@ namespace Render { class Scene; class NodeManagers; +class LoadSceneJob; + +class Q_AUTOTEST_EXPORT LoadSceneJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + explicit LoadSceneJobPrivate(LoadSceneJob *q): q_ptr(q) {} + ~LoadSceneJobPrivate() override {} + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + Qt3DCore::QEntity *m_sceneSubtree = nullptr; + QSceneLoader::Status m_status = QSceneLoader::None; + + Q_DECLARE_PUBLIC(LoadSceneJob) +private: + LoadSceneJob *q_ptr; +}; + class Q_AUTOTEST_EXPORT LoadSceneJob : public Qt3DCore::QAspectJob { public: @@ -91,10 +110,10 @@ private: NodeManagers *m_managers; QList<QSceneImporter *> m_sceneImporters; - Qt3DCore::QEntity *tryLoadScene(Scene *scene, - QSceneLoader::Status &finalStatus, + Qt3DCore::QEntity *tryLoadScene(QSceneLoader::Status &finalStatus, const QStringList &extensions, const std::function<void (QSceneImporter *)> &importerSetupFunc); + Q_DECLARE_PRIVATE(LoadSceneJob) }; typedef QSharedPointer<LoadSceneJob> LoadSceneJobPtr; diff --git a/src/render/jobs/loadskeletonjob.cpp b/src/render/jobs/loadskeletonjob.cpp index 413afc5b5..8d0d47fb9 100644 --- a/src/render/jobs/loadskeletonjob.cpp +++ b/src/render/jobs/loadskeletonjob.cpp @@ -35,32 +35,263 @@ ****************************************************************************/ #include "loadskeletonjob_p.h" -#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/qabstractskeleton.h> +#include <Qt3DCore/qskeletonloader.h> +#include <Qt3DCore/private/qabstractskeleton_p.h> +#include <Qt3DCore/private/qabstractnodefactory_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DCore/private/qskeletonloader_p.h> #include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/qurlhelper_p.h> +#include <Qt3DRender/private/gltfskeletonloader_p.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { +class LoadSkeletonJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + LoadSkeletonJobPrivate() : m_backendSkeleton(nullptr), m_loadedRootJoint(nullptr) { } + ~LoadSkeletonJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + Skeleton *m_backendSkeleton; + Qt3DCore::QJoint* m_loadedRootJoint; +}; + LoadSkeletonJob::LoadSkeletonJob(const HSkeleton &handle) - : QAspectJob() + : QAspectJob(*new LoadSkeletonJobPrivate) , m_handle(handle) , m_nodeManagers(nullptr) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadSkeleton, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadSkeleton, 0) } -LoadSkeletonJob::~LoadSkeletonJob() +void LoadSkeletonJob::run() { + Q_D(LoadSkeletonJob); + d->m_backendSkeleton = nullptr; + + Skeleton *skeleton = m_nodeManagers->skeletonManager()->data(m_handle); + if (skeleton != nullptr) { + d->m_backendSkeleton = skeleton; + loadSkeleton(skeleton); + } } -void LoadSkeletonJob::run() +void LoadSkeletonJob::loadSkeleton(Skeleton *skeleton) { - Skeleton *skeleton = m_nodeManagers->skeletonManager()->data(m_handle); - if (skeleton != nullptr) - skeleton->loadSkeleton(); + qCDebug(Jobs) << Q_FUNC_INFO << skeleton->source(); + skeleton->clearData(); + + // Load the data + switch (skeleton->dataType()) { + case Skeleton::File: + loadSkeletonFromUrl(skeleton); + break; + + case Skeleton::Data: + loadSkeletonFromData(skeleton); + break; + + default: + Q_UNREACHABLE(); + } + + // If using a loader inform the frontend of the status change. + // Don't bother if asked to create frontend joints though. When + // the backend gets notified of those joints we'll update the + // status at that point. + if (skeleton->dataType() == Skeleton::File && !skeleton->createJoints()) { + if (skeleton->jointCount() == 0) + skeleton->setStatus(Qt3DCore::QSkeletonLoader::Error); + else + skeleton->setStatus(Qt3DCore::QSkeletonLoader::Ready); + } + + qCDebug(Jobs) << "Loaded skeleton data:" << *skeleton; +} + +void LoadSkeletonJob::loadSkeletonFromUrl(Skeleton *skeleton) +{ + Q_D(LoadSkeletonJob); + + using namespace Qt3DCore; + + // TODO: Handle remote files + QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(skeleton->source()); + QFileInfo info(filePath); + if (!info.exists()) { + qWarning() << "Could not open skeleton file:" << filePath; + skeleton->setStatus(Qt3DCore::QSkeletonLoader::Error); + return; + } + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open skeleton file:" << filePath; + skeleton->setStatus(QSkeletonLoader::Error); + return; + } + + // TODO: Make plugin based for more file type support. For now gltf or native + const QString ext = info.suffix(); + SkeletonData skeletonData; + if (ext == QLatin1String("gltf")) { + GLTFSkeletonLoader loader; + loader.load(&file); + skeletonData = loader.createSkeleton(skeleton->name()); + + // If the user has requested it, create the frontend nodes for the joints + // and send them to the (soon to be owning) QSkeletonLoader. + if (skeleton->createJoints()) { + QJoint *rootJoint = createFrontendJoints(skeletonData); + if (!rootJoint) { + qWarning() << "Failed to create frontend joints"; + skeleton->setStatus(QSkeletonLoader::Error); + return; + } + + // Move the QJoint tree to the main thread and notify the + // corresponding QSkeletonLoader + const auto appThread = QCoreApplication::instance()->thread(); + rootJoint->moveToThread(appThread); + + d->m_loadedRootJoint = rootJoint; + + // Clear the skeleton data. It will be recreated from the + // frontend joints. A little bit inefficient but ensures + // that joints created this way and via QSkeleton go through + // the same code path. + skeletonData = SkeletonData(); + } + } else if (ext == QLatin1String("json")) { + // TODO: Support native skeleton type + } else { + qWarning() << "Unknown skeleton file type:" << ext; + skeleton->setStatus(QSkeletonLoader::Error); + return; + } + + skeleton->setSkeletonData(skeletonData); +} + +void LoadSkeletonJob::loadSkeletonFromData(Skeleton *skeleton) +{ + // Recurse down through the joint hierarchy and process it into + // the vector of joints used within SkeletonData. The recursion + // ensures that a parent always appears before its children in + // the vector of JointInfo objects. + // + // In addition, we set up a mapping from the joint ids to the + // index of the corresponding JointInfo object in the vector. + // This will allow us to easily update entries in the vector of + // JointInfos when a Joint node marks itself as dirty. + const int rootParentIndex = -1; + auto skeletonData = skeleton->skeletonData(); + processJointHierarchy(skeleton->rootJointId(), rootParentIndex, skeletonData); + skeleton->setSkeletonData(skeletonData); +} + +Qt3DCore::QJoint *LoadSkeletonJob::createFrontendJoints(const SkeletonData &skeletonData) const +{ + if (skeletonData.joints.isEmpty()) + return nullptr; + + // Create frontend joints from the joint info objects + QVector<Qt3DCore::QJoint *> frontendJoints; + const int jointCount = skeletonData.joints.size(); + frontendJoints.reserve(jointCount); + for (int i = 0; i < jointCount; ++i) { + const QMatrix4x4 &inverseBindMatrix = skeletonData.joints[i].inverseBindPose; + const QString &jointName = skeletonData.jointNames[i]; + const Qt3DCore::Sqt &localPose = skeletonData.localPoses[i]; + frontendJoints.push_back(createFrontendJoint(jointName, localPose, inverseBindMatrix)); + } + + // Now go through and resolve the parent for each joint + for (int i = 0; i < frontendJoints.size(); ++i) { + const auto parentIndex = skeletonData.joints[i].parentIndex; + if (parentIndex == -1) + continue; + + // It's not enough to just set up the QObject parent-child relationship. + // We need to explicitly add the child to the parent's list of joints so + // that information is then propagated to the backend. + frontendJoints[parentIndex]->addChildJoint(frontendJoints[i]); + } + + return frontendJoints[0]; +} + +Qt3DCore::QJoint *LoadSkeletonJob::createFrontendJoint(const QString &jointName, + const Qt3DCore::Sqt &localPose, + const QMatrix4x4 &inverseBindMatrix) const +{ + auto joint = Qt3DCore::QAbstractNodeFactory::createNode<Qt3DCore::QJoint>("QJoint"); + joint->setTranslation(localPose.translation); + joint->setRotation(localPose.rotation); + joint->setScale(localPose.scale); + joint->setInverseBindMatrix(inverseBindMatrix); + joint->setName(jointName); + return joint; +} + +void LoadSkeletonJob::processJointHierarchy(Qt3DCore::QNodeId jointId, + int parentJointIndex, + SkeletonData &skeletonData) +{ + // Lookup the joint, create a JointInfo, and add an entry to the index map + Joint *joint = m_nodeManagers->jointManager()->lookupResource(jointId); + Q_ASSERT(joint); + joint->setOwningSkeleton(m_handle); + const JointInfo jointInfo(joint, parentJointIndex); + skeletonData.joints.push_back(jointInfo); + skeletonData.localPoses.push_back(joint->localPose()); + skeletonData.jointNames.push_back(joint->name()); + + const int jointIndex = skeletonData.joints.size() - 1; + const HJoint jointHandle = m_nodeManagers->jointManager()->lookupHandle(jointId); + skeletonData.jointIndices.insert(jointHandle, jointIndex); + + // Recurse to the children + const auto childIds = joint->childJointIds(); + for (const auto &childJointId : childIds) + processJointHierarchy(childJointId, jointIndex, skeletonData); +} + +void LoadSkeletonJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + if (!m_backendSkeleton) + return; + + using namespace Qt3DCore; + QAbstractSkeleton *node = qobject_cast<QAbstractSkeleton *>(manager->lookupNode(m_backendSkeleton->peerId())); + if (!node) + return; + + QAbstractSkeletonPrivate *dnode = QAbstractSkeletonPrivate::get(node); + dnode->m_jointCount = m_backendSkeleton->jointCount(); + dnode->m_jointNames = m_backendSkeleton->jointNames(); + dnode->m_localPoses = m_backendSkeleton->localPoses(); + dnode->update(); + + QSkeletonLoader *loaderNode = qobject_cast<QSkeletonLoader *>(node); + if (loaderNode) { + QSkeletonLoaderPrivate *dloaderNode = static_cast<QSkeletonLoaderPrivate *>(QSkeletonLoaderPrivate::get(loaderNode)); + dloaderNode->setStatus(m_backendSkeleton->status()); + + if (m_loadedRootJoint) { + dloaderNode->m_rootJoint = m_loadedRootJoint; + m_loadedRootJoint = nullptr; + } + } } } // namespace Render diff --git a/src/render/jobs/loadskeletonjob_p.h b/src/render/jobs/loadskeletonjob_p.h index 2cd9fa8bf..0cc09da3d 100644 --- a/src/render/jobs/loadskeletonjob_p.h +++ b/src/render/jobs/loadskeletonjob_p.h @@ -51,28 +51,46 @@ #include <Qt3DCore/qaspectjob.h> #include <QtCore/qsharedpointer.h> - +#include <Qt3DRender/private/skeletondata_p.h> #include <Qt3DRender/private/handle_types_p.h> QT_BEGIN_NAMESPACE +namespace Qt3DCore { +class QJoint; +} + namespace Qt3DRender { namespace Render { class NodeManagers; +class LoadSkeletonJobPrivate; class LoadSkeletonJob : public Qt3DCore::QAspectJob { public: explicit LoadSkeletonJob(const HSkeleton &handle); - ~LoadSkeletonJob(); void setNodeManagers(NodeManagers *nodeManagers) { m_nodeManagers = nodeManagers; } protected: void run() override; + void loadSkeleton(Skeleton *skeleton); + void loadSkeletonFromUrl(Skeleton *skeleton); + void loadSkeletonFromData(Skeleton *skeleton); + Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const; + Qt3DCore::QJoint *createFrontendJoint(const QString &jointName, + const Qt3DCore::Sqt &localPose, + const QMatrix4x4 &inverseBindMatrix) const; + void processJointHierarchy(Qt3DCore::QNodeId jointId, + int parentJointIndex, + SkeletonData &skeletonData); + HSkeleton m_handle; NodeManagers *m_nodeManagers; + +private: + Q_DECLARE_PRIVATE(LoadSkeletonJob) }; typedef QSharedPointer<LoadSkeletonJob> LoadSkeletonJobPtr; diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp index f3571c210..380447873 100644 --- a/src/render/jobs/raycastingjob.cpp +++ b/src/render/jobs/raycastingjob.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "raycastingjob_p.h" +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/geometryrenderer_p.h> @@ -51,6 +52,7 @@ #include <Qt3DRender/private/rendersettings_p.h> #include <Qt3DRender/private/trianglesvisitor_p.h> #include <Qt3DRender/private/entityvisitor_p.h> +#include <Qt3DRender/private/qabstractraycaster_p.h> QT_BEGIN_NAMESPACE @@ -82,11 +84,43 @@ public: } // anonymous +class Qt3DRender::Render::RayCastingJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + RayCastingJobPrivate() { } + ~RayCastingJobPrivate() override { Q_ASSERT(dispatches.isEmpty()); } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<QPair<RayCaster *, QAbstractRayCaster::Hits>> dispatches; +}; + + +void RayCastingJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (auto res: qAsConst(dispatches)) { + QAbstractRayCaster *node = qobject_cast<QAbstractRayCaster *>(manager->lookupNode(res.first->peerId())); + if (!node) + continue; + + QAbstractRayCasterPrivate *d = QAbstractRayCasterPrivate::get(node); + d->dispatchHits(res.second); + + if (node->runMode() == QAbstractRayCaster::SingleShot) { + node->setEnabled(false); + res.first->setEnabled(false); + } + } + + dispatches.clear(); +} + + RayCastingJob::RayCastingJob() - : AbstractPickingJob() + : AbstractPickingJob(*new RayCastingJobPrivate()) , m_castersDirty(true) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0) } void RayCastingJob::markCastersDirty() @@ -239,7 +273,8 @@ void RayCastingJob::dispatchHits(RayCaster *rayCaster, const PickingUtils::HitLi }; } - rayCaster->dispatchHits(hits); + Q_D(RayCastingJob); + d->dispatches.push_back({rayCaster, hits}); } QT_END_NAMESPACE diff --git a/src/render/jobs/raycastingjob_p.h b/src/render/jobs/raycastingjob_p.h index 0bd8d445a..4b8b91ad5 100644 --- a/src/render/jobs/raycastingjob_p.h +++ b/src/render/jobs/raycastingjob_p.h @@ -68,6 +68,8 @@ namespace PickingUtils { typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList; } +class RayCastingJobPrivate; + class Q_AUTOTEST_EXPORT RayCastingJob : public AbstractPickingJob { public: @@ -80,6 +82,8 @@ protected: void dispatchHits(RayCaster *rayCaster, const PickingUtils::HitList &sphereHits); private: + Q_DECLARE_PRIVATE(RayCastingJob) + bool m_castersDirty; bool m_oneEnabledAtLeast; }; diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp index b5349a2c1..0a28b7628 100644 --- a/src/render/jobs/updatelevelofdetailjob.cpp +++ b/src/render/jobs/updatelevelofdetailjob.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "updatelevelofdetailjob_p.h" +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/QLevelOfDetail> #include <Qt3DRender/private/entityvisitor_p.h> #include <Qt3DRender/private/job_common_p.h> @@ -66,9 +67,11 @@ public: , m_filterValue(filterValue) , m_frameGraphRoot(frameGraphRoot) { + m_updatedIndices.reserve(manager->levelOfDetailManager()->count()); } double filterValue() const { return m_filterValue; } + const QVector<QPair<Qt3DCore::QNodeId, int>> &updatedIndices() const { return m_updatedIndices; } Operation visit(Qt3DRender::Render::Entity *entity = nullptr) override { using namespace Qt3DRender; @@ -102,6 +105,7 @@ public: private: double m_filterValue = 0.; Qt3DRender::Render::FrameGraphNode *m_frameGraphRoot; + QVector<QPair<Qt3DCore::QNodeId, int>> m_updatedIndices; void updateEntityLodByDistance(Qt3DRender::Render::Entity *entity, Qt3DRender::Render::LevelOfDetail *lod) { @@ -128,8 +132,10 @@ private: if (dist <= thresholds[i] || i == n -1) { m_filterValue = approxRollingAverage<30>(m_filterValue, i); i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1); - if (lod->currentIndex() != i) + if (lod->currentIndex() != i) { lod->setCurrentIndex(i); + m_updatedIndices.push_back({lod->peerId(), i}); + } break; } } @@ -172,8 +178,10 @@ private: if (thresholds[i] < area || i == n -1) { m_filterValue = approxRollingAverage<30>(m_filterValue, i); i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1); - if (lod->currentIndex() != i) + if (lod->currentIndex() != i) { lod->setCurrentIndex(i); + m_updatedIndices.push_back({lod->peerId(), i}); + } break; } } @@ -199,13 +207,24 @@ private: namespace Qt3DRender { namespace Render { +class UpdateLevelOfDetailJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + UpdateLevelOfDetailJobPrivate() { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<QPair<Qt3DCore::QNodeId, int>> m_updatedIndices; +}; + UpdateLevelOfDetailJob::UpdateLevelOfDetailJob() - : m_manager(nullptr) + : Qt3DCore::QAspectJob(*new UpdateLevelOfDetailJobPrivate) + , m_manager(nullptr) , m_frameGraphRoot(nullptr) , m_root(nullptr) , m_filterValue(0.) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLevelOfDetail, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLevelOfDetail, 0) } UpdateLevelOfDetailJob::~UpdateLevelOfDetailJob() @@ -229,23 +248,32 @@ void UpdateLevelOfDetailJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot) void UpdateLevelOfDetailJob::run() { + Q_D(UpdateLevelOfDetailJob); + Q_ASSERT(m_frameGraphRoot && m_root && m_manager); // short-circuit if no LoDs exist if (m_manager->levelOfDetailManager()->count() == 0) return; - - if (m_manager->levelOfDetailManager()->count() == 0) - return; // no LODs, lets bail out early - LODUpdateVisitor visitor(m_filterValue, m_frameGraphRoot, m_manager); visitor.apply(m_root); m_filterValue = visitor.filterValue(); + d->m_updatedIndices = visitor.updatedIndices(); } -} // Render +void UpdateLevelOfDetailJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (const auto &updatedNode: qAsConst(m_updatedIndices)) { + QLevelOfDetail *node = qobject_cast<QLevelOfDetail *>(manager->lookupNode(updatedNode.first)); + if (!node) + continue; + node->setCurrentIndex(updatedNode.second); + } +} + +} // Render } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/jobs/updatelevelofdetailjob_p.h b/src/render/jobs/updatelevelofdetailjob_p.h index 3c7d00d2c..9ac5cf0e9 100644 --- a/src/render/jobs/updatelevelofdetailjob_p.h +++ b/src/render/jobs/updatelevelofdetailjob_p.h @@ -65,6 +65,7 @@ class Entity; class NodeManagers; class LevelOfDetail; class FrameGraphNode; +class UpdateLevelOfDetailJobPrivate; class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateLevelOfDetailJob : public Qt3DCore::QAspectJob { @@ -81,6 +82,8 @@ public: Entity *root() const { return m_root; } private: + Q_DECLARE_PRIVATE(UpdateLevelOfDetailJob) + NodeManagers *m_manager; FrameGraphNode *m_frameGraphRoot; Entity *m_root; diff --git a/src/render/jobs/updateworldtransformjob.cpp b/src/render/jobs/updateworldtransformjob.cpp index 6b8bccec2..13e14442f 100644 --- a/src/render/jobs/updateworldtransformjob.cpp +++ b/src/render/jobs/updateworldtransformjob.cpp @@ -39,6 +39,9 @@ #include "updateworldtransformjob_p.h" +#include <Qt3DCore/qtransform.h> +#include <Qt3DCore/private/qtransform_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/transform_p.h> @@ -56,10 +59,17 @@ namespace Render { namespace { -void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform) +struct TransformUpdate +{ + Qt3DCore::QNodeId peerId; + QMatrix4x4 worldTransformMatrix; +}; + +QVector<TransformUpdate> updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform) { Matrix4x4 worldTransform(parentTransform); Transform *nodeTransform = node->renderComponent<Transform>(); + QVector<TransformUpdate> updatedTransforms; const bool hasTransformComponent = nodeTransform != nullptr && nodeTransform->isEnabled(); if (hasTransformComponent) @@ -68,21 +78,33 @@ void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Ma if (*(node->worldTransform()) != worldTransform) { *(node->worldTransform()) = worldTransform; if (hasTransformComponent) - nodeTransform->notifyWorldTransformChanged(worldTransform); + updatedTransforms.push_back({nodeTransform->peerId(), convertToQMatrix4x4(worldTransform)}); } const auto childrenHandles = node->childrenHandles(); for (const HEntity &handle : childrenHandles) { Entity *child = manager->renderNodesManager()->data(handle); if (child) - updateWorldTransformAndBounds(manager, child, worldTransform); + updatedTransforms += updateWorldTransformAndBounds(manager, child, worldTransform); } + return updatedTransforms; } } +class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + UpdateWorldTransformJobPrivate() {} + ~UpdateWorldTransformJobPrivate() override {} + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<TransformUpdate> m_updatedTransforms; +}; + UpdateWorldTransformJob::UpdateWorldTransformJob() - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new UpdateWorldTransformJobPrivate()) , m_node(nullptr) , m_manager(nullptr) { @@ -108,17 +130,32 @@ void UpdateWorldTransformJob::run() // TODO: Parallelise this on each level using a parallel_for // implementation. + Q_D(UpdateWorldTransformJob); qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread(); Matrix4x4 parentTransform; Entity *parent = m_node->parent(); if (parent != nullptr) parentTransform = *(parent->worldTransform()); - updateWorldTransformAndBounds(m_manager, m_node, parentTransform); + d->m_updatedTransforms = updateWorldTransformAndBounds(m_manager, m_node, parentTransform); qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread(); } +void UpdateWorldTransformJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + const QVector<TransformUpdate> updatedTransforms = std::move(m_updatedTransforms); + for (const TransformUpdate &t : updatedTransforms) { + Qt3DCore::QTransform *node = + qobject_cast<Qt3DCore::QTransform *>(manager->lookupNode(t.peerId)); + if (!node) + continue; + Qt3DCore::QTransformPrivate *dNode = + static_cast<Qt3DCore::QTransformPrivate *>(Qt3DCore::QNodePrivate::get(node)); + dNode->setWorldMatrix(t.worldTransformMatrix); + } +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/jobs/updateworldtransformjob_p.h b/src/render/jobs/updateworldtransformjob_p.h index 2689fe45a..e7ff592de 100644 --- a/src/render/jobs/updateworldtransformjob_p.h +++ b/src/render/jobs/updateworldtransformjob_p.h @@ -63,6 +63,7 @@ namespace Render { class Entity; class NodeManagers; +class UpdateWorldTransformJobPrivate; class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJob : public Qt3DCore::QAspectJob { @@ -77,6 +78,7 @@ public: private: Entity *m_node; NodeManagers *m_manager; + Q_DECLARE_PRIVATE(UpdateWorldTransformJob) }; typedef QSharedPointer<UpdateWorldTransformJob> UpdateWorldTransformJobPtr; diff --git a/src/render/lights/light.cpp b/src/render/lights/light.cpp index 30d71082b..3bdab0457 100644 --- a/src/render/lights/light.cpp +++ b/src/render/lights/light.cpp @@ -40,7 +40,6 @@ #include "light_p.h" #include "qabstractlight.h" #include "qabstractlight_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <private/abstractrenderer_p.h> #include <private/nodemanagers_p.h> #include <private/qbackendnode_p.h> diff --git a/src/render/lights/qdirectionallight.cpp b/src/render/lights/qdirectionallight.cpp index 9b6e580de..13fb78843 100644 --- a/src/render/lights/qdirectionallight.cpp +++ b/src/render/lights/qdirectionallight.cpp @@ -39,7 +39,6 @@ #include "qdirectionallight.h" #include "qdirectionallight_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/lights/qspotlight.cpp b/src/render/lights/qspotlight.cpp index c4deaf817..eddafbe61 100644 --- a/src/render/lights/qspotlight.cpp +++ b/src/render/lights/qspotlight.cpp @@ -40,7 +40,6 @@ #include "qspotlight.h" #include "qspotlight_p.h" #include "shaderdata_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/effect.cpp b/src/render/materialsystem/effect.cpp index 76036bd1f..035cf4746 100644 --- a/src/render/materialsystem/effect.cpp +++ b/src/render/materialsystem/effect.cpp @@ -43,10 +43,6 @@ #include <Qt3DRender/qparameter.h> #include <Qt3DRender/private/qeffect_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - #include <QVariant> #include <algorithm> diff --git a/src/render/materialsystem/filterkey.cpp b/src/render/materialsystem/filterkey.cpp index d51a06eec..e6c37b241 100644 --- a/src/render/materialsystem/filterkey.cpp +++ b/src/render/materialsystem/filterkey.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "filterkey_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qfilterkey_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/material.cpp b/src/render/materialsystem/material.cpp index 07764c207..6fda17ccd 100644 --- a/src/render/materialsystem/material.cpp +++ b/src/render/materialsystem/material.cpp @@ -46,10 +46,6 @@ #include "qeffect.h" #include <Qt3DRender/private/qmaterial_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - using namespace Qt3DCore; QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/parameter.cpp b/src/render/materialsystem/parameter.cpp index d32e60a2d..3360aebef 100644 --- a/src/render/materialsystem/parameter.cpp +++ b/src/render/materialsystem/parameter.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "parameter_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/private/qparameter_p.h> #include <Qt3DRender/qtexture.h> @@ -68,6 +67,7 @@ void Parameter::cleanup() m_nameId = -1; m_name.clear(); m_uniformValue = UniformValue(); + m_backendValue = {}; } void Parameter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) diff --git a/src/render/materialsystem/parameter_p.h b/src/render/materialsystem/parameter_p.h index 9deaa11f3..258834ff3 100644 --- a/src/render/materialsystem/parameter_p.h +++ b/src/render/materialsystem/parameter_p.h @@ -76,6 +76,7 @@ public: QString name() const; int nameId() const Q_DECL_NOTHROW { return m_nameId; } const UniformValue &uniformValue() const { return m_uniformValue; } + QVariant backendValue() const { return m_backendValue; } private: QString m_name; diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp index 35ac662fb..35f4d64a9 100644 --- a/src/render/materialsystem/qeffect.cpp +++ b/src/render/materialsystem/qeffect.cpp @@ -42,10 +42,6 @@ #include "qtechnique.h" #include "qparameter.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -172,7 +168,7 @@ QEffect::QEffect(QEffectPrivate &dd, QNode *parent) */ /*! - * Adds \a parameter to the effect. It sends a QPropertyNodeAddedChange to the backend. + * Adds \a parameter to the effect. It sends an update to the backend. * The \a parameter will be used to set a corresponding uniform value in the shader used * by this effect. */ @@ -219,7 +215,7 @@ QVector<QParameter *> QEffect::parameters() const } /*! - * Adds a new technique \a t to the effect. It sends a QPropertyNodeAddedChange to the backend. + * Adds a new technique \a t to the effect. It sends an update to the backend. */ void QEffect::addTechnique(QTechnique *t) { diff --git a/src/render/materialsystem/qfilterkey.cpp b/src/render/materialsystem/qfilterkey.cpp index 547c56d26..dc968400b 100644 --- a/src/render/materialsystem/qfilterkey.cpp +++ b/src/render/materialsystem/qfilterkey.cpp @@ -40,7 +40,6 @@ #include "qfilterkey.h" #include "qfilterkey_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp index db523a700..db286de6b 100644 --- a/src/render/materialsystem/qmaterial.cpp +++ b/src/render/materialsystem/qmaterial.cpp @@ -43,9 +43,6 @@ #include "qeffect.h" #include <Qt3DRender/private/renderlogging_p.h> #include "qparameter.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> /*! \qmltype Material diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp index afaf42158..77eda8c8e 100644 --- a/src/render/materialsystem/qparameter.cpp +++ b/src/render/materialsystem/qparameter.cpp @@ -40,7 +40,6 @@ #include "qparameter.h" #include "qparameter_p.h" #include <Qt3DRender/private/renderlogging_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtexture.h> diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp index d0821c49c..e9dd50325 100644 --- a/src/render/materialsystem/qrenderpass.cpp +++ b/src/render/materialsystem/qrenderpass.cpp @@ -43,9 +43,6 @@ #include "qparameter.h" #include "qfilterkey.h" #include "qrenderstate.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/private/qnode_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp index dadeb98bd..2b96aa285 100644 --- a/src/render/materialsystem/qtechnique.cpp +++ b/src/render/materialsystem/qtechnique.cpp @@ -41,9 +41,6 @@ #include "qtechnique_p.h" #include "qparameter.h" #include "qgraphicsapifilter.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE @@ -376,7 +373,6 @@ QVector<QParameter *> QTechnique::parameters() const return d->m_parameters; } -// TODO Qt 6 -> Remove QGraphicsApiFilter *QTechnique::graphicsApiFilter() { Q_D(QTechnique); diff --git a/src/render/materialsystem/qtechnique.h b/src/render/materialsystem/qtechnique.h index f0c857c2b..b9887b6a2 100644 --- a/src/render/materialsystem/qtechnique.h +++ b/src/render/materialsystem/qtechnique.h @@ -76,7 +76,7 @@ public: void removeRenderPass(QRenderPass *pass); QVector<QRenderPass *> renderPasses() const; - Q_DECL_DEPRECATED QGraphicsApiFilter *graphicsApiFilter(); + QGraphicsApiFilter *graphicsApiFilter(); const QGraphicsApiFilter *graphicsApiFilter() const; protected: diff --git a/src/render/materialsystem/renderpass.cpp b/src/render/materialsystem/renderpass.cpp index aaeca3bb4..19e2a427e 100644 --- a/src/render/materialsystem/renderpass.cpp +++ b/src/render/materialsystem/renderpass.cpp @@ -48,10 +48,6 @@ #include <Qt3DRender/private/renderstates_p.h> #include <Qt3DRender/private/renderstateset_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - #include <algorithm> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp index b80a66a50..6116ca56b 100644 --- a/src/render/materialsystem/shaderbuilder.cpp +++ b/src/render/materialsystem/shaderbuilder.cpp @@ -39,6 +39,8 @@ #include "shaderbuilder_p.h" +#include <Qt3DCore/qpropertyupdatedchange.h> + #include <Qt3DRender/private/qshaderprogrambuilder_p.h> #include <Qt3DRender/qshaderprogram.h> #include <Qt3DRender/private/qshaderprogram_p.h> diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h index 12234bb6c..6b92d3114 100644 --- a/src/render/materialsystem/shaderbuilder_p.h +++ b/src/render/materialsystem/shaderbuilder_p.h @@ -53,7 +53,6 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/private/qgraphicsapifilter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp index 130333898..34d4641e9 100644 --- a/src/render/materialsystem/shaderdata.cpp +++ b/src/render/materialsystem/shaderdata.cpp @@ -64,8 +64,6 @@ const int qNodeIdTypeId = qMetaTypeId<Qt3DCore::QNodeId>(); } -QVector<Qt3DCore::QNodeId> ShaderData::m_updatedShaderData; - ShaderData::ShaderData() : m_managers(nullptr) { @@ -80,51 +78,82 @@ void ShaderData::setManagers(NodeManagers *managers) m_managers = managers; } -void ShaderData::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +void ShaderData::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderDataData>>(change); - const QShaderDataData &data = typedChange->data; - - m_propertyReader = data.propertyReader; - - for (const QPair<QByteArray, QVariant> &entry : data.properties) { - if (entry.first == QByteArrayLiteral("data") || - entry.first == QByteArrayLiteral("childNodes")) // We don't handle default Node properties - continue; - const QVariant &propertyValue = entry.second; - const QString propertyName = QString::fromLatin1(entry.first); - - m_originalProperties.insert(propertyName, propertyValue); - - // We check if the property is a QNodeId or QVector<QNodeId> so that we can - // check nested QShaderData for update - if (propertyValue.userType() == qNodeIdTypeId) { - m_nestedShaderDataProperties.insert(propertyName, propertyValue); - } else if (propertyValue.userType() == QMetaType::QVariantList) { - QVariantList list = propertyValue.value<QVariantList>(); - if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId) - m_nestedShaderDataProperties.insert(propertyName, propertyValue); - } - } + const QShaderData *node = qobject_cast<const QShaderData *>(frontEnd); + if (!node) + return; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (firstTime) { + m_propertyReader = node->propertyReader(); + + const QMetaObject *metaObj = node->metaObject(); + const int propertyOffset = QShaderData::staticMetaObject.propertyOffset(); + const int propertyCount = metaObj->propertyCount(); + // Dynamic properties names + const auto dynamicPropertyNames = node->dynamicPropertyNames(); - // We look for transformed properties once the complete hash of - // originalProperties is available - QHash<QString, QVariant>::iterator it = m_originalProperties.begin(); - const QHash<QString, QVariant>::iterator end = m_originalProperties.end(); - - while (it != end) { - if (it.value().type() == QVariant::Vector3D) { - // if there is a matching QShaderData::TransformType propertyTransformed - QVariant value = m_originalProperties.value(it.key() + QLatin1String("Transformed")); - // if that's the case, we apply a space transformation to the property - if (value.isValid() && value.type() == QVariant::Int) - m_transformedProperties.insert(it.key(), static_cast<TransformType>(value.toInt())); + QVector<QString> propertyNames; + propertyNames.reserve(propertyCount - propertyOffset + dynamicPropertyNames.size()); + + // Statiically defined properties + for (int i = propertyOffset; i < propertyCount; ++i) { + const QMetaProperty pro = metaObj->property(i); + if (pro.isWritable()) + propertyNames.push_back(QString::fromLatin1(pro.name())); + } + // Dynamic properties + for (const QByteArray &propertyName : dynamicPropertyNames) + propertyNames.push_back(QString::fromLatin1(propertyName)); + + for (const QString &propertyName : propertyNames) { + if (propertyName == QStringLiteral("data") || + propertyName == QStringLiteral("childNodes")) // We don't handle default Node properties + continue; + + const QVariant &propertyValue = m_propertyReader->readProperty(node->property(propertyName.toLatin1())); + bool isNested = false; + bool isTransformed = false; + + // We check if the property is a QNodeId + isNested = (propertyValue.userType() == qNodeIdTypeId); + // We check if QVector<QNodeId> + if (propertyValue.userType() == QMetaType::QVariantList) { + QVariantList list = propertyValue.value<QVariantList>(); + if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId) + isNested = true; + } + + // We check if property is a Transformed property + if (propertyValue.userType() == QVariant::Vector3D) { + // if there is a matching QShaderData::TransformType propertyTransformed + isTransformed = propertyNames.contains(propertyName + QLatin1String("Transformed")); + } + m_originalProperties.insert(propertyName, { propertyValue, isNested, isTransformed }); + } + BackendNode::markDirty(AbstractRenderer::ParameterDirty); + } else { + // Updates + if (!m_propertyReader.isNull()) { + auto it = m_originalProperties.begin(); + const auto end = m_originalProperties.end(); + + while (it != end) { + const QVariant newValue = m_propertyReader->readProperty(node->property(it.key().toLatin1())); + PropertyValue &propValue = it.value(); + if (propValue.value != newValue) { + // Note we aren't notified about nested QShaderData in this call + // only scalar / vec properties + propValue.value = newValue; + BackendNode::markDirty(AbstractRenderer::ParameterDirty); + } + ++it; + } } - ++it; } } - ShaderData *ShaderData::lookupResource(NodeManagers *managers, QNodeId id) { return managers->shaderDataManager()->lookupResource(id); @@ -135,120 +164,62 @@ ShaderData *ShaderData::lookupResource(QNodeId id) return ShaderData::lookupResource(m_managers, id); } -// Call by cleanup job (single thread) -void ShaderData::clearUpdatedProperties() -{ - // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7 - // const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end(); - // QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin(); - - // while (it != end) { - // if (it.value().userType() == QMetaType::QVariantList) { - // const auto values = it.value().value<QVariantList>(); - // for (const QVariant &v : values) { - // ShaderData *nested = lookupResource(v.value<QNodeId>()); - // if (nested != nullptr) - // nested->clearUpdatedProperties(); - // } - // } else { - // ShaderData *nested = lookupResource(it.value().value<QNodeId>()); - // if (nested != nullptr) - // nested->clearUpdatedProperties(); - // } - // ++it; - // } -} - void ShaderData::cleanup(NodeManagers *managers) { Q_UNUSED(managers) - // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7 - // for (Qt3DCore::QNodeId id : qAsConst(m_updatedShaderData)) { - // ShaderData *shaderData = ShaderData::lookupResource(managers, id); - // if (shaderData) - // shaderData->clearUpdatedProperties(); - // } - m_updatedShaderData.clear(); } +// RenderCommand updater jobs QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) { // Note protecting m_worldMatrix at this point as we assume all world updates // have been performed when reaching this point - auto it = m_transformedProperties.find(name); - if (it != m_transformedProperties.end()) { - const TransformType transformType = it.value(); - switch (transformType) { - case ModelToEye: - return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(m_originalProperties.value(name).value<QVector3D>())); - case ModelToWorld: - return QVariant::fromValue(m_worldMatrix * Vector3D(m_originalProperties.value(it.key()).value<QVector3D>())); - case ModelToWorldDirection: - return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(m_originalProperties.value(it.key()).value<QVector3D>(), 0.0f))); - case NoTransform: - break; + const auto it = m_originalProperties.constFind(name); + if (it != m_originalProperties.constEnd()) { + const PropertyValue &propertyValue = it.value(); + if (propertyValue.isTransformed) { + const auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed")); + if (transformedIt != m_originalProperties.constEnd()) { + const PropertyValue &transformedValue = transformedIt.value(); + const TransformType transformType = static_cast<TransformType>(transformedValue.value.toInt()); + switch (transformType) { + case ModelToEye: + return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>())); + case ModelToWorld: + return QVariant::fromValue(m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>())); + case ModelToWorldDirection: + return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(propertyValue.value.value<QVector3D>(), 0.0f))); + case NoTransform: + break; + } + } } + return propertyValue.value; } return QVariant(); } -// Called by FramePreparationJob or by RenderView when dealing with lights -void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix) -{ - QMutexLocker lock(&m_mutex); - if (m_worldMatrix != worldMatrix) { - m_worldMatrix = worldMatrix; - } -} - -// This will add the ShaderData to be cleared from updates at the end of the frame -// by the cleanup job -// Called by renderview jobs (several concurrent threads) -void ShaderData::markDirty() -{ - QMutexLocker lock(&m_mutex); - if (!ShaderData::m_updatedShaderData.contains(peerId())) - ShaderData::m_updatedShaderData.append(peerId()); -} - -/*! - \internal - Lookup if the current ShaderData or a nested ShaderData has updated properties. - UpdateProperties contains either the value of the propertie of a QNodeId if it's another ShaderData. - Transformed properties are updated for all of ShaderData that have ones at the point. - - \note This needs to be performed for every top level ShaderData every time it is used. - As we don't know if the transformed properties use the same viewMatrix for all RenderViews. - */ - +// Unit tests only ShaderData::TransformType ShaderData::propertyTransformType(const QString &name) const { - return m_transformedProperties.value(name, TransformType::NoTransform); + const auto it = m_originalProperties.constFind(name); + if (it != m_originalProperties.constEnd()) { + const PropertyValue &propertyValue = it.value(); + if (propertyValue.isTransformed) { + auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed")); + if (transformedIt != m_originalProperties.end()) + return static_cast<TransformType>(transformedIt.value().value.toInt()); + } + } + return NoTransform; } -void ShaderData::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +// Called by FramePreparationJob or by RenderView when dealing with lights +void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix) { - if (!m_propertyReader.isNull() && e->type() == PropertyUpdated) { - QString propertyName; - QVariant propertyValue; - - if (auto propertyChange = qSharedPointerDynamicCast<QPropertyUpdatedChange>(e)) { - propertyName = QString::fromLatin1(propertyChange->propertyName()); - propertyValue = m_propertyReader->readProperty(propertyChange->value()); - } else if (auto propertyChange = qSharedPointerDynamicCast<QDynamicPropertyUpdatedChange>(e)) { - propertyName = QString::fromLatin1(propertyChange->propertyName()); - propertyValue = m_propertyReader->readProperty(propertyChange->value()); - } else { - Q_UNREACHABLE(); - } - - // Note we aren't notified about nested QShaderData in this call - // only scalar / vec properties - m_originalProperties.insert(propertyName, propertyValue); - BackendNode::markDirty(AbstractRenderer::ParameterDirty); + if (m_worldMatrix != worldMatrix) { + m_worldMatrix = worldMatrix; } - - BackendNode::sceneChangeEvent(e); } RenderShaderDataFunctor::RenderShaderDataFunctor(AbstractRenderer *renderer, NodeManagers *managers) diff --git a/src/render/materialsystem/shaderdata_p.h b/src/render/materialsystem/shaderdata_p.h index f9c3ecc79..c9cc22939 100644 --- a/src/render/materialsystem/shaderdata_p.h +++ b/src/render/materialsystem/shaderdata_p.h @@ -76,49 +76,42 @@ public: ModelToWorld, ModelToWorldDirection }; + struct PropertyValue { + QVariant value; + bool isNested; + bool isTransformed; + }; ShaderData(); ~ShaderData(); - QHash<QString, QVariant> properties() const { return m_originalProperties; } + QHash<QString, PropertyValue> properties() const { return m_originalProperties; } // Called by FramePreparationJob void updateWorldTransform(const Matrix4x4 &worldMatrix); - // Call by RenderViewJob - void markDirty(); + QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix); + // Unit tests purposes only TransformType propertyTransformType(const QString &name) const; - QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix); // Called by FrameCleanupJob static void cleanup(NodeManagers *managers); void setManagers(NodeManagers *managers); -protected: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; +protected: PropertyReaderInterfacePtr m_propertyReader; - // 1 to 1 match with frontend properties, modified only by sceneChangeEvent - QHash<QString, QVariant> m_originalProperties; - - // Contains properties thar are of type ShaderData - QHash<QString, QVariant> m_nestedShaderDataProperties; - - // Contains property that are defined like: postionTransformed: ModelToEye - QHash<QString, TransformType> m_transformedProperties; + // 1 to 1 match with frontend properties + QHash<QString, PropertyValue> m_originalProperties; - QMutex m_mutex; - static QVector<Qt3DCore::QNodeId> m_updatedShaderData; Matrix4x4 m_worldMatrix; - Matrix4x4 m_viewMatrix; NodeManagers *m_managers; - void clearUpdatedProperties(); static ShaderData *lookupResource(NodeManagers *managers, Qt3DCore::QNodeId id); ShaderData *lookupResource(Qt3DCore::QNodeId id); diff --git a/src/render/materialsystem/shaderimage.cpp b/src/render/materialsystem/shaderimage.cpp index c1fb72bfd..65a4cf761 100644 --- a/src/render/materialsystem/shaderimage.cpp +++ b/src/render/materialsystem/shaderimage.cpp @@ -39,7 +39,6 @@ #include "shaderimage_p.h" #include <Qt3DRender/private/qshaderimage_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qabstracttexture.h> diff --git a/src/render/materialsystem/technique.cpp b/src/render/materialsystem/technique.cpp index d4199b7e3..10e9af990 100644 --- a/src/render/materialsystem/technique.cpp +++ b/src/render/materialsystem/technique.cpp @@ -48,9 +48,6 @@ #include <Qt3DRender/private/qtechnique_p.h> #include <Qt3DRender/private/shader_p.h> #include <Qt3DCore/private/qchangearbiter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/techniquemanager_p.h> #include <Qt3DRender/private/nodemanagers_p.h> diff --git a/src/render/picking/qraycaster.cpp b/src/render/picking/qraycaster.cpp index 27307d2a8..f32ea32f1 100644 --- a/src/render/picking/qraycaster.cpp +++ b/src/render/picking/qraycaster.cpp @@ -40,7 +40,6 @@ #include "qraycaster.h" #include "qabstractraycaster_p.h" #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qcomponent_p.h> #include <Qt3DCore/private/qscene_p.h> diff --git a/src/render/picking/qscreenraycaster.cpp b/src/render/picking/qscreenraycaster.cpp index ef87632b4..3e47c2a01 100644 --- a/src/render/picking/qscreenraycaster.cpp +++ b/src/render/picking/qscreenraycaster.cpp @@ -40,7 +40,6 @@ #include "qscreenraycaster.h" #include "qabstractraycaster_p.h" #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qcomponent_p.h> #include <Qt3DCore/private/qscene_p.h> diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp index 34bbaefd9..3a79204c7 100644 --- a/src/render/picking/raycaster.cpp +++ b/src/render/picking/raycaster.cpp @@ -45,8 +45,6 @@ #include <Qt3DRender/private/qabstractraycaster_p.h> #include <Qt3DRender/private/raycastingjob_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE @@ -179,24 +177,6 @@ void RayCaster::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime } } -void RayCaster::dispatchHits(const QAbstractRayCaster::Hits &hits) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("hits"); - e->setValue(QVariant::fromValue(hits)); - notifyObservers(e); - - if (m_runMode == QAbstractRayCaster::SingleShot) { - setEnabled(false); - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("enabled"); - e->setValue(false); - notifyObservers(e); - } -} - void RayCaster::notifyJob() { if (m_renderer && m_renderer->rayCastingJob()) diff --git a/src/render/picking/raycaster_p.h b/src/render/picking/raycaster_p.h index 2be87ec3c..865d40365 100644 --- a/src/render/picking/raycaster_p.h +++ b/src/render/picking/raycaster_p.h @@ -83,8 +83,6 @@ public: void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void cleanup(); - void dispatchHits(const QAbstractRayCaster::Hits &hits); - private: void notifyJob(); diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp index bedc7f61c..4b4199820 100644 --- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp @@ -1572,7 +1572,8 @@ void SubmissionContext::blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId, const GLenum mode = interpolationMethod ? GL_NEAREST : GL_LINEAR; m_glHelper->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - GL_COLOR_BUFFER_BIT, mode); + GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, + mode); // Reset draw buffer bindFramebuffer(lastDrawFboId, GraphicsHelperInterface::FBOReadAndDraw); diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp index c70f82dea..fee1cc4b5 100644 --- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp +++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp @@ -512,27 +512,24 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * // If the property needs to be transformed, we transform it here as // the shaderdata cannot hold transformed properties for multiple // thread contexts at once - if (currentShaderData->propertyTransformType(qmlPropertyName) != ShaderData::NoTransform) - activeUniformNamesToValue.insert(StringToInt::lookupId(varName), - currentShaderData->getTransformedProperty(qmlPropertyName, viewMatrix)); - else - activeUniformNamesToValue.insert(StringToInt::lookupId(varName), value); + activeUniformNamesToValue.insert(StringToInt::lookupId(varName), + currentShaderData->getTransformedProperty(qmlPropertyName.toLatin1(), viewMatrix)); } } } void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName) { - const QHash<QString, QVariant> &properties = rShaderData->properties(); - QHash<QString, QVariant>::const_iterator it = properties.begin(); - const QHash<QString, QVariant>::const_iterator end = properties.end(); + const QHash<QString, ShaderData::PropertyValue> &properties = rShaderData->properties(); + auto it = properties.begin(); + const auto end = properties.end(); while (it != end) { const auto prefix = qmlPropertyName.isEmpty() ? QLatin1String("") : QLatin1String("."); buildActiveUniformNameValueMapHelper(rShaderData, blockName + prefix + qmlPropertyName, it.key(), - it.value()); + it.value().value); ++it; } } diff --git a/src/render/renderers/opengl/renderer/commandthread.cpp b/src/render/renderers/opengl/renderer/commandthread.cpp deleted file mode 100644 index a518d3b68..000000000 --- a/src/render/renderers/opengl/renderer/commandthread.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "commandthread_p.h" -#include <Qt3DRender/private/glcommands_p.h> -#include <Qt3DRender/private/offscreensurfacehelper_p.h> -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/shadercache_p.h> -#include <QOpenGLContext> -#include <QOffscreenSurface> -#include <QDebug> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -CommandThread::CommandThread(Renderer *renderer) - : QThread() - , m_renderer(renderer) - , m_waitForStartSemaphore(0) - , m_initializedSemaphore(0) - , m_commandRequestedSemaphore(0) - , m_commandExecutionSemaphore(0) - , m_mainContext(nullptr) - , m_shaderCache(nullptr) - , m_offsreenSurfaceHelper(nullptr) - , m_currentCommand(nullptr) - , m_running(0) -{ -} - -CommandThread::~CommandThread() -{ - Q_ASSERT(!isRunning()); -} - -void CommandThread::setShaderCache(ShaderCache *shaderCache) -{ - m_shaderCache = shaderCache; -} - -// Called by RenderThread or MainThread (Scene3d) -void CommandThread::initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper) -{ - // Start the thread - start(); - - // Wait for thread to be started - m_waitForStartSemaphore.acquire(); - - m_mainContext = mainContext; - m_offsreenSurfaceHelper = offsreenSurfaceHelper; - Q_ASSERT(m_mainContext && offsreenSurfaceHelper); - - // Initialize shared context and resources for the thread. This must be - // done here since some platforms do not allow context sharing to be set up - // with contexts created on different threads. (Windows with WGL, in - // particular; resource sharing works fine later on, what matters is the - // thread the wglShareLists call is made on) - m_localContext.reset(new QOpenGLContext()); - m_localContext->setFormat(m_mainContext->format()); - m_localContext->setShareContext(m_mainContext); - if (!m_localContext->create()) - qWarning("CommandThread: Failed to create local context"); - m_localContext->moveToThread(this); - - m_running.fetchAndStoreOrdered(1); - - // Allow thread to proceed - m_initializedSemaphore.release(); -} - -// Called by RenderThread or MainThread (Scene3D) -void CommandThread::shutdown() -{ - m_running.fetchAndStoreOrdered(0); - - // Unblock thread - m_commandRequestedSemaphore.release(1); - - // Wait for thread to exit - wait(); - - // Reset semaphores (in case we ever want to restart) - m_waitForStartSemaphore.acquire(m_waitForStartSemaphore.available()); - m_initializedSemaphore.acquire(m_initializedSemaphore.available()); - m_commandRequestedSemaphore.acquire(m_commandRequestedSemaphore.available()); - m_commandExecutionSemaphore.acquire(m_commandExecutionSemaphore.available()); - m_localContext.reset(); -} - -// Any thread can call this, this is a blocking command -void CommandThread::executeCommand(GLCommand *command) -{ - if (!isRunning()) - return; - - // We lock to prevent any other call to executeCommand to be executed - // before we have received the result of our command - m_blockingCallerMutex.lock(); - - // Store command to be executed - m_currentCommand = command; - - // Allow thread to proceed and execute command - m_commandRequestedSemaphore.release(); - - // Wait for thread to be done - m_commandExecutionSemaphore.acquire(); - - // Reset command - m_currentCommand = nullptr; - - // Unlock blocking semaphore so that other calls to executeCommand - // can proceed - m_blockingCallerMutex.unlock(); -} - -void CommandThread::run() -{ - // Allow initialize to proceed - m_waitForStartSemaphore.release(); - - // Wait for initialize to be completed - m_initializedSemaphore.acquire(); - - Q_ASSERT(m_mainContext && m_shaderCache); - - // Initialize GraphicsContext - m_graphicsContext.reset(new GraphicsContext()); - m_graphicsContext->setShaderCache(m_shaderCache); - m_graphicsContext->setOpenGLContext(m_localContext.data()); - - bool initialized = false; - while (true) { - - // Wait for command - m_commandRequestedSemaphore.acquire(); - - // Are we still running? - if (!m_running.loadRelaxed()) { - m_graphicsContext->doneCurrent(); - // to prevent executeCommand being locked - m_commandExecutionSemaphore.release(); - break; - } - - if (Q_UNLIKELY(!initialized)) { - QOffscreenSurface *offscreenSurface = m_offsreenSurfaceHelper->offscreenSurface(); - Q_ASSERT(offscreenSurface); - m_graphicsContext->makeCurrent(offscreenSurface); - initialized = true; - } - - m_currentCommand->execute(m_renderer, m_graphicsContext.data()); - - // Allow caller to proceed as we are done with the command - m_commandExecutionSemaphore.release(); - } -} - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/renderers/opengl/renderer/commandthread_p.h b/src/render/renderers/opengl/renderer/commandthread_p.h deleted file mode 100644 index 0508675c4..000000000 --- a/src/render/renderers/opengl/renderer/commandthread_p.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_COMMANDTHREAD_P_H -#define QT3DRENDER_RENDER_COMMANDTHREAD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QThread> -#include <QtCore/QSemaphore> -#include <QtCore/QMutex> - -QT_BEGIN_NAMESPACE - -class QOpenGLContext; - -namespace Qt3DRender { - -namespace Render { - -class Renderer; -class GLCommand; -class OffscreenSurfaceHelper; -class GraphicsContext; -class ShaderCache; - -class CommandThread : public QThread -{ - Q_OBJECT -public: - explicit CommandThread(Renderer *renderer); - ~CommandThread(); - - Render::Renderer* renderer() const { return m_renderer; } - - void setShaderCache(ShaderCache *shaderCache); - ShaderCache *shaderCache() const { return m_shaderCache; } - - void initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper); - void shutdown(); - - void executeCommand(GLCommand *command); - -private: - void run() override; - void executeCommandInternal(Qt3DRender::Render::GLCommand *command); - -private: - Renderer* m_renderer; - QSemaphore m_waitForStartSemaphore; - QSemaphore m_initializedSemaphore; - QSemaphore m_commandRequestedSemaphore; - QSemaphore m_commandExecutionSemaphore; - QMutex m_blockingCallerMutex; - QOpenGLContext *m_mainContext; - ShaderCache *m_shaderCache; - OffscreenSurfaceHelper *m_offsreenSurfaceHelper; - QScopedPointer<QOpenGLContext> m_localContext; - QScopedPointer<GraphicsContext> m_graphicsContext; - GLCommand *m_currentCommand; - QAtomicInt m_running; -}; - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_COMMANDTHREAD_P_H diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 45f13c424..42af03d11 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -89,14 +89,13 @@ #include <Qt3DRender/private/buffercapture_p.h> #include <Qt3DRender/private/offscreensurfacehelper_p.h> #include <Qt3DRender/private/renderviewbuilder_p.h> -#include <Qt3DRender/private/commandthread_p.h> -#include <Qt3DRender/private/glcommands_p.h> #include <Qt3DRender/private/setfence_p.h> #include <Qt3DRender/private/subtreeenabler_p.h> #include <Qt3DRender/qcameralens.h> #include <Qt3DCore/private/qeventfilterservice_p.h> #include <Qt3DCore/private/qabstractaspectjobmanager_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> #if QT_CONFIG(qt3d_profile_jobs) #include <Qt3DCore/private/aspectcommanddebugger_p.h> @@ -165,7 +164,6 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_submissionContext(nullptr) , m_renderQueue(new RenderQueue()) , m_renderThread(type == QRenderAspect::Threaded ? new RenderThread(this) : nullptr) - , m_commandThread(new CommandThread(this)) , m_vsyncFrameAdvanceService(new VSyncFrameAdvanceService(m_renderThread != nullptr)) , m_waitForInitializationToBeCompleted(0) , m_hasBeenInitializedMutex() @@ -196,7 +194,9 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) - , m_sendTextureChangesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendTextureChangesToFrontend(); }, JobTypes::SendTextureChangesToFrontend)) + , m_sendTextureChangesToFrontendJob(decltype(m_sendTextureChangesToFrontendJob)::create([] {}, + [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); }, + JobTypes::SendTextureChangesToFrontend)) , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend)) , m_sendDisablesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend)) , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering)) @@ -331,18 +331,11 @@ QOpenGLContext *Renderer::shareContext() const : nullptr); } -// Executed in the command thread +// Executed in the reloadDirtyShader job void Renderer::loadShader(Shader *shader, HShader shaderHandle) { -#ifdef SHADER_LOADING_IN_COMMAND_THREAD - Q_UNUSED(shaderHandle); - Profiling::GLTimeRecorder recorder(Profiling::ShaderUpload); - LoadShaderCommand cmd(shader); - m_commandThread->executeCommand(&cmd); -#else Q_UNUSED(shader); m_dirtyShaders.push_back(shaderHandle); -#endif } void Renderer::setOpenGLContext(QOpenGLContext *context) @@ -403,7 +396,6 @@ void Renderer::initialize() // Set shader cache on submission context and command thread m_submissionContext->setShaderCache(m_shaderCache); - m_commandThread->setShaderCache(m_shaderCache); // Note: we don't have a surface at this point // The context will be made current later on (at render time) @@ -416,13 +408,6 @@ void Renderer::initialize() // (MS Windows), an offscreen surface is just a hidden QWindow. m_format = ctx->format(); QMetaObject::invokeMethod(m_offscreenHelper, "createOffscreenSurface"); - - // Initialize command thread (uses the offscreen surface to make its own ctx current) - m_commandThread->initialize(ctx, m_offscreenHelper); - // Note: the offscreen surface is also used at shutdown time to release resources - // of the submission gl context (when the window is already gone). - // By that time (in releaseGraphicResources), the commandThread has been destroyed - // and the offscreenSurface can be reused } // Awake setScenegraphRoot in case it was waiting @@ -454,8 +439,6 @@ void Renderer::shutdown() m_renderQueue->reset(); lockRenderQueue.unlock(); - m_commandThread->shutdown(); - if (!m_renderThread) { releaseGraphicsResources(); } else { @@ -1167,24 +1150,39 @@ void Renderer::reloadDirtyShaders() } } -// Executed in a job -void Renderer::sendTextureChangesToFrontend() +// Executed in a job (as postFrame) +void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager) { const QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties); for (const auto &pair : updateTextureProperties) { - // Prepare change notification - const Qt3DCore::QNodeIdVector targetIds = pair.second; for (const Qt3DCore::QNodeId targetId: targetIds) { + // Lookup texture Texture *t = m_nodesManager->textureManager()->lookupResource(targetId); + // If backend texture is Dirty, some property has changed and the properties we are + // about to send are already outdate + if (t == nullptr || t->dirtyFlags() != Texture::NotDirty) + continue; - // Texture might have been deleted between previous and current frame - if (t == nullptr) + QAbstractTexture *texture = static_cast<QAbstractTexture *>(manager->lookupNode(targetId)); + if (!texture) continue; + const TextureProperties &properties = pair.first.properties; + + const bool blocked = texture->blockNotifications(true); + texture->setWidth(properties.width); + texture->setHeight(properties.height); + texture->setDepth(properties.depth); + texture->setLayers(properties.layers); + texture->setFormat(properties.format); + texture->blockNotifications(blocked); + + QAbstractTexturePrivate *dTexture = static_cast<QAbstractTexturePrivate *>(QNodePrivate::get(texture)); - // Send change and update backend - t->updatePropertiesAndNotify(pair.first); + dTexture->setStatus(properties.status); + dTexture->setHandleType(pair.first.handleType); + dTexture->setHandle(pair.first.handle); } } } @@ -1807,11 +1805,12 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() const bool frameGraphDirty = dirtyBitsForFrame & AbstractRenderer::FrameGraphDirty; const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty || frameGraphDirty; + const bool shadersDirty = dirtyBitsForFrame & AbstractRenderer::ShadersDirty; const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty; const bool lightsDirty = dirtyBitsForFrame & AbstractRenderer::LightsDirty; const bool computeableDirty = dirtyBitsForFrame & AbstractRenderer::ComputeDirty; const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty; - const bool materialCacheNeedsToBeRebuilt = materialDirty || frameGraphDirty; + const bool materialCacheNeedsToBeRebuilt = shadersDirty || materialDirty || frameGraphDirty; // Rebuild Entity Layers list if layers are dirty if (layersDirty) diff --git a/src/render/renderers/opengl/renderer/renderer.pri b/src/render/renderers/opengl/renderer/renderer.pri index 34f6064bd..849bac702 100644 --- a/src/render/renderers/opengl/renderer/renderer.pri +++ b/src/render/renderers/opengl/renderer/renderer.pri @@ -1,8 +1,6 @@ INCLUDEPATH += $$PWD SOURCES += \ - $$PWD/commandthread.cpp \ - $$PWD/glcommands.cpp \ $$PWD/openglvertexarrayobject.cpp \ $$PWD/rendercommand.cpp \ $$PWD/renderer.cpp \ @@ -12,8 +10,6 @@ SOURCES += \ $$PWD/shaderparameterpack.cpp HEADERS += \ - $$PWD/commandthread_p.h \ - $$PWD/glcommands_p.h \ $$PWD/openglvertexarrayobject_p.h \ $$PWD/renderercache_p.h \ $$PWD/rendercommand_p.h \ diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index c7b4f8805..41a071290 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -144,7 +144,6 @@ class RenderView; class Effect; class RenderPass; class RenderThread; -class CommandThread; class RenderStateSet; class VSyncFrameAdvanceService; class PickEventFilter; @@ -320,7 +319,6 @@ private: RenderQueue *m_renderQueue; QScopedPointer<RenderThread> m_renderThread; - QScopedPointer<CommandThread> m_commandThread; QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService; QSemaphore m_submitRenderViewsSemaphore; @@ -379,7 +377,7 @@ private: GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob; GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob; GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob; - GenericLambdaJobPtr<std::function<void ()>> m_sendTextureChangesToFrontendJob; + GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>> m_sendTextureChangesToFrontendJob; GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob; GenericLambdaJobPtr<std::function<void ()>> m_sendDisablesToFrontendJob; IntrospectShadersJobPtr m_introspectShaderJob; @@ -391,7 +389,7 @@ private: void lookForDownloadableBuffers(); void lookForDirtyTextures(); void reloadDirtyShaders(); - void sendTextureChangesToFrontend(); + void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager); void sendSetFenceHandlesToFrontend(); void sendDisablesToFrontend(); diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp index 420b32325..8fbe8e188 100644 --- a/src/render/renderers/opengl/renderer/renderview.cpp +++ b/src/render/renderers/opengl/renderer/renderview.cpp @@ -849,56 +849,6 @@ void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, uniformPack.setUniformBuffer(std::move(uniformBlockUBO)); // Buffer update to GL buffer will be done at render time } - - - //ShaderData *shaderData = nullptr; - // if ((shaderData = m_manager->shaderDataManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != nullptr) { - // UBO are indexed by <ShaderId, ShaderDataId> so that a same QShaderData can be used among different shaders - // while still making sure that if they have a different layout everything will still work - // If two shaders define the same block with the exact same layout, in that case the UBO could be shared - // but how do we know that ? We'll need to compare ShaderUniformBlocks - - // Note: we assume that if a buffer is shared across multiple shaders - // then it implies that they share the same layout - - // Temporarly disabled - - // BufferShaderKey uboKey(shaderData->peerId(), - // shader->peerId()); - - // BlockToUBO uniformBlockUBO; - // uniformBlockUBO.m_blockIndex = block.m_index; - // uniformBlockUBO.m_shaderDataID = shaderData->peerId(); - // bool uboNeedsUpdate = false; - - // // build UBO at uboId if not created before - // if (!m_manager->glBufferManager()->contains(uboKey)) { - // m_manager->glBufferManager()->getOrCreateResource(uboKey); - // uboNeedsUpdate = true; - // } - - // // If shaderData has been updated (property has changed or one of the nested properties has changed) - // // foreach property defined in the QShaderData, we try to fill the value of the corresponding active uniform(s) - // // for all the updated properties (all the properties if the UBO was just created) - // if (shaderData->updateViewTransform(*m_data->m_viewMatrix) || uboNeedsUpdate) { - // // Clear previous values remaining in the hash - // m_data->m_uniformBlockBuilder.activeUniformNamesToValue.clear(); - // // Update only update properties if uboNeedsUpdate is true, otherwise update the whole block - // m_data->m_uniformBlockBuilder.updatedPropertiesOnly = uboNeedsUpdate; - // // Retrieve names and description of each active uniforms in the uniform block - // m_data->m_uniformBlockBuilder.uniforms = shader->activeUniformsForUniformBlock(block.m_index); - // // Builds the name-value map for the block - // m_data->m_uniformBlockBuilder.buildActiveUniformNameValueMapStructHelper(shaderData, block.m_name); - // if (!uboNeedsUpdate) - // shaderData->markDirty(); - // // copy the name-value map into the BlockToUBO - // uniformBlockUBO.m_updatedProperties = m_data->m_uniformBlockBuilder.activeUniformNamesToValue; - // uboNeedsUpdate = true; - // } - - // uniformBlockUBO.m_needsUpdate = uboNeedsUpdate; - // uniformPack.setUniformBuffer(std::move(uniformBlockUBO)); - // } } } diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp index 11d2c2be9..1b5a972ec 100644 --- a/src/render/renderers/opengl/textures/gltexture.cpp +++ b/src/render/renderers/opengl/textures/gltexture.cpp @@ -54,9 +54,6 @@ #include <Qt3DRender/private/qabstracttexture_p.h> #include <Qt3DRender/private/renderbuffer_p.h> #include <Qt3DRender/private/qtextureimagedata_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #if !defined(QT_OPENGL_ES_2) #include <QOpenGLFunctions_3_1> diff --git a/src/render/renderstates/qdithering.cpp b/src/render/renderstates/qdithering.cpp index ae77ced97..a449be508 100644 --- a/src/render/renderstates/qdithering.cpp +++ b/src/render/renderstates/qdithering.cpp @@ -41,7 +41,6 @@ #include "qdithering.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qmultisampleantialiasing.cpp b/src/render/renderstates/qmultisampleantialiasing.cpp index bb5136846..249dcd4bd 100644 --- a/src/render/renderstates/qmultisampleantialiasing.cpp +++ b/src/render/renderstates/qmultisampleantialiasing.cpp @@ -40,7 +40,6 @@ #include "qmultisampleantialiasing.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qnodepthmask.cpp b/src/render/renderstates/qnodepthmask.cpp index 7be7f24f4..241751a26 100644 --- a/src/render/renderstates/qnodepthmask.cpp +++ b/src/render/renderstates/qnodepthmask.cpp @@ -41,7 +41,6 @@ #include "qnodepthmask.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qrastermode.cpp b/src/render/renderstates/qrastermode.cpp index fc255b717..c432f1063 100644 --- a/src/render/renderstates/qrastermode.cpp +++ b/src/render/renderstates/qrastermode.cpp @@ -45,6 +45,100 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +/*! + \class Qt3DRender::QRasterMode + \brief The QRasterMode render state allows to control the type of + rasterization to be performed + \since 5.14 + \inmodule Qt3DRender + \ingroup renderstates + + The QRasterMode class is used to control the rasterization step of the + primitives at render time. This can be used to choose whether we only + want to show points, edges or fill a primitive. + + \note This is not supported when rendering on OpenGL ES 2.0 platforms. + + \sa QAlphaTest, QStencilTest + */ + +/*! + \qmltype RasterMode + \brief The RasterMode render state allows to control the type of + rasterization to be performed + \since 5.14 + \inqmlmodule Qt3D.Render + \inherits RenderState + \instantiates Qt3DRender::QRasterMode + \ingroup renderstates + + The QRasterMode class is used to control the rasterization step of the + primitives at render time. This can be used to choose whether we only + want to show points, edges or fill a primitive. + + \note This is not supported when rendering on OpenGL ES 2.0 platforms. + + \sa AlphaTest, StencilTest + */ + +/*! + \enum Qt3DRender::QRasterMode::RasterMode + + Enumeration for raster mode values + \value Points Vertices at the start of an edge are drawn as points. + \value Lines Edges of a polygon are draw as line segments. + \value Fill Fills the interior of the primitive. +*/ + +/*! + \enum Qt3DRender::QRasterMode::FaceMode + + Enumeration for face mode values + \value Front Applies to front faces only + \value Back Applies to back faces only + \value FrontAndBack Applies to front and back faces +*/ + +/*! + \property QRasterMode::rasterMode + + Holds the raster mode to be used. +*/ + +/*! + \property QRasterMode::faceMode + + Holds the face mode to be used. Controls on which face the raster mode is + to be applied. +*/ + +/*! + \qmlproperty enumeration RasterMode::rasterMode + + Holds the raster mode to be used. + + \list + \li Points Vertices at the start of an edge are drawn as points. + \li Lines Edges of a polygon are draw as line segments. + \li Fill Fills the interior of the primitive. + \endlist +*/ + +/*! + \qmlproperty enumeration RasterMode::faceMode + + Holds the face mode to be used. Controls on which face the raster mode is + to be applied. + + \list + \li Front Applies to front faces only + \li Back Applies to back faces only + \li FrontAndBack Applies to front and back faces + \endlist +*/ + + + QRasterMode::QRasterMode(QNode *parent) : QRenderState(*new QRasterModePrivate, parent) { diff --git a/src/render/renderstates/qseamlesscubemap.cpp b/src/render/renderstates/qseamlesscubemap.cpp index 860b36450..8458aded8 100644 --- a/src/render/renderstates/qseamlesscubemap.cpp +++ b/src/render/renderstates/qseamlesscubemap.cpp @@ -40,7 +40,6 @@ #include "qseamlesscubemap.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qstenciloperation.cpp b/src/render/renderstates/qstenciloperation.cpp index 86b4c706b..34f95c03d 100644 --- a/src/render/renderstates/qstenciloperation.cpp +++ b/src/render/renderstates/qstenciloperation.cpp @@ -40,7 +40,6 @@ #include "qstenciloperation.h" #include "qstenciloperation_p.h" #include "qstenciloperationarguments.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qstenciltest.cpp b/src/render/renderstates/qstenciltest.cpp index 8f6738e54..7284af140 100644 --- a/src/render/renderstates/qstenciltest.cpp +++ b/src/render/renderstates/qstenciltest.cpp @@ -41,7 +41,6 @@ #include "qstenciltest.h" #include "qstenciltest_p.h" #include "qstenciltestarguments.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/renderstatenode.cpp b/src/render/renderstates/renderstatenode.cpp index bd218c803..3040c5aaa 100644 --- a/src/render/renderstates/renderstatenode.cpp +++ b/src/render/renderstates/renderstatenode.cpp @@ -37,7 +37,6 @@ #include "renderstatenode_p.h" #include <Qt3DRender/qrenderstate.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qalphacoverage.h> #include <Qt3DRender/qalphatest.h> diff --git a/src/render/renderstates/renderstates.cpp b/src/render/renderstates/renderstates.cpp index bd4a209a1..5e238c010 100644 --- a/src/render/renderstates/renderstates.cpp +++ b/src/render/renderstates/renderstates.cpp @@ -40,7 +40,6 @@ #include "renderstates_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qrenderstate.h> #include <Qt3DRender/qcullface.h> #include <Qt3DRender/qpointsize.h> diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp index 229d773ad..ab9f01d39 100644 --- a/src/render/texture/qabstracttexture.cpp +++ b/src/render/texture/qabstracttexture.cpp @@ -85,6 +85,39 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat } } +void QAbstractTexturePrivate::setStatus(QAbstractTexture::Status status) +{ + Q_Q(QAbstractTexture); + if (m_status != status) { + m_status = status; + const bool blocked = q->blockNotifications(true); + q->statusChanged(status); + q->blockNotifications(blocked); + } +} + +void QAbstractTexturePrivate::setHandle(const QVariant &handle) +{ + Q_Q(QAbstractTexture); + if (m_handle != handle) { + m_handle = handle; + const bool blocked = q->blockNotifications(true); + emit q->handleChanged(handle); + q->blockNotifications(blocked); + } +} + +void QAbstractTexturePrivate::setHandleType(QAbstractTexture::HandleType type) +{ + Q_Q(QAbstractTexture); + if (m_handleType != type) { + m_handleType = type; + const bool blocked = q->blockNotifications(true); + emit q->handleTypeChanged(type); + q->blockNotifications(blocked); + } +} + /*! \class Qt3DRender::QAbstractTexture \inmodule Qt3DRender @@ -564,7 +597,9 @@ void QAbstractTexture::setStatus(Status status) Q_D(QAbstractTexture); if (status != d->m_status) { d->m_status = status; + const bool blocked = blockNotifications(true); emit statusChanged(status); + blockNotifications(blocked); } } @@ -673,11 +708,7 @@ void QAbstractTexture::addTextureImage(QAbstractTextureImage *textureImage) if (!textureImage->parent()) textureImage->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), textureImage); - change->setPropertyName("textureImage"); - d->notifyObservers(change); - } + d->updateNode(textureImage, "textureImage", PropertyValueAdded); } } @@ -688,11 +719,7 @@ void QAbstractTexture::removeTextureImage(QAbstractTextureImage *textureImage) { Q_ASSERT(textureImage); Q_D(QAbstractTexture); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), textureImage); - change->setPropertyName("textureImage"); - d->notifyObservers(change); - } + d->updateNode(textureImage, "textureImage", PropertyValueRemoved); d->m_textureImages.removeOne(textureImage); // Remove bookkeeping connection d->unregisterDestructionHelper(textureImage); diff --git a/src/render/texture/qabstracttexture.h b/src/render/texture/qabstracttexture.h index 5a32b8487..b3d5efb34 100644 --- a/src/render/texture/qabstracttexture.h +++ b/src/render/texture/qabstracttexture.h @@ -350,6 +350,7 @@ protected: explicit QAbstractTexture(QAbstractTexturePrivate &dd, Qt3DCore::QNode *parent = nullptr); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; + // TO DO Qt6, should be on private class void setStatus(Status status); void setHandle(const QVariant &handle); void setHandleType(HandleType type); diff --git a/src/render/texture/qabstracttexture_p.h b/src/render/texture/qabstracttexture_p.h index 573eac8c7..5b2945f73 100644 --- a/src/render/texture/qabstracttexture_p.h +++ b/src/render/texture/qabstracttexture_p.h @@ -96,6 +96,10 @@ public : QTextureGeneratorPtr dataFunctor() const; void setDataFunctor(const QTextureGeneratorPtr &generator); + void setStatus(QAbstractTexture::Status status); + void setHandle(const QVariant &handle); + void setHandleType(QAbstractTexture::HandleType type); + QVector<QTextureDataUpdate> m_pendingDataUpdates; private: diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp index a5d342d83..9ca4599c5 100644 --- a/src/render/texture/qabstracttextureimage.cpp +++ b/src/render/texture/qabstracttextureimage.cpp @@ -39,7 +39,6 @@ #include "qabstracttextureimage.h" #include "qabstracttextureimage_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtextureimagedatagenerator.h> QT_BEGIN_NAMESPACE diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp index 53216d27d..d120c2b39 100644 --- a/src/render/texture/texture.cpp +++ b/src/render/texture/texture.cpp @@ -93,20 +93,6 @@ void Texture::unsetDirty() m_dirty = Texture::NotDirty; } -void Texture::addTextureImage(Qt3DCore::QNodeId id) -{ - if (!m_textureImageIds.contains(id)) { - m_textureImageIds.push_back(id); - addDirtyFlag(DirtyImageGenerators); - } -} - -void Texture::removeTextureImage(Qt3DCore::QNodeId id) -{ - m_textureImageIds.removeAll(id); - addDirtyFlag(DirtyImageGenerators); -} - // This is called by Renderer::updateGLResources // when the texture has been marked for cleanup void Texture::cleanup() @@ -125,38 +111,6 @@ void Texture::cleanup() m_dirty = NotDirty; } -// ChangeArbiter/Aspect Thread -void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - DirtyFlags dirty; - - switch (e->type()) { - - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("textureImage")) { - addTextureImage(change->addedNodeId()); - } - } - break; - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("textureImage")) { - removeTextureImage(change->removedNodeId()); - } - } - break; - - default: - break; - - } - - addDirtyFlag(dirty); - BackendNode::sceneChangeEvent(e); -} - void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { BackendNode::syncFromFrontEnd(frontEnd, firstTime); @@ -203,8 +157,12 @@ void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) addTextureDataUpdate(pendingUpdate); dnode->m_pendingDataUpdates.clear(); - for (const auto imgNode : dnode->m_textureImages) - addTextureImage(imgNode->id()); + auto ids = Qt3DCore::qIdsForNodes(dnode->m_textureImages); + std::sort(std::begin(ids), std::end(ids)); + if (ids != m_textureImageIds) { + m_textureImageIds = ids; + addDirtyFlag(DirtyImageGenerators); + } } if (dnode->m_sharedTextureId != m_sharedTextureId) { @@ -220,88 +178,6 @@ void Texture::setDataGenerator(const QTextureGeneratorPtr &generator) addDirtyFlag(DirtyDataGenerator); } -// Called by sendTextureChangesToFrontendJob once GLTexture and sharing -// has been performed -void Texture::updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo) -{ - // If we are Dirty, some property has changed and the properties we have - // received are potentially already outdated - if (m_dirty != NotDirty) - return; - - // Note we don't update target has it is constant for frontend nodes - - if (updateInfo.properties.width != m_properties.width) { - m_properties.width = updateInfo.properties.width; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("width"); - change->setValue(updateInfo.properties.width); - notifyObservers(change); - } - - if (updateInfo.properties.height != m_properties.height) { - m_properties.height = updateInfo.properties.height; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("height"); - change->setValue(updateInfo.properties.height); - notifyObservers(change); - } - - if (updateInfo.properties.depth != m_properties.depth) { - m_properties.depth = updateInfo.properties.depth; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("depth"); - change->setValue(updateInfo.properties.depth); - notifyObservers(change); - } - - if (updateInfo.properties.layers != m_properties.layers) { - m_properties.layers = updateInfo.properties.layers; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("layers"); - change->setValue(updateInfo.properties.layers); - notifyObservers(change); - } - - if (updateInfo.properties.format != m_properties.format) { - m_properties.format = updateInfo.properties.format; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("format"); - change->setValue(updateInfo.properties.format); - notifyObservers(change); - } - - if (updateInfo.properties.status != m_properties.status) { - m_properties.status = updateInfo.properties.status; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("status"); - change->setValue(updateInfo.properties.status); - notifyObservers(change); - } - - { - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("handleType"); - change->setValue(updateInfo.handleType); - notifyObservers(change); - } - - { - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("handle"); - change->setValue(updateInfo.handle); - notifyObservers(change); - } -} - bool Texture::isValid(TextureImageManager *manager) const { for (const QNodeId &id : m_textureImageIds) { @@ -336,8 +212,9 @@ void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan m_dataFunctor = data.dataFunctor; m_sharedTextureId = data.sharedTextureId; - for (const QNodeId &imgId : data.textureImageIds) - addTextureImage(imgId); + m_textureImageIds = data.textureImageIds; + if (m_textureImageIds.size()) + addDirtyFlag(DirtyImageGenerators); const QVector<QTextureDataUpdate> initialDataUpdates = data.initialDataUpdates; for (const QTextureDataUpdate &initialUpdate : initialDataUpdates) diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h index 516a1f1f3..83a05ebcc 100644 --- a/src/render/texture/texture_p.h +++ b/src/render/texture/texture_p.h @@ -156,14 +156,11 @@ public: DirtyFlags dirtyFlags(); void unsetDirty(); - void addTextureImage(Qt3DCore::QNodeId id); - void removeTextureImage(Qt3DCore::QNodeId id); void cleanup(); void addTextureDataUpdate(const QTextureDataUpdate &update); QVector<QTextureDataUpdate> takePendingTextureDataUpdates() { return std::move(m_pendingTextureDataUpdates); } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline const TextureProperties& properties() const { return m_properties; } @@ -173,7 +170,6 @@ public: inline int sharedTextureId() const { return m_sharedTextureId; } void setDataGenerator(const QTextureGeneratorPtr &generator); - void updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo); bool isValid(TextureImageManager *manager) const; private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; diff --git a/src/render/texture/textureimage.cpp b/src/render/texture/textureimage.cpp index 512949d91..25001b9df 100644 --- a/src/render/texture/textureimage.cpp +++ b/src/render/texture/textureimage.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "textureimage_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtextureimage.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/qabstracttextureimage_p.h> |