diff options
-rw-r--r-- | examples/qt3d/scene3d/AnimatedEntity.qml | 6 | ||||
-rw-r--r-- | examples/qt3d/scene3d/main.qml | 21 | ||||
-rw-r--r-- | src/core/geometry/qgeometryview.cpp | 2 | ||||
-rw-r--r-- | src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp | 2 | ||||
-rw-r--r-- | src/render/frontend/qrenderaspect.cpp | 10 | ||||
-rw-r--r-- | src/render/geometry/geometryrenderer.cpp | 18 | ||||
-rw-r--r-- | src/render/geometry/geometryrenderer_p.h | 3 | ||||
-rw-r--r-- | src/render/jobs/calcboundingvolumejob.cpp | 135 | ||||
-rw-r--r-- | src/render/jobs/calcboundingvolumejob_p.h | 12 | ||||
-rw-r--r-- | tests/auto/render/boundingsphere/tst_boundingsphere.cpp | 73 | ||||
-rw-r--r-- | tests/auto/render/commons/testaspect.h | 27 | ||||
-rw-r--r-- | tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp | 46 | ||||
-rw-r--r-- | tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp | 2 | ||||
-rw-r--r-- | tests/auto/render/raycastingjob/tst_raycastingjob.cpp | 56 |
14 files changed, 316 insertions, 97 deletions
diff --git a/examples/qt3d/scene3d/AnimatedEntity.qml b/examples/qt3d/scene3d/AnimatedEntity.qml index 3e24dc785..962317a6b 100644 --- a/examples/qt3d/scene3d/AnimatedEntity.qml +++ b/examples/qt3d/scene3d/AnimatedEntity.qml @@ -48,7 +48,7 @@ ** ****************************************************************************/ -import Qt3D.Core 2.0 +import Qt3D.Core 2.15 import Qt3D.Render 2.15 import Qt3D.Input 2.0 import Qt3D.Extras 2.15 @@ -60,6 +60,10 @@ Entity { id: sceneRoot property RenderCapabilities capabilities : renderSettings.renderCapabilities + property bool validBounds: sphereMesh.implicitPointsValid + property vector3d sphereMinPt: sphereMesh.implicitMinPoint + property vector3d sphereMaxPt: sphereMesh.implicitMaxPoint + Camera { id: camera projectionType: CameraLens.PerspectiveProjection diff --git a/examples/qt3d/scene3d/main.qml b/examples/qt3d/scene3d/main.qml index 6d5617ca3..f7ba24ab4 100644 --- a/examples/qt3d/scene3d/main.qml +++ b/examples/qt3d/scene3d/main.qml @@ -151,6 +151,27 @@ Item { } } + Rectangle { + radius: 10 + color: "#aaffffff" + border.width: 1 + border.color: "black" + width: childrenRect.width + anchors.margins + height: childrenRect.height + anchors.margins + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.margins: 20 + visible: rootEntity.validBounds + + Column { + x: parent.anchors.margins / 2 + y: x + + Text { text: "Sphere:\n Min Extent: " + rootEntity.sphereMinPt } + Text { text: " Max Extent: " + rootEntity.sphereMaxPt } + } + } + SequentialAnimation { id: animation diff --git a/src/core/geometry/qgeometryview.cpp b/src/core/geometry/qgeometryview.cpp index 258448ba4..44933914a 100644 --- a/src/core/geometry/qgeometryview.cpp +++ b/src/core/geometry/qgeometryview.cpp @@ -273,7 +273,7 @@ bool BoundingVolumeCalculator::apply(QAttribute *positionAttribute, const float radius = (center - maxDistantPointCenter.maxDistPt).length(); - if (center == Vector3D{} || radius < 0.f) + if (center == Vector3D{} && radius < 0.f) return false; m_radius = radius; diff --git a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp index 8576e113b..4fa5a5fd1 100644 --- a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp +++ b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp @@ -48,6 +48,7 @@ #include <Qt3DCore/qbuffer.h> #include <Qt3DCore/qgeometry.h> #include <Qt3DCore/qgeometryview.h> +#include <Qt3DCore/qboundingvolume.h> #include <QtCore/qvariantanimation.h> #include <Qt3DQuick/private/quick3dnodev9_p.h> @@ -87,6 +88,7 @@ void Qt3DQuick3DCorePlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DCore::Quick::Quick3DBuffer>(uri, 2, 0, "Buffer"); Qt3DCore::Quick::registerExtendedType<Qt3DCore::QGeometry, Qt3DCore::Quick::Quick3DGeometry>("QGeometry", "Qt3D.Core/Geometry", uri, 2, 0, "Geometry"); qmlRegisterType<Qt3DCore::QGeometryView>(uri, 2, 16, "GeometryView"); + qmlRegisterType<Qt3DCore::QBoundingVolume>(uri, 2, 16, "BoundingVolume"); qmlRegisterType<Qt3DCore::Quick::QQuaternionAnimation>(uri, 2, 0, "QuaternionAnimation"); qRegisterAnimationInterpolator<QQuaternion>(Qt3DCore::Quick::q_quaternionInterpolator); diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 202012194..dff7f3640 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -95,6 +95,7 @@ #include <Qt3DCore/qarmature.h> #include <Qt3DCore/qjoint.h> #include <Qt3DCore/qskeletonloader.h> +#include <Qt3DCore/qcoreaspect.h> #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/private/cameraselectornode_p.h> @@ -297,6 +298,8 @@ void QRenderAspectPrivate::createNodeManagers() m_updateEntityLayersJob->setManager(m_nodeManagers); m_pickBoundingVolumeJob->setManagers(m_nodeManagers); m_rayCastingJob->setManagers(m_nodeManagers); + + m_calculateBoundingVolumeJob->setFrontEndNodeManager(m_aspectManager); } void QRenderAspectPrivate::onEngineStartup() @@ -316,6 +319,13 @@ void QRenderAspectPrivate::onEngineStartup() // Ensures all skeletons are loaded before we try to update them m_updateSkinningPaletteJob->addDependency(m_syncLoadingJobs); + + // make sure bv job in core aspect runs before the one in render aspect + if (m_aspectManager) { + auto *coreAspect = qobject_cast<Qt3DCore::QCoreAspect *>(m_aspectManager->aspect(&Qt3DCore::QCoreAspect::staticMetaObject)); + Q_ASSERT(coreAspect); + m_calculateBoundingVolumeJob->addDependency(coreAspect->calculateBoundingVolumeJob()); + } } /*! \internal */ diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp index 5a4bdcd9c..d314e87ce 100644 --- a/src/render/geometry/geometryrenderer.cpp +++ b/src/render/geometry/geometryrenderer.cpp @@ -92,8 +92,6 @@ void GeometryRenderer::cleanup() m_geometryId = Qt3DCore::QNodeId(); m_dirty = false; m_geometryFactory.reset(); - qDeleteAll(m_triangleVolumes); - m_triangleVolumes.clear(); } void GeometryRenderer::setManager(GeometryRendererManager *manager) @@ -135,8 +133,12 @@ void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) }; if (view) { + m_dirty |= !m_hasView; + m_hasView = true; propertyUpdater(view); } else { + m_dirty |= m_hasView; + m_hasView = false; propertyUpdater(node); const QGeometryRendererPrivate *dnode = static_cast<const QGeometryRendererPrivate *>(QNodePrivate::get(frontEnd)); @@ -210,18 +212,6 @@ void GeometryRenderer::unsetDirty() m_dirty = false; } - -void GeometryRenderer::setTriangleVolumes(const QVector<RayCasting::QBoundingVolume *> &volumes) -{ - qDeleteAll(m_triangleVolumes); - m_triangleVolumes = volumes; -} - -QVector<RayCasting::QBoundingVolume *> GeometryRenderer::triangleData() const -{ - return m_triangleVolumes; -} - GeometryRendererFunctor::GeometryRendererFunctor(AbstractRenderer *renderer, GeometryRendererManager *manager) : m_manager(manager) , m_renderer(renderer) diff --git a/src/render/geometry/geometryrenderer_p.h b/src/render/geometry/geometryrenderer_p.h index 87a289f7d..36ba08acd 100644 --- a/src/render/geometry/geometryrenderer_p.h +++ b/src/render/geometry/geometryrenderer_p.h @@ -98,6 +98,7 @@ public: inline bool isDirty() const { return m_dirty; } inline Qt3DCore::QGeometryFactoryPtr geometryFactory() const { return m_geometryFactory; } void unsetDirty(); + bool hasView() const { return m_hasView; } // Build triangle data Job thread void setTriangleVolumes(const QVector<RayCasting::QBoundingVolume *> &volumes); @@ -117,9 +118,9 @@ private: bool m_primitiveRestartEnabled; QGeometryRenderer::PrimitiveType m_primitiveType; bool m_dirty; + bool m_hasView; Qt3DCore::QGeometryFactoryPtr m_geometryFactory; GeometryRendererManager *m_manager; - QVector<RayCasting::QBoundingVolume *> m_triangleVolumes; }; class GeometryRendererFunctor : public Qt3DCore::QBackendNodeMapper diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp index dc95151c4..b7daddbcb 100644 --- a/src/render/jobs/calcboundingvolumejob.cpp +++ b/src/render/jobs/calcboundingvolumejob.cpp @@ -40,10 +40,14 @@ #include "calcboundingvolumejob_p.h" +#include <Qt3DCore/qboundingvolume.h> +#include <Qt3DCore/qabstractfrontendnodemanager.h> +#include <Qt3DCore/private/qgeometry_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/renderlogging_p.h> #include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/qgeometryrenderer_p.h> #include <Qt3DRender/private/geometryrenderer_p.h> #include <Qt3DRender/private/geometry_p.h> #include <Qt3DRender/private/buffermanager_p.h> @@ -52,8 +56,6 @@ #include <Qt3DRender/private/sphere_p.h> #include <Qt3DRender/private/buffervisitor_p.h> #include <Qt3DRender/private/entityvisitor_p.h> -#include <Qt3DCore/private/qgeometry_p.h> -#include <Qt3DCore/private/qaspectmanager_p.h> #include <QtCore/qmath.h> #if QT_CONFIG(concurrent) @@ -220,34 +222,39 @@ private: struct BoundingVolumeComputeData { Entity *entity = nullptr; + GeometryRenderer *renderer = nullptr; Geometry *geometry = nullptr; Attribute *positionAttribute = nullptr; Attribute *indexAttribute = nullptr; - bool primitiveRestartEnabled = false; - int primitiveRestartIndex = -1; - int vertexCount = 0; + int vertexCount = -1; - bool valid() const { return entity != nullptr; } + bool valid() const { return vertexCount >= 0; } }; BoundingVolumeComputeData findBoundingVolumeComputeData(NodeManagers *manager, Entity *node) { - GeometryRenderer *gRenderer = node->renderComponent<GeometryRenderer>(); + BoundingVolumeComputeData res; + res.entity = node; + + res.renderer = node->renderComponent<GeometryRenderer>(); + if (!res.renderer || res.renderer->primitiveType() == QGeometryRenderer::Patches) + return res; + GeometryManager *geometryManager = manager->geometryManager(); - if (!gRenderer || gRenderer->primitiveType() == QGeometryRenderer::Patches) - return {}; + res.geometry = geometryManager->lookupResource(res.renderer->geometryId()); + if (!res.geometry) + return res; - Geometry *geom = geometryManager->lookupResource(gRenderer->geometryId()); - if (!geom) - return {}; + if (res.renderer->hasView()) + return res; - int drawVertexCount = gRenderer->vertexCount(); // may be 0, gets changed below if so + int drawVertexCount = res.renderer->vertexCount(); // may be 0, gets changed below if so - Qt3DRender::Render::Attribute *positionAttribute = manager->lookupResource<Attribute, AttributeManager>(geom->boundingPositionAttribute()); + Qt3DRender::Render::Attribute *positionAttribute = manager->lookupResource<Attribute, AttributeManager>(res.geometry->boundingPositionAttribute()); // Use the default position attribute if attribute is null if (!positionAttribute) { - const auto attrIds = geom->attributes(); + const auto attrIds = res.geometry->attributes(); for (const Qt3DCore::QNodeId &attrId : attrIds) { positionAttribute = manager->lookupResource<Attribute, AttributeManager>(attrId); if (positionAttribute && @@ -261,20 +268,20 @@ BoundingVolumeComputeData findBoundingVolumeComputeData(NodeManagers *manager, E || positionAttribute->vertexBaseType() != QAttribute::Float || positionAttribute->vertexSize() < 3) { qWarning("findBoundingVolumeComputeData: Position attribute not suited for bounding volume computation"); - return {}; + return res; } Buffer *buf = manager->lookupResource<Buffer, BufferManager>(positionAttribute->bufferId()); // No point in continuing if the positionAttribute doesn't have a suitable buffer if (!buf) { qWarning("findBoundingVolumeComputeData: Position attribute not referencing a valid buffer"); - return {}; + return res; } // Check if there is an index attribute. Qt3DRender::Render::Attribute *indexAttribute = nullptr; Buffer *indexBuf = nullptr; - const QVector<Qt3DCore::QNodeId> attributes = geom->attributes(); + const QVector<Qt3DCore::QNodeId> attributes = res.geometry->attributes(); for (Qt3DCore::QNodeId attrNodeId : attributes) { Qt3DRender::Render::Attribute *attr = manager->lookupResource<Attribute, AttributeManager>(attrNodeId); @@ -296,7 +303,7 @@ BoundingVolumeComputeData findBoundingVolumeComputeData(NodeManagers *manager, E std::end(validIndexTypes), indexAttribute->vertexBaseType()) == std::end(validIndexTypes)) { qWarning() << "findBoundingVolumeComputeData: Unsupported index attribute type" << indexAttribute->name() << indexAttribute->vertexBaseType(); - return {}; + return res; } break; @@ -314,17 +321,16 @@ BoundingVolumeComputeData findBoundingVolumeComputeData(NodeManagers *manager, E if (buf->isDirty() || node->isBoundingVolumeDirty() || positionAttribute->isDirty() - || geom->isDirty() - || gRenderer->isDirty() + || res.geometry->isDirty() + || res.renderer->isDirty() || (indexAttribute && indexAttribute->isDirty()) || (indexBuf && indexBuf->isDirty())) { - return { - node, geom, positionAttribute, indexAttribute, - gRenderer->primitiveRestartEnabled(), gRenderer->restartIndexValue(), drawVertexCount - }; + res.vertexCount = drawVertexCount; + res.positionAttribute = positionAttribute; + res.indexAttribute = indexAttribute; } - return {}; + return res; } QVector<Geometry *> calculateLocalBoundingVolume(NodeManagers *manager, const BoundingVolumeComputeData &data) @@ -336,7 +342,7 @@ QVector<Geometry *> calculateLocalBoundingVolume(NodeManagers *manager, const Bo BoundingVolumeCalculator reader(manager); if (reader.apply(data.positionAttribute, data.indexAttribute, data.vertexCount, - data.primitiveRestartEnabled, data.primitiveRestartIndex)) { + data.renderer->primitiveRestartEnabled(), data.renderer->restartIndexValue())) { data.entity->localBoundingVolume()->setCenter(reader.result().center()); data.entity->localBoundingVolume()->setRadius(reader.result().radius()); data.entity->unsetBoundingVolumeDirty(); @@ -383,49 +389,56 @@ public: if (!entity->isTreeEnabled()) return Prune; auto data = findBoundingVolumeComputeData(m_manager, entity); - if (data.valid()) + + if (data.valid()) { + // only valid if front end is a QGeometryRenderer without a view. All other cases handled by core aspect m_entities.push_back(data); + } else { + if (!data.renderer || data.renderer->primitiveType() == QGeometryRenderer::Patches + || !data.renderer->hasView()) // should have been handled above + return Continue; + + // renderer has a view, we can pull the data from the front end + QBoundingVolume *frontEndBV = qobject_cast<QBoundingVolume *>(m_frontEndNodeManager->lookupNode(data.renderer->peerId())); + if (!frontEndBV) + return Continue; + auto dFrontEndBV = QGeometryRendererPrivate::get(frontEndBV); + + // copy data to the entity + entity->localBoundingVolume()->setCenter(Vector3D(dFrontEndBV->m_implicitCenter)); + entity->localBoundingVolume()->setRadius(dFrontEndBV->m_implicitRadius); + entity->unsetBoundingVolumeDirty(); + // copy the data to the geometry + data.geometry->updateExtent(dFrontEndBV->m_implicitMinPoint, dFrontEndBV->m_implicitMaxPoint); + } + return Continue; } + NodeManagers *m_nodeNanager; + Qt3DCore::QAbstractFrontEndNodeManager *m_frontEndNodeManager = nullptr; std::vector<BoundingVolumeComputeData> m_entities; }; } // anonymous -class CalculateBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate -{ -public: - CalculateBoundingVolumeJobPrivate() { } - ~CalculateBoundingVolumeJobPrivate() override { } - - void postFrame(Qt3DCore::QAspectManager *manager) override - { - for (Geometry *backend : qAsConst(m_updatedGeometries)) { - Qt3DCore::QGeometry *node = qobject_cast<Qt3DCore::QGeometry *>(manager->lookupNode(backend->peerId())); - if (!node) - continue; - Qt3DCore::QGeometryPrivate *dNode = static_cast<Qt3DCore::QGeometryPrivate *>(Qt3DCore::QNodePrivate::get(node)); - dNode->setExtent(backend->min(), backend->max()); - } - - m_updatedGeometries.clear(); - } - - QVector<Geometry *> m_updatedGeometries; -}; CalculateBoundingVolumeJob::CalculateBoundingVolumeJob() - : Qt3DCore::QAspectJob(*new CalculateBoundingVolumeJobPrivate()) + : Qt3DCore::QAspectJob() , m_manager(nullptr) , m_node(nullptr) + , m_frontEndNodeManager(nullptr) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcBoundingVolume, 0) } void CalculateBoundingVolumeJob::run() { + Q_ASSERT(m_frontEndNodeManager); + DirtyEntityAccumulator accumulator(m_manager); + accumulator.m_frontEndNodeManager = m_frontEndNodeManager; + accumulator.m_nodeNanager = m_manager; accumulator.apply(m_node); std::vector<BoundingVolumeComputeData> entities = std::move(accumulator.m_entities); @@ -446,8 +459,21 @@ void CalculateBoundingVolumeJob::run() updatedGeometries += calculateLocalBoundingVolume(m_manager, data); } - Q_D(CalculateBoundingVolumeJob); - d->m_updatedGeometries = std::move(updatedGeometries); + m_updatedGeometries = std::move(updatedGeometries); +} + +void CalculateBoundingVolumeJob::postFrame(QAspectEngine *aspectEngine) +{ + Q_UNUSED(aspectEngine) + for (Geometry *backend : qAsConst(m_updatedGeometries)) { + Qt3DCore::QGeometry *node = qobject_cast<Qt3DCore::QGeometry *>(m_frontEndNodeManager->lookupNode(backend->peerId())); + if (!node) + continue; + Qt3DCore::QGeometryPrivate *dNode = static_cast<Qt3DCore::QGeometryPrivate *>(Qt3DCore::QNodePrivate::get(node)); + dNode->setExtent(backend->min(), backend->max()); + } + + m_updatedGeometries.clear(); } void CalculateBoundingVolumeJob::setRoot(Entity *node) @@ -460,6 +486,11 @@ void CalculateBoundingVolumeJob::setManagers(NodeManagers *manager) m_manager = manager; } +void CalculateBoundingVolumeJob::setFrontEndNodeManager(Qt3DCore::QAbstractFrontEndNodeManager *manager) +{ + m_frontEndNodeManager = manager; +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/jobs/calcboundingvolumejob_p.h b/src/render/jobs/calcboundingvolumejob_p.h index 3f7b8c09c..11392dc0b 100644 --- a/src/render/jobs/calcboundingvolumejob_p.h +++ b/src/render/jobs/calcboundingvolumejob_p.h @@ -59,12 +59,16 @@ QT_BEGIN_NAMESPACE +namespace Qt3DCore { +class QAbstractFrontEndNodeManager; +} + namespace Qt3DRender { namespace Render { class NodeManagers; class Entity; -class CalculateBoundingVolumeJobPrivate; +class Geometry; class Q_3DRENDERSHARED_PRIVATE_EXPORT CalculateBoundingVolumeJob : public Qt3DCore::QAspectJob { @@ -73,12 +77,16 @@ public: void setRoot(Entity *node); void setManagers(NodeManagers *manager); + void setFrontEndNodeManager(Qt3DCore::QAbstractFrontEndNodeManager *manager); void run() override; + void postFrame(Qt3DCore::QAspectEngine *aspectEngine) override; + private: NodeManagers *m_manager; Entity *m_node; - Q_DECLARE_PRIVATE(CalculateBoundingVolumeJob) + Qt3DCore::QAbstractFrontEndNodeManager *m_frontEndNodeManager; + QVector<Geometry *> m_updatedGeometries; }; typedef QSharedPointer<CalculateBoundingVolumeJob> CalculateBoundingVolumeJobPtr; diff --git a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp index 7a05addcd..6fbdee807 100644 --- a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp +++ b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp @@ -36,6 +36,7 @@ #include <Qt3DCore/qtransform.h> #include <Qt3DCore/private/qaspectjobmanager_p.h> #include <Qt3DCore/private/qnodevisitor_p.h> +#include <Qt3DCore/private/calcboundingvolumejob_p.h> #include <QtQuick/qquickwindow.h> #include <Qt3DRender/QCamera> @@ -103,7 +104,7 @@ QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore return nodeTreeChanges; } -class TestAspect : public Qt3DRender::QRenderAspect +class TestAspect : public Qt3DRender::QRenderAspect, public Qt3DCore::QAbstractFrontEndNodeManager { public: TestAspect(Qt3DCore::QNode *root) @@ -111,10 +112,11 @@ public: , m_sceneRoot(nullptr) { QRenderAspect::onRegistered(); + m_root = qobject_cast<Qt3DCore::QEntity *>(root); const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root); const QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges = nodeTreeChangesForNodes(nodes); - d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), nodeTreeChanges); + d_func()->setRootAndCreateNodes(m_root, nodeTreeChanges); Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId()); Q_ASSERT(rootEntity); @@ -126,17 +128,42 @@ public: QRenderAspect::onUnregistered(); } - void onRegistered() { QRenderAspect::onRegistered(); } - void onUnregistered() { QRenderAspect::onUnregistered(); } + void onRegistered() override { QRenderAspect::onRegistered(); } + void onUnregistered() override { QRenderAspect::onUnregistered(); } Qt3DRender::Render::NodeManagers *nodeManagers() const { return d_func()->m_renderer->nodeManagers(); } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); } Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); } + Qt3DCore::QEntity *root() const { return m_root; } Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; } Qt3DRender::Render::AbstractRenderer *renderer() const { return d_func()->m_renderer; } + void registerNode(Qt3DCore::QNode *node) { m_frontEndNodes.insert(node->id(), node); } + void registerTree(Qt3DCore::QEntity *root) { + using namespace Qt3DCore; + QNodeVisitor visitor; + visitor.traverse(root, [](QNode *) {}, [this](QEntity *entity) { + registerNode(entity); + const auto &components = entity->components(); + for (const auto &c : components) + registerNode(c); + }); + } + Qt3DCore::QNode *lookupNode(Qt3DCore::QNodeId id) const override { return m_frontEndNodes.value(id, nullptr); } + QVector<Qt3DCore::QNode *> lookupNodes(const QVector<Qt3DCore::QNodeId> &ids) const override { + QVector<Qt3DCore::QNode *> res; + for (const auto &id: ids) { + auto node = m_frontEndNodes.value(id, nullptr); + if (node) + res.push_back(node); + } + return res; + } + private: + Qt3DCore::QEntity *m_root; Render::Entity *m_sceneRoot; + QHash<Qt3DCore::QNodeId, Qt3DCore::QNode *> m_frontEndNodes; }; } // namespace Qt3DRender @@ -152,10 +179,16 @@ void runRequiredJobs(Qt3DRender::TestAspect *test) updateWorldTransform.setManagers(test->nodeManagers()); updateWorldTransform.run(); - Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; - calcBVolume.setManagers(test->nodeManagers()); - calcBVolume.setRoot(test->sceneRoot()); - calcBVolume.run(); + Qt3DCore::CalculateBoundingVolumeJob calcCBVolume; + calcCBVolume.setRoot(test->root()); + calcCBVolume.run(); + calcCBVolume.postFrame(nullptr); + + Qt3DRender::Render::CalculateBoundingVolumeJob calcRBVolume; + calcRBVolume.setManagers(test->nodeManagers()); + calcRBVolume.setFrontEndNodeManager(test); + calcRBVolume.setRoot(test->sceneRoot()); + calcRBVolume.run(); Qt3DRender::Render::UpdateWorldBoundingVolumeJob updateWorldBVolume; updateWorldBVolume.setManager(test->nodeManagers()->renderNodesManager()); @@ -215,7 +248,7 @@ private Q_SLOTS: auto copiedSphere = firstValidSphere; firstValidSphere.expandToContain(defaultSphere); QVERIFY(firstValidSphere.center() == copiedSphere.center()); - QVERIFY(firstValidSphere.radius() == copiedSphere.radius()); + QCOMPARE(firstValidSphere.radius(), copiedSphere.radius()); QVERIFY(!firstValidSphere.isNull()); } @@ -224,7 +257,7 @@ private Q_SLOTS: auto defaultSphere = Qt3DRender::Render::Sphere(); defaultSphere.expandToContain(firstValidSphere); QVERIFY(defaultSphere.center() == firstValidSphere.center()); - QVERIFY(defaultSphere.radius() == firstValidSphere.radius()); + QCOMPARE(defaultSphere.radius(), firstValidSphere.radius()); QVERIFY(!defaultSphere.isNull()); } @@ -336,6 +369,7 @@ private Q_SLOTS: QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs + test->registerTree(qobject_cast<Qt3DCore::QEntity *>(root.data())); runRequiredJobs(test.data()); // THEN @@ -476,10 +510,18 @@ private Q_SLOTS: entityBackend->setRenderer(test->renderer()); simulateInitializationSync(entity.data(), entityBackend); - Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; - calcBVolume.setManagers(test->nodeManagers()); - calcBVolume.setRoot(test->sceneRoot()); - calcBVolume.run(); + test->registerTree(entity.data()); + + Qt3DCore::CalculateBoundingVolumeJob calcCBVolume; + calcCBVolume.setRoot(test->root()); + calcCBVolume.run(); + calcCBVolume.postFrame(nullptr); + + Qt3DRender::Render::CalculateBoundingVolumeJob calcRBVolume; + calcRBVolume.setManagers(test->nodeManagers()); + calcRBVolume.setRoot(test->sceneRoot()); + calcRBVolume.setFrontEndNodeManager(test.data()); + calcRBVolume.run(); Vector3D center = entityBackend->localBoundingVolume()->center(); float radius = entityBackend->localBoundingVolume()->radius(); @@ -566,7 +608,10 @@ private Q_SLOTS: entityBackend->setRenderer(test->renderer()); simulateInitializationSync(entity.data(), entityBackend); + test->registerTree(entity.data()); + Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; + calcBVolume.setFrontEndNodeManager(test.data()); calcBVolume.setManagers(test->nodeManagers()); calcBVolume.setRoot(test->sceneRoot()); calcBVolume.run(); diff --git a/tests/auto/render/commons/testaspect.h b/tests/auto/render/commons/testaspect.h index dfbe78fbd..22d0a7172 100644 --- a/tests/auto/render/commons/testaspect.h +++ b/tests/auto/render/commons/testaspect.h @@ -41,13 +41,15 @@ #include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DRender/private/abstractrenderer_p.h> #include <Qt3DCore/private/qaspectjobmanager_p.h> +#include <Qt3DCore/private/qnodevisitor_p.h> +#include <Qt3DCore/qabstractfrontendnodemanager.h> #include <Qt3DRender/private/qrenderaspect_p.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { -class TestAspect : public Qt3DRender::QRenderAspect +class TestAspect : public Qt3DRender::QRenderAspect, public Qt3DCore::QAbstractFrontEndNodeManager { public: TestAspect(Qt3DCore::QNode *root); @@ -60,8 +62,31 @@ public: void onRegistered(); void onUnregistered(); + void registerNode(Qt3DCore::QNode *node) { m_frontEndNodes.insert(node->id(), node); } + void registerTree(Qt3DCore::QEntity *root) { + using namespace Qt3DCore; + QNodeVisitor visitor; + visitor.traverse(root, [](QNode *) {}, [this](QEntity *entity) { + registerNode(entity); + const auto &components = entity->components(); + for (const auto &c : components) + registerNode(c); + }); + } + Qt3DCore::QNode *lookupNode(Qt3DCore::QNodeId id) const override { return m_frontEndNodes.value(id, nullptr); } + QVector<Qt3DCore::QNode *> lookupNodes(const QVector<Qt3DCore::QNodeId> &ids) const override { + QVector<Qt3DCore::QNode *> res; + for (const auto &id: ids) { + auto node = m_frontEndNodes.value(id, nullptr); + if (node) + res.push_back(node); + } + return res; + } + private: QScopedPointer<Qt3DCore::QAspectJobManager> m_jobManager; + QHash<Qt3DCore::QNodeId, Qt3DCore::QNode *> m_frontEndNodes; }; } // Qt3DRender diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index cd984cfac..fb61e4105 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -32,12 +32,14 @@ #include <QtTest/QTest> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qtransform.h> +#include <Qt3DCore/qabstractfrontendnodemanager.h> #include <Qt3DCore/private/qaspectjobmanager_p.h> #include <Qt3DCore/private/qnodevisitor_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/private/qaspectengine_p.h> #include <Qt3DCore/private/qaspectjob_p.h> +#include <Qt3DCore/private/calcboundingvolumejob_p.h> #include <QtQuick/qquickwindow.h> #include <Qt3DRender/QCamera> @@ -112,7 +114,7 @@ QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore return nodeTreeChanges; } -class TestAspect : public Qt3DRender::QRenderAspect +class TestAspect : public Qt3DRender::QRenderAspect, public Qt3DCore::QAbstractFrontEndNodeManager { public: TestAspect(Qt3DCore::QNode *root) @@ -124,6 +126,7 @@ public: Q_ASSERT(d_func()->m_aspectManager); // do what QAspectEngine::setRootEntity does since we don't want to enter the simulation loop + m_root = qobject_cast<Qt3DCore::QEntity *>(root); Qt3DCore::QEntityPtr proot(qobject_cast<Qt3DCore::QEntity *>(root), [](Qt3DCore::QEntity *) { }); Qt3DCore::QAspectEnginePrivate *aed = Qt3DCore::QAspectEnginePrivate::get(m_engine); aed->m_root = proot; @@ -135,6 +138,8 @@ public: Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId()); Q_ASSERT(rootEntity); m_sceneRoot = rootEntity; + + registerTree(m_root); } ~TestAspect() @@ -158,12 +163,37 @@ public: Qt3DRender::Render::NodeManagers *nodeManagers() const { return d_func()->m_renderer->nodeManagers(); } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); } Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); } + Qt3DCore::QEntity *root() const { return m_root; } Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; } Qt3DCore::QAspectManager *aspectManager() const { return d_func()->m_aspectManager; } Qt3DCore::QChangeArbiter *arbiter() const { return d_func()->m_arbiter; } + + void registerNode(Qt3DCore::QNode *node) { m_frontEndNodes.insert(node->id(), node); } + void registerTree(Qt3DCore::QEntity *root) { + using namespace Qt3DCore; + QNodeVisitor visitor; + visitor.traverse(root, [](QNode *) {}, [this](QEntity *entity) { + registerNode(entity); + const auto &components = entity->components(); + for (const auto &c : components) + registerNode(c); + }); + } + Qt3DCore::QNode *lookupNode(Qt3DCore::QNodeId id) const override { return m_frontEndNodes.value(id, nullptr); } + QVector<Qt3DCore::QNode *> lookupNodes(const QVector<Qt3DCore::QNodeId> &ids) const override { + QVector<Qt3DCore::QNode *> res; + for (const auto &id: ids) { + auto node = m_frontEndNodes.value(id, nullptr); + if (node) + res.push_back(node); + } + return res; + } private: Qt3DCore::QAspectEngine *m_engine; + Qt3DCore::QEntity *m_root; Render::Entity *m_sceneRoot; + QHash<Qt3DCore::QNodeId, Qt3DCore::QNode *> m_frontEndNodes; }; } // namespace Qt3DRender @@ -179,10 +209,16 @@ void runRequiredJobs(Qt3DRender::TestAspect *test) updateWorldTransform.setManagers(test->nodeManagers()); updateWorldTransform.run(); - Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; - calcBVolume.setManagers(test->nodeManagers()); - calcBVolume.setRoot(test->sceneRoot()); - calcBVolume.run(); + Qt3DCore::CalculateBoundingVolumeJob calcCBVolume; + calcCBVolume.setRoot(test->root()); + calcCBVolume.run(); + calcCBVolume.postFrame(nullptr); + + Qt3DRender::Render::CalculateBoundingVolumeJob calcRBVolume; + calcRBVolume.setManagers(test->nodeManagers()); + calcRBVolume.setFrontEndNodeManager(test); + calcRBVolume.setRoot(test->sceneRoot()); + calcRBVolume.run(); Qt3DRender::Render::UpdateWorldBoundingVolumeJob updateWorldBVolume; updateWorldBVolume.setManager(test->nodeManagers()->renderNodesManager()); diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp index ee0be6647..a64f5de71 100644 --- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp +++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp @@ -291,6 +291,7 @@ private Q_SLOTS: // GIVEN QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(entitySubtree)); + aspect->registerTree(entitySubtree); // WHEN Qt3DRender::Render::Entity *backendRoot = aspect->nodeManagers()->renderNodesManager()->getOrCreateResource(entitySubtree->id()); @@ -308,6 +309,7 @@ private Q_SLOTS: Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; calcBVolume.setManagers(aspect->nodeManagers()); calcBVolume.setRoot(backendRoot); + calcBVolume.setFrontEndNodeManager(aspect.data()); calcBVolume.run(); Qt3DRender::Render::UpdateWorldBoundingVolumeJob updateWorldBVolume; diff --git a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp index 0f466b4d4..5c8a1d76f 100644 --- a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp +++ b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp @@ -32,12 +32,14 @@ #include <QtTest/QTest> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qtransform.h> +#include <Qt3DCore/qabstractfrontendnodemanager.h> #include <Qt3DCore/private/qaspectjobmanager_p.h> #include <Qt3DCore/private/qnodevisitor_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/private/qaspectengine_p.h> #include <Qt3DCore/private/qaspectjob_p.h> +#include <Qt3DCore/private/calcboundingvolumejob_p.h> #include <QtQuick/qquickwindow.h> #include <Qt3DRender/QCamera> @@ -104,7 +106,7 @@ QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore return nodeTreeChanges; } -class TestAspect : public Qt3DRender::QRenderAspect +class TestAspect : public Qt3DRender::QRenderAspect, public Qt3DCore::QAbstractFrontEndNodeManager { public: TestAspect(Qt3DCore::QNode *root) @@ -116,7 +118,8 @@ public: Q_ASSERT(d_func()->m_aspectManager); // do what QAspectEngine::setRootEntity does since we don't want to enter the simulation loop - Qt3DCore::QEntityPtr proot(qobject_cast<Qt3DCore::QEntity *>(root), [](Qt3DCore::QEntity *) { }); + m_root = qobject_cast<Qt3DCore::QEntity *>(root); + Qt3DCore::QEntityPtr proot(m_root, [](Qt3DCore::QEntity *) { }); Qt3DCore::QAspectEnginePrivate *aed = Qt3DCore::QAspectEnginePrivate::get(m_engine); aed->m_root = proot; aed->initialize(); @@ -127,6 +130,8 @@ public: Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId()); Q_ASSERT(rootEntity); m_sceneRoot = rootEntity; + + registerTree(m_root); } ~TestAspect() @@ -150,13 +155,39 @@ public: Qt3DRender::Render::NodeManagers *nodeManagers() const { return d_func()->m_renderer->nodeManagers(); } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); } Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); } + Qt3DCore::QEntity *root() const { return m_root; } Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; } Qt3DCore::QAspectManager *aspectManager() const { return d_func()->m_aspectManager; } Qt3DCore::QAspectEngine *aspectEngine() const { return m_engine; } Qt3DCore::QChangeArbiter *arbiter() const { return d_func()->m_arbiter; } + + void registerNode(Qt3DCore::QNode *node) { m_frontEndNodes.insert(node->id(), node); } + void registerTree(Qt3DCore::QEntity *root) { + using namespace Qt3DCore; + QNodeVisitor visitor; + visitor.traverse(root, [](QNode *) {}, [this](QEntity *entity) { + registerNode(entity); + const auto &components = entity->components(); + for (const auto &c : components) + registerNode(c); + }); + } + Qt3DCore::QNode *lookupNode(Qt3DCore::QNodeId id) const override { return m_frontEndNodes.value(id, nullptr); } + QVector<Qt3DCore::QNode *> lookupNodes(const QVector<Qt3DCore::QNodeId> &ids) const override { + QVector<Qt3DCore::QNode *> res; + for (const auto &id: ids) { + auto node = m_frontEndNodes.value(id, nullptr); + if (node) + res.push_back(node); + } + return res; + } + private: Qt3DCore::QAspectEngine *m_engine; + Qt3DCore::QEntity *m_root; Render::Entity *m_sceneRoot; + QHash<Qt3DCore::QNodeId, Qt3DCore::QNode *> m_frontEndNodes; }; } // namespace Qt3DRender @@ -176,10 +207,16 @@ void runRequiredJobs(Qt3DRender::TestAspect *test) updateWorldTransform.setManagers(test->nodeManagers()); updateWorldTransform.run(); - Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; - calcBVolume.setManagers(test->nodeManagers()); - calcBVolume.setRoot(test->sceneRoot()); - calcBVolume.run(); + Qt3DCore::CalculateBoundingVolumeJob calcCBVolume; + calcCBVolume.setRoot(test->root()); + calcCBVolume.run(); + calcCBVolume.postFrame(nullptr); + + Qt3DRender::Render::CalculateBoundingVolumeJob calcRBVolume; + calcRBVolume.setManagers(test->nodeManagers()); + calcRBVolume.setFrontEndNodeManager(test); + calcRBVolume.setRoot(test->sceneRoot()); + calcRBVolume.run(); Qt3DRender::Render::UpdateWorldBoundingVolumeJob updateWorldBVolume; updateWorldBVolume.setManager(test->nodeManagers()->renderNodesManager()); @@ -254,6 +291,9 @@ private Q_SLOTS: // Runs Required jobs runRequiredJobs(test.data()); + // Clear changed nodes + test->arbiter()->takeDirtyFrontEndNodes(); + Qt3DRender::Render::RayCaster *backendRayCaster = test->nodeManagers()->rayCasterManager()->lookupResource(rayCaster->id()); QVERIFY(backendRayCaster); @@ -270,6 +310,7 @@ private Q_SLOTS: QVERIFY(!backendRayCaster->isEnabled()); QVERIFY(!rayCaster->isEnabled()); auto dirtyNodes = test->arbiter()->takeDirtyFrontEndNodes(); + qDebug() << dirtyNodes; QCOMPARE(dirtyNodes.count(), 1); // hits & disable QCOMPARE(rayCaster->hits().size(), numIntersections); @@ -313,6 +354,9 @@ private Q_SLOTS: // Runs Required jobs runRequiredJobs(test.data()); + // Clear changed nodes + test->arbiter()->takeDirtyFrontEndNodes(); + Qt3DRender::Render::RayCaster *backendRayCaster = test->nodeManagers()->rayCasterManager()->lookupResource(rayCaster->id()); QVERIFY(backendRayCaster); |