summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/qt3d/scene3d/AnimatedEntity.qml6
-rw-r--r--examples/qt3d/scene3d/main.qml21
-rw-r--r--src/core/geometry/qgeometryview.cpp2
-rw-r--r--src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp2
-rw-r--r--src/render/frontend/qrenderaspect.cpp10
-rw-r--r--src/render/geometry/geometryrenderer.cpp18
-rw-r--r--src/render/geometry/geometryrenderer_p.h3
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp135
-rw-r--r--src/render/jobs/calcboundingvolumejob_p.h12
-rw-r--r--tests/auto/render/boundingsphere/tst_boundingsphere.cpp73
-rw-r--r--tests/auto/render/commons/testaspect.h27
-rw-r--r--tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp46
-rw-r--r--tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp2
-rw-r--r--tests/auto/render/raycastingjob/tst_raycastingjob.cpp56
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);