summaryrefslogtreecommitdiffstats
path: root/src/render/jobs
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2018-02-05 13:01:09 +0000
committerSean Harmer <sean.harmer@kdab.com>2018-02-05 15:42:29 +0000
commit0403ee45736241aa621eb3d38880a4fff571fd96 (patch)
tree94650145a3b7e2517dfcf29d33f97859933b518d /src/render/jobs
parent04afcf1cb9e79697360baa01a97a26815237eba1 (diff)
parentceae743678d41a58154612781e896c04c87a8c4f (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.cpp59
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp64
-rw-r--r--src/render/jobs/pickboundingvolumejob_p.h12
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp34
-rw-r--r--src/render/jobs/pickboundingvolumeutils_p.h13
-rw-r--r--src/render/jobs/updatelevelofdetailjob.cpp4
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());