summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-10-15 09:40:09 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-10-15 09:40:40 +0200
commit7339e9ae93df3720e1b936dd027d821105020bc4 (patch)
treef563b7cf4e02ad8a0628fb228733dc841f8ca554
parentfd85ebb1e24d48ffdff0659810a1830691bba89f (diff)
parent7628760f8f16aba7769c04f2251633faa9fbcad1 (diff)
Merge remote-tracking branch 'origin/5.13' into 5.14
-rw-r--r--src/animation/frontend/qabstractclipanimator.cpp22
-rw-r--r--src/animation/frontend/qblendedclipanimator.cpp1
-rw-r--r--src/animation/frontend/qclipanimator.cpp1
-rw-r--r--src/plugins/sceneparsers/sceneparsers.pro2
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp4
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindow.cpp3
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.cpp4
-rw-r--r--src/render/backend/abstractrenderer_p.h3
-rw-r--r--src/render/backend/offscreensurfacehelper.cpp1
-rw-r--r--src/render/backend/platformsurfacefilter.cpp4
-rw-r--r--src/render/frontend/qcomputecommand.cpp2
-rw-r--r--src/render/frontend/qrenderaspect.cpp1
-rw-r--r--src/render/frontend/qrenderaspect_p.h2
-rw-r--r--src/render/frontend/sphere.cpp50
-rw-r--r--src/render/frontend/sphere_p.h13
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp78
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp4
-rw-r--r--src/render/materialsystem/qeffect.cpp4
-rw-r--r--src/render/materialsystem/qfilterkey.cpp4
-rw-r--r--src/render/materialsystem/qparameter.cpp4
-rw-r--r--src/render/materialsystem/qtechnique.cpp4
-rw-r--r--src/render/picking/qobjectpicker.cpp6
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp14
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h4
-rw-r--r--src/render/renderstates/qrenderstate.cpp1
-rw-r--r--tests/auto/render/boundingsphere/tst_boundingsphere.cpp172
-rw-r--r--tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp38
27 files changed, 386 insertions, 60 deletions
diff --git a/src/animation/frontend/qabstractclipanimator.cpp b/src/animation/frontend/qabstractclipanimator.cpp
index b2f6f817f..cb4621182 100644
--- a/src/animation/frontend/qabstractclipanimator.cpp
+++ b/src/animation/frontend/qabstractclipanimator.cpp
@@ -125,6 +125,11 @@ QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Q
QAbstractClipAnimator::~QAbstractClipAnimator()
{
}
+/*!
+ \qmlproperty bool Qt3DAnimation::AbstractClipAnimator::running
+
+ This property holds a boolean indicating whether the animation is currently running.
+*/
/*!
\property Qt3DAnimation::QAbstractClipAnimator::running
@@ -142,6 +147,13 @@ bool QAbstractClipAnimator::isRunning() const
}
/*!
+ \qmlproperty ChannelMapper Qt3DAnimation::AbstractClipAnimator::channelMapper
+
+ This property holds the ChannelMapper that controls how the channels in
+ the animation clip map onto the properties of the target objects.
+*/
+
+/*!
\property Qt3DAnimation::QAbstractClipAnimator::channelMapper
This property holds the ChannelMapper that controls how the channels in
@@ -199,6 +211,12 @@ int QAbstractClipAnimator::loopCount() const
return d->m_loops;
}
/*!
+ \qmlproperty Clock Qt3DAnimation::AbstractClipAnimator::clock
+
+ The clock controls the speed with which an animation is played.
+*/
+
+/*!
\property Qt3DAnimation::QAbstractClipAnimator::clock
The clock controls the speed with which an animation is played.
@@ -208,7 +226,11 @@ QClock *QAbstractClipAnimator::clock() const
Q_D(const QAbstractClipAnimator);
return d->m_clock;
}
+/*!
+ \qmlproperty real Qt3DAnimation::AbstractClipAnimator::normalizedTime
+ This property holds the clips normalized time.
+*/
/*!
\property Qt3DAnimation::QAbstractClipAnimator::normalizedTime
diff --git a/src/animation/frontend/qblendedclipanimator.cpp b/src/animation/frontend/qblendedclipanimator.cpp
index 388144c81..c48706606 100644
--- a/src/animation/frontend/qblendedclipanimator.cpp
+++ b/src/animation/frontend/qblendedclipanimator.cpp
@@ -56,6 +56,7 @@ QBlendedClipAnimatorPrivate::QBlendedClipAnimatorPrivate()
\qmltype BlendedClipAnimator
\instantiates Qt3DAnimation::QBlendedClipAnimator
\inqmlmodule Qt3D.Animation
+ \inherits AbstractClipAnimator
\since 5.9
\brief BlendedClipAnimator is a component providing animation playback capabilities of a tree
diff --git a/src/animation/frontend/qclipanimator.cpp b/src/animation/frontend/qclipanimator.cpp
index 398758820..03510aa93 100644
--- a/src/animation/frontend/qclipanimator.cpp
+++ b/src/animation/frontend/qclipanimator.cpp
@@ -66,6 +66,7 @@ bool QClipAnimatorPrivate::canPlay() const
\qmltype ClipAnimator
\instantiates Qt3DAnimation::QClipAnimator
\inqmlmodule Qt3D.Animation
+ \inherits AbstractClipAnimator
\since 5.9
\brief ClipAnimator is a component providing simple animation playback capabilities.
diff --git a/src/plugins/sceneparsers/sceneparsers.pro b/src/plugins/sceneparsers/sceneparsers.pro
index 9bb0ada36..e57bcac22 100644
--- a/src/plugins/sceneparsers/sceneparsers.pro
+++ b/src/plugins/sceneparsers/sceneparsers.pro
@@ -2,7 +2,7 @@ TEMPLATE = subdirs
# QNX is not supported, and Linux GCC 4.9 on ARM chokes on the assimp
# sources (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66964).
QT_FOR_CONFIG += 3dcore-private
-qtConfig(assimp):if(qtConfig(system-assimp)|android-clang|gcc:greaterThan(QT_GCC_MAJOR_VERSION, 4)): {
+!ios:!tvos:!qcc:qtConfig(assimp):if(qtConfig(system-assimp)|android-clang|clang|win32-msvc)|if(gcc:greaterThan(QT_GCC_MAJOR_VERSION, 4)) {
SUBDIRS += assimp
}
SUBDIRS += gltf
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index 098cab032..02e8447c7 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -529,6 +529,7 @@ void Scene3DItem::setWindowSurface(QObject *rootObject)
m_dummySurface = new QOffscreenSurface;
m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living
m_dummySurface->setFormat(rw->format());
+ m_dummySurface->setScreen(rw->screen());
m_dummySurface->create();
surfaceSelector->setSurface(m_dummySurface);
} else {
@@ -616,6 +617,9 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
// If the render aspect wasn't created yet, do so now
if (m_renderAspect == nullptr) {
m_renderAspect = new QRenderAspect(QRenderAspect::Synchronous);
+ auto *rw = QQuickRenderControl::renderWindowFor(window());
+ static_cast<Qt3DRender::QRenderAspectPrivate *>(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect))->m_screen =
+ (rw ? rw->screen() : window()->screen());
m_aspectEngine->registerAspect(m_renderAspect);
// Before Synchronizing is in the SG Thread, we want beforeSync to be triggered
diff --git a/src/quick3d/quick3dextras/qt3dquickwindow.cpp b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
index bc4bb25ee..d67dfdc71 100644
--- a/src/quick3d/quick3dextras/qt3dquickwindow.cpp
+++ b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
@@ -66,6 +66,7 @@
#include <Qt3DQuickExtras/private/qt3dquickwindowlogging_p.h>
#include <Qt3DRender/private/qrendersurfaceselector_p.h>
+#include <Qt3DRender/private/qrenderaspect_p.h>
QT_BEGIN_NAMESPACE
@@ -132,6 +133,8 @@ Qt3DQuickWindow::Qt3DQuickWindow(QWindow *parent)
QSurfaceFormat::setDefaultFormat(format);
d->m_renderAspect = new Qt3DRender::QRenderAspect;
+ if (parent && parent->screen())
+ static_cast<Qt3DRender::QRenderAspectPrivate*>(Qt3DRender::QRenderAspectPrivate::get(d->m_renderAspect))->m_screen = parent->screen();
d->m_inputAspect = new Qt3DInput::QInputAspect;
d->m_logicAspect = new Qt3DLogic::QLogicAspect;
d->m_engine = new Qt3DCore::Quick::QQmlAspectEngine;
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.cpp b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
index ef06f39f1..8908894c8 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d.cpp
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
@@ -70,6 +70,8 @@ namespace Quick {
with the item; if an entity has a QObjectPicker component, the pick events from that picker
are sent to the QScene2D and converted to mouse events and finally sent to the item.
+ \note Only mouse events are supported. The item does not support keyboard input.
+
\since 5.9
*/
@@ -91,6 +93,8 @@ namespace Quick {
with the item; if an entity has an ObjectPicker component, the pick events from that picker
are sent to the Scene2D and converted to mouse events and finally sent to the item.
+ \note Only mouse events are supported. The item does not support keyboard input.
+
Usage:
\qml
Entity {
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index 006919512..b618eda55 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
class QSurface;
class QSize;
+class QScreen;
namespace Qt3DCore {
class QAbstractFrameAdvanceService;
@@ -175,6 +176,8 @@ public:
// For QtQuick rendering
virtual void setOpenGLContext(QOpenGLContext *ctx) = 0;
+ virtual void setScreen(QScreen *) {}
+ virtual QScreen *screen() const { return nullptr; }
virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0;
virtual QSurfaceFormat format() = 0;
diff --git a/src/render/backend/offscreensurfacehelper.cpp b/src/render/backend/offscreensurfacehelper.cpp
index 89dc6211f..38558d484 100644
--- a/src/render/backend/offscreensurfacehelper.cpp
+++ b/src/render/backend/offscreensurfacehelper.cpp
@@ -72,6 +72,7 @@ void OffscreenSurfaceHelper::createOffscreenSurface()
m_offscreenSurface = new QOffscreenSurface;
m_offscreenSurface->setParent(this);
m_offscreenSurface->setFormat(m_renderer->format());
+ m_offscreenSurface->setScreen(m_renderer->screen());
m_offscreenSurface->create();
}
diff --git a/src/render/backend/platformsurfacefilter.cpp b/src/render/backend/platformsurfacefilter.cpp
index 7458f607d..891e30c44 100644
--- a/src/render/backend/platformsurfacefilter.cpp
+++ b/src/render/backend/platformsurfacefilter.cpp
@@ -107,10 +107,6 @@ bool PlatformSurfaceFilter::eventFilter(QObject *obj, QEvent *e)
// If we remove it, the call to isSurfaceValid will
// implicitely return false
PlatformSurfaceFilter::m_surfacesValidity.remove(m_surface);
- if (m_obj) {
- m_obj->removeEventFilter(this);
- m_obj = nullptr;
- }
break;
}
diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp
index d040150d5..d0c9f5805 100644
--- a/src/render/frontend/qcomputecommand.cpp
+++ b/src/render/frontend/qcomputecommand.cpp
@@ -66,7 +66,7 @@ namespace Qt3DRender {
/*!
\qmltype ComputeCommand
\since 5.7
- \inmodule Qt3DRender
+ \inqmlmodule Qt3D.Render
\inherits Component3D
\instantiates Qt3DRender::QComputeCommand
\brief Component to issue work for the compute shader on GPU.
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index 159c11981..271eb9c11 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -562,6 +562,7 @@ void QRenderAspect::onRegistered()
// TO DO: Load proper Renderer class based on Qt configuration preferences
d->m_renderer = new Render::Renderer(d->m_renderType);
+ d->m_renderer->setScreen(d->m_screen);
d->m_renderer->setNodeManagers(d->m_nodeManagers);
// Create a helper for deferring creation of an offscreen surface used during cleanup
diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h
index 8ef4ecd12..62e373b11 100644
--- a/src/render/frontend/qrenderaspect_p.h
+++ b/src/render/frontend/qrenderaspect_p.h
@@ -60,6 +60,7 @@
QT_BEGIN_NAMESPACE
class QSurface;
+class QScreen;
namespace Qt3DRender {
@@ -106,6 +107,7 @@ public:
QVector<Render::QRenderPlugin *> m_renderPlugins;
QRenderAspect::RenderType m_renderType;
Render::OffscreenSurfaceHelper *m_offscreenHelper;
+ QScreen *m_screen = nullptr;
static QMutex m_pluginLock;
static QVector<QString> m_pluginConfig;
diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp
index 4909acaef..470dbfe59 100644
--- a/src/render/frontend/sphere.cpp
+++ b/src/render/frontend/sphere.cpp
@@ -44,6 +44,7 @@
#include <QPair>
#include <math.h>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -55,6 +56,9 @@ namespace {
// returns true and intersection point q; false otherwise
bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRender::Render::Sphere &s, Vector3D *q = nullptr)
{
+ if (s.isNull())
+ return false;
+
const Vector3D p = ray.origin();
const Vector3D d = ray.direction();
const Vector3D m = p - s.center();
@@ -139,11 +143,31 @@ inline void sphereFromExtremePoints(Qt3DRender::Render::Sphere &s, const QVector
inline void constructRitterSphere(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points)
{
- // Calculate the sphere encompassing two axially extreme points
- sphereFromExtremePoints(s, points);
-
- // Now make sure the sphere bounds all points by growing if needed
- s.expandToContain(points);
+ //def bounding_sphere(points):
+ // dist = lambda a,b: ((a[0] - b[0])**2 + (a[1] - b[1])**2 + (a[2] - b[2])**2)**0.5
+ // x = points[0]
+ // y = max(points,key= lambda p: dist(p,x) )
+ // z = max(points,key= lambda p: dist(p,y) )
+ // bounding_sphere = (((y[0]+z[0])/2,(y[1]+z[1])/2,(y[2]+z[2])/2), dist(y,z)/2)
+ //
+ // exterior_points = [p for p in points if dist(p,bounding_sphere[0]) > bounding_sphere[1] ]
+ // while ( len(exterior_points) > 0 ):
+ // pt = exterior_points.pop()
+ // if (dist(pt, bounding_sphere[0]) > bounding_sphere[1]):
+ // bounding_sphere = (bounding_sphere[0],dist(pt,bounding_sphere[0]))
+ //
+ // return bounding_sphere
+
+ const Vector3D x = points[0];
+ const Vector3D y = *std::max_element(points.begin(), points.end(), [&x](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - x).lengthSquared() < (rhs - x).lengthSquared(); });
+ const Vector3D z = *std::max_element(points.begin(), points.end(), [&y](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - y).lengthSquared() < (rhs - y).lengthSquared(); });
+
+ const Vector3D center = (y + z) * 0.5f;
+ const Vector3D maxDistPt = *std::max_element(points.begin(), points.end(), [&center](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - center).lengthSquared() < (rhs - center).lengthSquared(); });
+ const float radius = (maxDistPt - center).length();
+
+ s.setCenter(center);
+ s.setRadius(radius);
}
} // anonymous namespace
@@ -169,6 +193,12 @@ void Sphere::initializeFromPoints(const QVector<Vector3D> &points)
void Sphere::expandToContain(const Vector3D &p)
{
+ if (isNull()) {
+ m_center = p;
+ m_radius = 0.0f;
+ return;
+ }
+
const Vector3D d = p - m_center;
const float dist2 = d.lengthSquared();
@@ -184,6 +214,13 @@ void Sphere::expandToContain(const Vector3D &p)
void Sphere::expandToContain(const Sphere &sphere)
{
+ if (isNull()) {
+ *this = sphere;
+ return;
+ } else if (sphere.isNull()) {
+ return;
+ }
+
const Vector3D d(sphere.m_center - m_center);
const float dist2 = d.lengthSquared();
@@ -206,6 +243,9 @@ void Sphere::expandToContain(const Sphere &sphere)
Sphere Sphere::transformed(const Matrix4x4 &mat) const
{
+ if (isNull())
+ return *this;
+
// Transform extremities in x, y, and z directions to find extremities
// of the resulting ellipsoid
Vector3D x = mat.map(m_center + Vector3D(m_radius, 0.0f, 0.0f));
diff --git a/src/render/frontend/sphere_p.h b/src/render/frontend/sphere_p.h
index 10cf92091..b7585f85a 100644
--- a/src/render/frontend/sphere_p.h
+++ b/src/render/frontend/sphere_p.h
@@ -69,7 +69,7 @@ class Q_3DRENDERSHARED_PRIVATE_EXPORT Sphere : public RayCasting::BoundingSphere
public:
inline Sphere(Qt3DCore::QNodeId i = Qt3DCore::QNodeId())
: m_center()
- , m_radius(0.0f)
+ , m_radius(-1.0f)
, m_id(i)
{}
@@ -82,7 +82,7 @@ public:
void setCenter(const Vector3D &c);
Vector3D center() const override;
- inline bool isNull() { return m_center == Vector3D() && m_radius == 0.0f; }
+ bool isNull() const { return m_center == Vector3D() && m_radius == -1.0f; }
void setRadius(float r);
float radius() const override;
@@ -131,7 +131,9 @@ inline Vector3D Sphere::center() const
inline void Sphere::setRadius(float r)
{
- m_radius = r;
+ Q_ASSERT(r >= 0.0f);
+ if (r >= 0.0f)
+ m_radius = r;
}
inline float Sphere::radius() const
@@ -142,11 +144,14 @@ inline float Sphere::radius() const
inline void Sphere::clear()
{
m_center = Vector3D();
- m_radius = 0.0f;
+ m_radius = -1.0f;
}
inline bool intersects(const Sphere &a, const Sphere &b)
{
+ if (a.isNull() || b.isNull())
+ return false;
+
// Calculate squared distance between sphere centers
const Vector3D d = a.center() - b.center();
const float distSq = Vector3D::dotProduct(d, d);
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp
index 113dc34ce..9af2f4f38 100644
--- a/src/render/jobs/calcboundingvolumejob.cpp
+++ b/src/render/jobs/calcboundingvolumejob.cpp
@@ -90,30 +90,42 @@ public:
m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
- // Calculate squared distance for the pairs of points
- const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared();
- const float yDist2 = (findExtremePoints.yMaxPt - findExtremePoints.yMinPt).lengthSquared();
- const float zDist2 = (findExtremePoints.zMaxPt - findExtremePoints.zMinPt).lengthSquared();
-
- // Select most distant pair
- Vector3D p = findExtremePoints.xMinPt;
- Vector3D q = findExtremePoints.xMaxPt;
- if (yDist2 > xDist2 && yDist2 > zDist2) {
- p = findExtremePoints.yMinPt;
- q = findExtremePoints.yMaxPt;
+ FindMaxDistantPoint maxDistantPointY(m_manager);
+ maxDistantPointY.setReferencePoint = true;
+ if (!maxDistantPointY.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
}
- if (zDist2 > xDist2 && zDist2 > yDist2) {
- p = findExtremePoints.zMinPt;
- q = findExtremePoints.zMaxPt;
+ if (maxDistantPointY.hasNoPoints)
+ return false;
+
+ //const Vector3D x = maxDistantPointY.referencePt;
+ const Vector3D y = maxDistantPointY.maxDistPt;
+
+ FindMaxDistantPoint maxDistantPointZ(m_manager);
+ maxDistantPointZ.setReferencePoint = false;
+ maxDistantPointZ.referencePt = y;
+ if (!maxDistantPointZ.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
+ }
+ const Vector3D z = maxDistantPointZ.maxDistPt;
+
+ const Vector3D center = (y + z) * 0.5f;
+
+ FindMaxDistantPoint maxDistantPointCenter(m_manager);
+ maxDistantPointCenter.setReferencePoint = false;
+ maxDistantPointCenter.referencePt = center;
+ if (!maxDistantPointCenter.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
}
- const Vector3D c = 0.5f * (p + q);
- m_volume.setCenter(c);
- m_volume.setRadius((q - c).length());
+ const float radius = (center - maxDistantPointCenter.maxDistPt).length();
- ExpandSphere expandSphere(m_manager, m_volume);
- if (!expandSphere.apply(positionAttribute, indexAttribute, drawVertexCount,
- primitiveRestartEnabled, primitiveRestartIndex))
+ m_volume = Qt3DRender::Render::Sphere(center, radius);
+
+ if (m_volume.isNull())
return false;
return true;
@@ -172,18 +184,34 @@ private:
}
};
- class ExpandSphere : public Buffer3fVisitor
+ class FindMaxDistantPoint : public Buffer3fVisitor
{
public:
- ExpandSphere(NodeManagers *manager, Sphere& volume)
- : Buffer3fVisitor(manager), m_volume(volume)
+ FindMaxDistantPoint(NodeManagers *manager)
+ : Buffer3fVisitor(manager)
{ }
- Sphere& m_volume;
+ float maxLengthSquared = 0.0f;
+ Vector3D maxDistPt;
+ Vector3D referencePt;
+ bool setReferencePoint = false;
+ bool hasNoPoints = true;
+
void visit(uint ndx, float x, float y, float z) override
{
Q_UNUSED(ndx);
- m_volume.expandToContain(Vector3D(x, y, z));
+ const Vector3D p = Vector3D(x, y, z);
+
+ if (hasNoPoints && setReferencePoint) {
+ maxLengthSquared = 0.0f;
+ referencePt = p;
+ }
+ const float lengthSquared = (p - referencePt).lengthSquared();
+ if ( lengthSquared >= maxLengthSquared ) {
+ maxDistPt = p;
+ maxLengthSquared = lengthSquared;
+ }
+ hasNoPoints = false;
}
};
};
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index 9d8d3e491..2973ee100 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -202,12 +202,12 @@ void PickBoundingVolumeJob::setRoot(Entity *root)
void PickBoundingVolumeJob::setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents)
{
- m_pendingMouseEvents = pendingEvents;
+ m_pendingMouseEvents.append(pendingEvents);
}
void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents)
{
- m_pendingKeyEvents = pendingEvents;
+ m_pendingKeyEvents.append(pendingEvents);
}
void PickBoundingVolumeJob::markPickersDirty()
diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp
index 35f4d64a9..6f5ff09e6 100644
--- a/src/render/materialsystem/qeffect.cpp
+++ b/src/render/materialsystem/qeffect.cpp
@@ -65,6 +65,8 @@ QEffectPrivate::QEffectPrivate()
An QEffect instance should be shared among several QMaterial instances when possible.
+ \note QEffect node can not be disabled.
+
\code
QEffect *effect = new QEffect();
@@ -111,6 +113,8 @@ QEffectPrivate::QEffectPrivate()
A Parameter defined on an Effect is overridden by a QParameter (of the same
name) defined in a Material, TechniqueFilter, RenderPassFilter.
+ \note Effect node can not be disabled.
+
\code
Effect {
id: effect
diff --git a/src/render/materialsystem/qfilterkey.cpp b/src/render/materialsystem/qfilterkey.cpp
index dc968400b..2105da987 100644
--- a/src/render/materialsystem/qfilterkey.cpp
+++ b/src/render/materialsystem/qfilterkey.cpp
@@ -60,6 +60,8 @@ QFilterKeyPrivate::QFilterKeyPrivate()
Filter keys are used by QTechnique and QRenderPass to specify at which stage of rendering the
technique or the render pass is used.
+
+ \note QFilterKey node can not be disabled.
*/
/*!
@@ -73,6 +75,8 @@ QFilterKeyPrivate::QFilterKeyPrivate()
A FilterKey is a storage type for filter key and value pair.
Filter keys are used by Technique and RenderPass to specify at which stage of rendering the
technique or the render pass is used.
+
+ \note FilterKey node can not be disabled.
*/
QFilterKey::QFilterKey(QNode *parent)
diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp
index 77eda8c8e..969882564 100644
--- a/src/render/materialsystem/qparameter.cpp
+++ b/src/render/materialsystem/qparameter.cpp
@@ -76,6 +76,8 @@
\note when the targeted uniform is an array, the name should be the name
of the uniform with [0] appended to it.
+ \note Parameter node can not be disabled.
+
\code
Parameter {
name: "diffuseValues[0]"
@@ -138,6 +140,8 @@
\note when the targeted uniform is an array, the name should be the name
of the uniform with [0] appended to it.
+ \note QParameter node can not be disabled.
+
\code
QParameter *param = new QParameter();
QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp
index 2b96aa285..5ebaefce7 100644
--- a/src/render/materialsystem/qtechnique.cpp
+++ b/src/render/materialsystem/qtechnique.cpp
@@ -87,6 +87,8 @@ QTechniquePrivate::~QTechniquePrivate()
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
will likely have no effect on Qt3D related rendering.
+ \note Technique node can not be disabled.
+
\qml
Technique {
id: gl3Technique
@@ -152,6 +154,8 @@ QTechniquePrivate::~QTechniquePrivate()
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
will likely have no effect on Qt3D related rendering.
+ \note QTechnique node can not be disabled.
+
\code
QTechnique *gl3Technique = new QTechnique();
diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp
index 0c667806c..7d9741f21 100644
--- a/src/render/picking/qobjectpicker.cpp
+++ b/src/render/picking/qobjectpicker.cpp
@@ -82,6 +82,9 @@ namespace Qt3DRender {
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
+ \note The camera far plane value affects picking and produces incorrect results due to
+ floating-point precision if it is greater than ~100 000.
+
\since 5.6
*/
@@ -115,6 +118,9 @@ namespace Qt3DRender {
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
+
+ \note The camera far plane value affects picking and produces incorrect results due to
+ floating-point precision if it is greater than ~100 000.
*/
/*!
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index c3e986854..9dfdf7d06 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -347,6 +347,16 @@ void Renderer::setOpenGLContext(QOpenGLContext *context)
m_glContext = context;
}
+void Renderer::setScreen(QScreen *scr)
+{
+ m_screen = scr;
+}
+
+QScreen *Renderer::screen() const
+{
+ return m_screen;
+}
+
// Called in RenderThread context by the run method of RenderThread
// RenderThread has locked the mutex already and unlocks it when this
// method termintates
@@ -364,6 +374,8 @@ void Renderer::initialize()
// we need to create it
if (!m_glContext) {
ctx = new QOpenGLContext;
+ if (m_screen)
+ ctx->setScreen(m_screen);
ctx->setShareContext(qt_gl_global_share_context());
// TO DO: Shouldn't we use the highest context available and trust
@@ -393,6 +405,8 @@ void Renderer::initialize()
if (!ctx->shareContext()) {
m_shareContext = new QOpenGLContext;
+ if (ctx->screen())
+ m_shareContext->setScreen(ctx->screen());
m_shareContext->setFormat(ctx->format());
m_shareContext->setShareContext(ctx);
m_shareContext->create();
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index 29aece008..b1cd4aac5 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -106,6 +106,7 @@ QT_BEGIN_NAMESPACE
class QSurface;
class QMouseEvent;
+class QScreen;
namespace Qt3DCore {
class QEntity;
@@ -293,6 +294,8 @@ public:
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
RendererCache *cache() { return &m_cache; }
+ void setScreen(QScreen *scr) override;
+ QScreen *screen() const override;
#ifdef QT3D_RENDER_UNIT_TESTS
public:
@@ -426,6 +429,7 @@ private:
bool m_shouldSwapBuffers;
QVector<FrameGraphNode *> m_frameGraphLeaves;
+ QScreen *m_screen = nullptr;
};
} // namespace Render
diff --git a/src/render/renderstates/qrenderstate.cpp b/src/render/renderstates/qrenderstate.cpp
index 8a7d897be..cd5346710 100644
--- a/src/render/renderstates/qrenderstate.cpp
+++ b/src/render/renderstates/qrenderstate.cpp
@@ -59,6 +59,7 @@ namespace Qt3DRender {
/*!
\qmltype RenderState
+ \inqmlmodule Qt3D.Render
\brief An abstract base type for all render states.
\since 5.7
\inherits Node
diff --git a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
index 80298780a..34d195221 100644
--- a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
+++ b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
@@ -204,13 +204,150 @@ class tst_BoundingSphere : public Qt3DCore::QBackendNodeTester
private:
private Q_SLOTS:
+ void checkIsNull() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ QVERIFY(defaultSphere.isNull());
+ }
+
+ void remainsNotNullAfterTransform() {
+ QMatrix4x4 mat;
+ mat.translate(-5,-5,-5);
+ auto mMat = Matrix4x4(mat);
+ auto pointSphere = Qt3DRender::Render::Sphere(Vector3D(5.f,5.f,5.f),0.f);
+ pointSphere.transform(mMat);
+ QVERIFY(!pointSphere.isNull());
+ QVERIFY(pointSphere.center() == Vector3D(0.,0.,0));
+ QVERIFY(pointSphere.radius() == 0.f);
+ }
+
+ void remainsNullAfterTransform() {
+ QMatrix4x4 mat;
+ mat.translate(-5,-5,-5);
+ auto mMat = Matrix4x4(mat);
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.transform(mMat);
+ QVERIFY(defaultSphere.isNull());
+ }
+
+ void expandToContainSphere() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ auto secondValidSphere = Qt3DRender::Render::Sphere(Vector3D(10.f,10.f,10.f),1.f);
+ firstValidSphere.expandToContain(secondValidSphere);
+ QVERIFY(firstValidSphere.center()==Vector3D(0.f,0.f,0.f));
+ float dist = static_cast<float>((2 + sqrt(3.*(20)*(20)))/2.);
+ QVERIFY(qFuzzyCompare(firstValidSphere.radius(), dist));
+ }
+
+ void expandToContainSphereOneInvalid() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ auto copiedSphere = firstValidSphere;
+ firstValidSphere.expandToContain(defaultSphere);
+ QVERIFY(firstValidSphere.center() == copiedSphere.center());
+ QVERIFY(firstValidSphere.radius() == copiedSphere.radius());
+ QVERIFY(!firstValidSphere.isNull());
+ }
+
+ void expandToContainOtherSphereInvalid() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(firstValidSphere);
+ QVERIFY(defaultSphere.center() == firstValidSphere.center());
+ QVERIFY(defaultSphere.radius() == firstValidSphere.radius());
+ QVERIFY(!defaultSphere.isNull());
+ }
+
+ void expandNullSphereWithNullSphere() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ auto otherDefaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(otherDefaultSphere);
+ QVERIFY(defaultSphere.isNull());
+ }
+
+ void expandToContainPoint() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ firstValidSphere.expandToContain(Vector3D(0,0,0));
+ QVERIFY(!firstValidSphere.isNull());
+ float expectedRadius = static_cast<float>((1 + qSqrt(3.*(10)*(10)))/2.);
+ QVERIFY(qFuzzyCompare(firstValidSphere.radius(), expectedRadius));
+ }
+
+ void nullSphereExpandToContainPoint() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(Vector3D(5,5,5));
+ QVERIFY(!defaultSphere.isNull());
+ QVERIFY(defaultSphere.center() == Vector3D(5,5,5));
+ QVERIFY(qFuzzyIsNull(defaultSphere.radius()));
+ }
+
+ void nullSphereExpandToOrigin() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(Vector3D(0,0,0));
+ QVERIFY(!defaultSphere.isNull());
+ QVERIFY(defaultSphere.center() == Vector3D(0,0,0));
+ QVERIFY(qFuzzyIsNull(defaultSphere.radius()));
+ }
+
+ void ritterSphereCubePoints() {
+ QVector<Vector3D> cubePts={
+ Vector3D(-0.5, -0.5, 0.5),
+ Vector3D( 0.5, -0.5, -0.5),
+ Vector3D(-0.5, 0.5, -0.5),
+ Vector3D( 0.5, 0.5, -0.5),
+ Vector3D(-0.5, -0.5, -0.5),
+ Vector3D( 0.5, -0.5, 0.5),
+ Vector3D(-0.5, 0.5, 0.5),
+ Vector3D( 0.5, 0.5, 0.5)
+ };
+ auto ritterSphere=Qt3DRender::Render::Sphere::fromPoints(cubePts);
+ QVERIFY(!ritterSphere.isNull());
+ QVERIFY(qFuzzyIsNull(ritterSphere.center().x()));
+ QVERIFY(qFuzzyIsNull(ritterSphere.center().y()));
+ QVERIFY(qFuzzyIsNull(ritterSphere.center().z()));
+ QVERIFY(qFuzzyCompare(ritterSphere.radius(), static_cast<float>(qSqrt(3)/2)));
+ }
+
+ void ritterSphereRandomPoints() {
+ QVector<Vector3D> randomPts={
+ Vector3D(-81, 55, 46),
+ Vector3D(-91, -73, -42),
+ Vector3D(-50, -76, -77),
+ Vector3D(-40, 63, 58),
+ Vector3D(-28, -2, -57),
+ Vector3D(84, 17, 33),
+ Vector3D(53, 11, -49),
+ Vector3D(-7, -24, -86),
+ Vector3D(-89, 6, 76),
+ Vector3D(46, -18, -27)
+ };
+
+ auto ritterSphere = Qt3DRender::Render::Sphere::fromPoints(randomPts);
+ QVERIFY(!ritterSphere.isNull());
+ QVERIFY(qFuzzyCompare(ritterSphere.center().x(), 17.f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().y(), -29.5f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().z(), -22.0f));
+ QVERIFY(qFuzzyCompare(ritterSphere.radius(), 148.66152831179963f));
+ }
+
+ void ritterSphereOnePoint() {
+ QVector<Vector3D> singlePt={
+ Vector3D(-0.5, -0.5, -0.5),
+ };
+ auto ritterSphere = Qt3DRender::Render::Sphere::fromPoints(singlePt);
+ QVERIFY(!ritterSphere.isNull());
+ QVERIFY(qFuzzyCompare(ritterSphere.center().x(), -0.5f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().y(), -0.5f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().z(), -0.5f));
+ QVERIFY(qFuzzyIsNull(ritterSphere.radius()));
+ }
+
void checkExtraGeometries_data()
{
QTest::addColumn<QString>("qmlFile");
QTest::addColumn<QVector3D>("sphereCenter");
QTest::addColumn<float>("sphereRadius");
QTest::newRow("SphereMesh") << "qrc:/sphere.qml" << QVector3D(0.f, 0.f, 0.f) << 1.f;
- QTest::newRow("CubeMesh") << "qrc:/cube.qml" << QVector3D(0.0928356f, -0.212021f, -0.0467958f) << 1.07583f; // weird!
+ QTest::newRow("CubeMesh") << "qrc:/cube.qml" << QVector3D(0.f, 0.f, 0.f) << static_cast<float>(qSqrt(3.)/2.); // not weird at all
}
void checkExtraGeometries()
@@ -235,9 +372,10 @@ private Q_SLOTS:
const auto boundingSphere = test->sceneRoot()->worldBoundingVolumeWithChildren();
qDebug() << qmlFile << boundingSphere->radius() << boundingSphere->center();
QCOMPARE(boundingSphere->radius(), sphereRadius);
- QVERIFY(qAbs(boundingSphere->center().x() - sphereCenter.x()) < 0.000001f); // qFuzzyCompare hates 0s
- QVERIFY(qAbs(boundingSphere->center().y() - sphereCenter.y()) < 0.000001f);
- QVERIFY(qAbs(boundingSphere->center().z() - sphereCenter.z()) < 0.000001f);
+
+ QVERIFY(qFuzzyIsNull(boundingSphere->center().x() - sphereCenter.x()));
+ QVERIFY(qFuzzyIsNull(boundingSphere->center().y() - sphereCenter.y()));
+ QVERIFY(qFuzzyIsNull(boundingSphere->center().z() - sphereCenter.z()));
}
void checkCustomGeometry_data()
@@ -247,10 +385,10 @@ private Q_SLOTS:
QTest::addColumn<QVector3D>("expectedCenter");
QTest::addColumn<float>("expectedRadius");
QTest::addColumn<bool>("withPrimitiveRestart");
- QTest::newRow("all") << 0 << 0 << QVector3D(-0.488892f, 0.0192147f, -75.4804f) << 25.5442f << false;
+ QTest::newRow("all") << 0 << 0 << QVector3D(0.0f, 0.0f, -75.0f) << 25.03997f << false;
QTest::newRow("first only") << 3 << 0 << QVector3D(0, 1, -100) << 1.0f << false;
QTest::newRow("second only") << 3 << int(3 * sizeof(ushort)) << QVector3D(0, -1, -50) << 1.0f << false;
- QTest::newRow("all with primitive restart") << 0 << 0 << QVector3D(-0.488892f, 0.0192147f, -75.4804f) << 25.5442f << true;
+ QTest::newRow("all with primitive restart") << 0 << 0 << QVector3D(0.0f, 0.0f, -75.0f) << 25.03997f << true;
QTest::newRow("first only with primitive restart") << 4 << 0 << QVector3D(0, 1, -100) << 1.0f << true;
QTest::newRow("second only with primitive restart") << 4 << int(3 * sizeof(ushort)) << QVector3D(0, -1, -50) << 1.0f << true;
}
@@ -376,18 +514,17 @@ private Q_SLOTS:
float radius = entityBackend->localBoundingVolume()->radius();
qDebug() << radius << center;
- // truncate and compare integers only
- QCOMPARE(int(radius), int(expectedRadius));
- QCOMPARE(int(center.x()), int(expectedCenter.x()));
- QCOMPARE(int(center.y()), int(expectedCenter.y()));
- QCOMPARE(int(center.z()), int(expectedCenter.z()));
+ QCOMPARE(radius, expectedRadius);
+ QCOMPARE(center.x(), expectedCenter.x());
+ QCOMPARE(center.y(), expectedCenter.y());
+ QCOMPARE(center.z(), expectedCenter.z());
}
void checkCustomPackedGeometry()
{
int drawVertexCount = 6;
- QVector3D expectedCenter(-0.488892f, 0.0192147f, -75.4804f);
- float expectedRadius = 25.5442f;
+ QVector3D expectedCenter(0.0f, 0.0f, -75.0f);
+ float expectedRadius = 25.03997f;
// two triangles with different Z
QByteArray vdata;
@@ -467,11 +604,10 @@ private Q_SLOTS:
float radius = entityBackend->localBoundingVolume()->radius();
qDebug() << radius << center;
- // truncate and compare integers only
- QVERIFY(int(radius) == int(expectedRadius));
- QVERIFY(int(center.x()) == int(expectedCenter.x()));
- QVERIFY(int(center.y()) == int(expectedCenter.y()));
- QVERIFY(int(center.z()) == int(expectedCenter.z()));
+ QCOMPARE(radius, expectedRadius);
+ QCOMPARE(center.x(), expectedCenter.x());
+ QCOMPARE(center.y(), expectedCenter.y());
+ QCOMPARE(center.z(), expectedCenter.z());
}
};
diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
index 07adf12b5..1bed9fc44 100644
--- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
+++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
@@ -29,6 +29,10 @@
#include <QtTest/QTest>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
+#include <Qt3DRender/qgeometry.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/entity_p.h>
@@ -43,6 +47,40 @@ namespace {
Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *parent)
{
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(parent);
+
+ // create geometry with a valid bounding volume - a single point is sufficient
+ auto geometry = new Qt3DRender::QGeometry;
+ auto vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, geometry);
+
+ auto positionAttribute = new Qt3DRender::QAttribute;
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setByteStride(3 * sizeof(float));
+ positionAttribute->setBuffer(vertexBuffer);
+
+ QByteArray vertexBufferData;
+ vertexBufferData.resize(static_cast<int>(3 * sizeof(float)));
+
+ auto vertexArray = reinterpret_cast<float*>(vertexBufferData.data());
+
+ int i = 0;
+ vertexArray[i++] = 0.0f;
+ vertexArray[i++] = 0.0f;
+ vertexArray[i++] = 0.0f;
+
+ vertexBuffer->setData(vertexBufferData);
+ positionAttribute->setCount(1);
+
+ geometry->addAttribute(positionAttribute);
+
+ auto geometryRenderer = new Qt3DRender::QGeometryRenderer;
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Points);
+ geometryRenderer->setGeometry(geometry);
+
+ entity->addComponent(geometryRenderer);
+
Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(parent);
const QVector3D t = QVector3D(1.0f, 0.0f, 0.0f) * distance;