diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2018-02-05 13:01:09 +0000 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2018-02-05 15:42:29 +0000 |
commit | 0403ee45736241aa621eb3d38880a4fff571fd96 (patch) | |
tree | 94650145a3b7e2517dfcf29d33f97859933b518d /src/render/jobs | |
parent | 04afcf1cb9e79697360baa01a97a26815237eba1 (diff) | |
parent | ceae743678d41a58154612781e896c04c87a8c4f (diff) |
Merge remote-tracking branch 'origin/5.9' into 5.10
Conflicts:
.qmake.conf
src/render/backend/trianglesvisitor.cpp
src/render/backend/uniform.cpp
src/render/jobs/calcboundingvolumejob.cpp
src/render/jobs/pickboundingvolumejob.cpp
src/render/jobs/pickboundingvolumeutils.cpp
Change-Id: Ib8305011c51710a3538c0b29f7022388f5244a38
Diffstat (limited to 'src/render/jobs')
-rw-r--r-- | src/render/jobs/calcboundingvolumejob.cpp | 59 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumejob.cpp | 64 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumejob_p.h | 12 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumeutils.cpp | 34 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumeutils_p.h | 13 | ||||
-rw-r--r-- | src/render/jobs/updatelevelofdetailjob.cpp | 4 |
6 files changed, 127 insertions, 59 deletions
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp index 7504b4ebd..aaee51e16 100644 --- a/src/render/jobs/calcboundingvolumejob.cpp +++ b/src/render/jobs/calcboundingvolumejob.cpp @@ -81,10 +81,10 @@ public: const Sphere& result() { return m_volume; } - bool apply(Qt3DRender::Render::Attribute *positionAttribute) + bool apply(Qt3DRender::Render::Attribute *positionAttribute, Qt3DRender::Render::Attribute *indexAttribute, int drawVertexCount) { FindExtremePoints findExtremePoints(m_manager); - if (!findExtremePoints.apply(positionAttribute)) + if (!findExtremePoints.apply(positionAttribute, indexAttribute, drawVertexCount)) return false; // Calculate squared distance for the pairs of points @@ -109,7 +109,7 @@ public: m_volume.setRadius((q - c).length()); ExpandSphere expandSphere(m_manager, m_volume); - if (!expandSphere.apply(positionAttribute)) + if (!expandSphere.apply(positionAttribute, indexAttribute, drawVertexCount)) return false; return true; @@ -191,10 +191,12 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node) return; GeometryRenderer *gRenderer = node->renderComponent<GeometryRenderer>(); - if (gRenderer) { + if (gRenderer && gRenderer->primitiveType() != QGeometryRenderer::Patches) { Geometry *geom = manager->lookupResource<Geometry, GeometryManager>(gRenderer->geometryId()); if (geom) { + int drawVertexCount = gRenderer->vertexCount(); // may be 0, gets changed below if so + Qt3DRender::Render::Attribute *positionAttribute = manager->lookupResource<Attribute, AttributeManager>(geom->boundingPositionAttribute()); // Use the default position attribute if attribute is null @@ -212,29 +214,60 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node) || positionAttribute->attributeType() != QAttribute::VertexAttribute || positionAttribute->vertexBaseType() != QAttribute::Float || positionAttribute->vertexSize() < 3) { - qWarning() << "QGeometry::boundingVolumePositionAttribute position Attribute not suited for bounding volume computation"; + qWarning("calculateLocalBoundingVolume: Position attribute not suited for bounding volume computation"); return; } Buffer *buf = manager->lookupResource<Buffer, BufferManager>(positionAttribute->bufferId()); // No point in continuing if the positionAttribute doesn't have a suitable buffer if (!buf) { - qWarning() << "ObjectPicker position Attribute not referencing a valid buffer"; + qWarning("calculateLocalBoundingVolume: Position attribute not referencing a valid buffer"); return; } + // Check if there is an index attribute. + Qt3DRender::Render::Attribute *indexAttribute = nullptr; + Buffer *indexBuf = nullptr; + const QVector<Qt3DCore::QNodeId> attributes = geom->attributes(); + + for (Qt3DCore::QNodeId attrNodeId : attributes) { + Qt3DRender::Render::Attribute *attr = manager->lookupResource<Attribute, AttributeManager>(attrNodeId); + if (attr && attr->attributeType() == Qt3DRender::QAttribute::IndexAttribute) { + indexBuf = manager->lookupResource<Buffer, BufferManager>(attr->bufferId()); + if (indexBuf) { + indexAttribute = attr; + + if (!drawVertexCount) + drawVertexCount = indexAttribute->count(); + + if (indexAttribute->vertexBaseType() != QAttribute::UnsignedShort + && indexAttribute->vertexBaseType() != QAttribute::UnsignedInt) + { + qWarning("calculateLocalBoundingVolume: Unsupported index attribute type"); + return; + } + + break; + } + } + } + + if (!indexAttribute && !drawVertexCount) + drawVertexCount = positionAttribute->count(); + // Buf will be set to not dirty once it's loaded // in a job executed after this one // We need to recompute the bounding volume // If anything in the GeometryRenderer has changed - if (buf->isDirty() || - node->isBoundingVolumeDirty() || - positionAttribute->isDirty() || - geom->isDirty() || - gRenderer->isDirty()) { - + if (buf->isDirty() + || node->isBoundingVolumeDirty() + || positionAttribute->isDirty() + || geom->isDirty() + || gRenderer->isDirty() + || (indexAttribute && indexAttribute->isDirty()) + || (indexBuf && indexBuf->isDirty())) { BoundingVolumeCalculator reader(manager); - if (reader.apply(positionAttribute)) { + if (reader.apply(positionAttribute, indexAttribute, drawVertexCount)) { node->localBoundingVolume()->setCenter(reader.result().center()); node->localBoundingVolume()->setRadius(reader.result().radius()); node->unsetBoundingVolumeDirty(); diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 902c048e6..23a553084 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -54,6 +54,10 @@ #include <Qt3DRender/private/qpickevent_p.h> #include <Qt3DRender/private/pickboundingvolumeutils_p.h> +#include <QSurface> +#include <QWindow> +#include <QOffscreenSurface> + QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -119,7 +123,7 @@ void PickBoundingVolumeJob::setRoot(Entity *root) m_node = root; } -void PickBoundingVolumeJob::setMouseEvents(const QList<QMouseEvent> &pendingEvents) +void PickBoundingVolumeJob::setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents) { m_pendingMouseEvents = pendingEvents; } @@ -185,8 +189,8 @@ bool PickBoundingVolumeJob::runHelper() bool hasMoveEvent = false; bool hasOtherEvent = false; // Quickly look which types of events we've got - for (const QMouseEvent &event : mouseEvents) { - const bool isMove = (event.type() == QEvent::MouseMove); + for (const auto &event : mouseEvents) { + const bool isMove = (event.second.type() == QEvent::MouseMove); hasMoveEvent |= isMove; hasOtherEvent |= !isMove; } @@ -214,10 +218,10 @@ bool PickBoundingVolumeJob::runHelper() PickingUtils::ViewportCameraAreaGatherer vcaGatherer; // TO DO: We could cache this and only gather when we know the FrameGraph tree has changed - const QVector<PickingUtils::ViewportCameraAreaTriplet> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); + const QVector<PickingUtils::ViewportCameraAreaDetails> vcaDetails = vcaGatherer.gather(m_frameGraphRoot); // If we have no viewport / camera or area, return early - if (vcaTriplets.empty()) + if (vcaDetails.empty()) return false; // TO DO: @@ -236,19 +240,21 @@ bool PickBoundingVolumeJob::runHelper() const float pickWorldSpaceTolerance = m_renderSettings->pickWorldSpaceTolerance(); // For each mouse event - for (const QMouseEvent &event : mouseEvents) { + for (const auto &event : mouseEvents) { m_hoveredPickersToClear = m_hoveredPickers; QPickEvent::Buttons eventButton = QPickEvent::NoButton; int eventButtons = 0; int eventModifiers = QPickEvent::NoModifier; - setEventButtonAndModifiers(event, eventButton, eventButtons, eventModifiers); + setEventButtonAndModifiers(event.second, eventButton, eventButtons, eventModifiers); - // For each triplet of Viewport / Camera and Area - for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) { + // For each Viewport / Camera and Area entry + for (const PickingUtils::ViewportCameraAreaDetails &vca : vcaDetails) { PickingUtils::HitList sphereHits; - QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId); + QRay3D ray = rayForViewportAndCamera(vca, event.first, event.second); + if (!ray.isValid()) + continue; PickingUtils::HierarchicalEntityPicker entityPicker(ray); if (entityPicker.collectHits(m_node)) { @@ -285,7 +291,7 @@ bool PickBoundingVolumeJob::runHelper() } // Dispatch events based on hit results - dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, allHitsRequested); + dispatchPickEvents(event.second, sphereHits, eventButton, eventButtons, eventModifiers, allHitsRequested); } } @@ -479,7 +485,7 @@ void PickBoundingVolumeJob::viewMatrixForCamera(Qt3DCore::QNodeId cameraId, if (camNode != nullptr && (lens = camNode->renderComponent<CameraLens>()) != nullptr && lens->isEnabled()) { - viewMatrix = *camNode->worldTransform(); + viewMatrix = lens->viewMatrix(*camNode->worldTransform()); projectionMatrix = lens->projection(); } } @@ -497,18 +503,38 @@ QRect PickBoundingVolumeJob::windowViewport(const QSize &area, const QRectF &rel return relativeViewport.toRect(); } -RayCasting::QRay3D PickBoundingVolumeJob::rayForViewportAndCamera(const QSize &area, - const QPoint &pos, - const QRectF &relativeViewport, - const Qt3DCore::QNodeId cameraId) const +RayCasting::QRay3D PickBoundingVolumeJob::rayForViewportAndCamera(const PickingUtils::ViewportCameraAreaDetails &vca, + QObject *eventSource, + const QMouseEvent &event) const { + static RayCasting::QRay3D invalidRay({}, {}, 0.f); + Matrix4x4 viewMatrix; Matrix4x4 projectionMatrix; - viewMatrixForCamera(cameraId, viewMatrix, projectionMatrix); - const QRect viewport = windowViewport(area, relativeViewport); + viewMatrixForCamera(vca.cameraId, viewMatrix, projectionMatrix); + const QRect viewport = windowViewport(vca.area, vca.viewport); + const QPoint pos = event.pos(); + + if (vca.area.isValid() && !viewport.contains(pos)) + return invalidRay; + if (vca.surface) { + QSurface *surface = nullptr; + if (eventSource) { + QWindow *window = qobject_cast<QWindow *>(eventSource); + if (window) { + surface = static_cast<QSurface *>(window); + } else { + QOffscreenSurface *offscreen = qobject_cast<QOffscreenSurface *>(eventSource); + if (offscreen) + surface = static_cast<QSurface *>(offscreen); + } + } + if (surface && vca.surface != surface) + return invalidRay; + } // In GL the y is inverted compared to Qt - const QPoint glCorrectPos = QPoint(pos.x(), area.isValid() ? area.height() - pos.y() : pos.y()); + const QPoint glCorrectPos = QPoint(pos.x(), vca.area.isValid() ? vca.area.height() - pos.y() : pos.y()); const auto ray = intersectionRay(glCorrectPos, viewMatrix, projectionMatrix, viewport); return ray; } diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h index 5d4f63f77..016d1ba0b 100644 --- a/src/render/jobs/pickboundingvolumejob_p.h +++ b/src/render/jobs/pickboundingvolumejob_p.h @@ -56,6 +56,7 @@ #include <Qt3DRender/private/handle_types_p.h> #include <Qt3DRender/private/qboundingvolumeprovider_p.h> #include <Qt3DRender/private/qcollisionqueryresult_p.h> +#include <Qt3DRender/private/pickboundingvolumeutils_p.h> #include <Qt3DRender/qpickevent.h> #include <QMouseEvent> #include <QKeyEvent> @@ -85,7 +86,7 @@ public: PickBoundingVolumeJob(); void setRoot(Entity *root); - void setMouseEvents(const QList<QMouseEvent> &pendingEvents); + void setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents); void setKeyEvents(const QList<QKeyEvent> &pendingEvents); void setFrameGraphRoot(FrameGraphNode *frameGraphRoot); void setRenderSettings(RenderSettings *settings); @@ -117,7 +118,7 @@ private: Entity *m_node; FrameGraphNode *m_frameGraphRoot; RenderSettings *m_renderSettings; - QList<QMouseEvent> m_pendingMouseEvents; + QList<QPair<QObject*, QMouseEvent>> m_pendingMouseEvents; bool m_pickersDirty; bool m_oneEnabledAtLeast; bool m_oneHoverAtLeast; @@ -128,10 +129,9 @@ private: Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix) const; QRect windowViewport(const QSize &area, const QRectF &relativeViewport) const; - RayCasting::QRay3D rayForViewportAndCamera(const QSize &area, - const QPoint &pos, - const QRectF &relativeViewport, - const Qt3DCore::QNodeId cameraId) const; + RayCasting::QRay3D rayForViewportAndCamera(const PickingUtils::ViewportCameraAreaDetails &vca, + QObject *eventSource, + const QMouseEvent &event) const; void clearPreviouslyHoveredPickers(); HObjectPicker m_currentPicker; QVector<HObjectPicker> m_hoveredPickers; diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp index ae80b0a23..fb45d563f 100644 --- a/src/render/jobs/pickboundingvolumeutils.cpp +++ b/src/render/jobs/pickboundingvolumeutils.cpp @@ -72,9 +72,9 @@ void ViewportCameraAreaGatherer::visit(FrameGraphNode *node) m_leaves.push_back(node); } -ViewportCameraAreaTriplet ViewportCameraAreaGatherer::gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const +ViewportCameraAreaDetails ViewportCameraAreaGatherer::gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const { - ViewportCameraAreaTriplet vca; + ViewportCameraAreaDetails vca; vca.viewport = QRectF(0.0f, 0.0f, 1.0f, 1.0f); while (node) { @@ -86,9 +86,12 @@ ViewportCameraAreaTriplet ViewportCameraAreaGatherer::gatherUpViewportCameraArea case FrameGraphNode::Viewport: vca.viewport = computeViewport(vca.viewport, static_cast<const ViewportNode *>(node)); break; - case FrameGraphNode::Surface: - vca.area = static_cast<const RenderSurfaceSelector *>(node)->renderTargetSize(); + case FrameGraphNode::Surface: { + auto selector = static_cast<const RenderSurfaceSelector *>(node); + vca.area = selector->renderTargetSize(); + vca.surface = selector->surface(); break; + } default: break; } @@ -98,29 +101,32 @@ ViewportCameraAreaTriplet ViewportCameraAreaGatherer::gatherUpViewportCameraArea return vca; } -QVector<ViewportCameraAreaTriplet> ViewportCameraAreaGatherer::gather(FrameGraphNode *root) +QVector<ViewportCameraAreaDetails> ViewportCameraAreaGatherer::gather(FrameGraphNode *root) { // Retrieve all leaves visit(root); - QVector<ViewportCameraAreaTriplet> vcaTriplets; + QVector<ViewportCameraAreaDetails> vcaTriplets; vcaTriplets.reserve(m_leaves.count()); // Find all viewport/camera pairs by traversing from leaf to root for (Render::FrameGraphNode *leaf : qAsConst(m_leaves)) { - ViewportCameraAreaTriplet vcaTriplet = gatherUpViewportCameraAreas(leaf); - if (!m_targetCamera.isNull() && vcaTriplet.cameraId != m_targetCamera) + ViewportCameraAreaDetails vcaDetails = gatherUpViewportCameraAreas(leaf); + if (!m_targetCamera.isNull() && vcaDetails.cameraId != m_targetCamera) continue; - if (!vcaTriplet.cameraId.isNull() && isUnique(vcaTriplets, vcaTriplet)) - vcaTriplets.push_back(vcaTriplet); + if (!vcaDetails.cameraId.isNull() && isUnique(vcaTriplets, vcaDetails)) + vcaTriplets.push_back(vcaDetails); } return vcaTriplets; } -bool ViewportCameraAreaGatherer::isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets, - const ViewportCameraAreaTriplet &vca) const +bool ViewportCameraAreaGatherer::isUnique(const QVector<ViewportCameraAreaDetails> &vcaList, + const ViewportCameraAreaDetails &vca) const { - for (const ViewportCameraAreaTriplet &triplet : vcaTriplets) { - if (vca.cameraId == triplet.cameraId && vca.viewport == triplet.viewport && vca.area == triplet.area) + for (const ViewportCameraAreaDetails &listItem : vcaList) { + if (vca.cameraId == listItem.cameraId && + vca.viewport == listItem.viewport && + vca.surface == listItem.surface && + vca.area == listItem.area) return false; } return true; diff --git a/src/render/jobs/pickboundingvolumeutils_p.h b/src/render/jobs/pickboundingvolumeutils_p.h index 6e2532ea5..9cd6a5bbc 100644 --- a/src/render/jobs/pickboundingvolumeutils_p.h +++ b/src/render/jobs/pickboundingvolumeutils_p.h @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE +class QSurface; + namespace Qt3DRender { namespace RayCasting { class QAbstractCollisionQueryService; @@ -72,27 +74,28 @@ class NodeManagers; namespace PickingUtils { -struct Q_AUTOTEST_EXPORT ViewportCameraAreaTriplet +struct Q_AUTOTEST_EXPORT ViewportCameraAreaDetails { Qt3DCore::QNodeId cameraId; QRectF viewport; QSize area; + QSurface *surface = nullptr; }; -QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, PickingUtils, ViewportCameraAreaTriplet, Q_PRIMITIVE_TYPE) +QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, PickingUtils, ViewportCameraAreaDetails, Q_PRIMITIVE_TYPE) class Q_AUTOTEST_EXPORT ViewportCameraAreaGatherer { public: ViewportCameraAreaGatherer(const Qt3DCore::QNodeId &nodeId = Qt3DCore::QNodeId()) : m_targetCamera(nodeId) { } - QVector<ViewportCameraAreaTriplet> gather(FrameGraphNode *root); + QVector<ViewportCameraAreaDetails> gather(FrameGraphNode *root); private: Qt3DCore::QNodeId m_targetCamera; QVector<FrameGraphNode *> m_leaves; void visit(FrameGraphNode *node); - ViewportCameraAreaTriplet gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const; - bool isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets, const ViewportCameraAreaTriplet &vca) const; + ViewportCameraAreaDetails gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const; + bool isUnique(const QVector<ViewportCameraAreaDetails> &vcaList, const ViewportCameraAreaDetails &vca) const; }; class Q_AUTOTEST_EXPORT EntityGatherer diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp index ad9bee8e1..141d65c22 100644 --- a/src/render/jobs/updatelevelofdetailjob.cpp +++ b/src/render/jobs/updatelevelofdetailjob.cpp @@ -175,11 +175,11 @@ void UpdateLevelOfDetailJob::updateEntityLodByScreenArea(Entity *entity, LevelOf return; PickingUtils::ViewportCameraAreaGatherer vcaGatherer(lod->camera()); - const QVector<PickingUtils::ViewportCameraAreaTriplet> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); + const QVector<PickingUtils::ViewportCameraAreaDetails> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); if (vcaTriplets.isEmpty()) return; - const PickingUtils::ViewportCameraAreaTriplet &vca = vcaTriplets.front(); + const PickingUtils::ViewportCameraAreaDetails &vca = vcaTriplets.front(); const QVector<qreal> thresholds = lod->thresholds(); Sphere bv(Vector3D(lod->center()), lod->radius()); |