mirror of https://github.com/qt/qt3d.git
Merge "Merge remote-tracking branch 'origin/5.13' into 5.14"
This commit is contained in:
commit
0ff2215bb0
|
|
@ -125,6 +125,11 @@ QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Q
|
||||||
QAbstractClipAnimator::~QAbstractClipAnimator()
|
QAbstractClipAnimator::~QAbstractClipAnimator()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
/*!
|
||||||
|
\qmlproperty bool Qt3DAnimation::AbstractClipAnimator::running
|
||||||
|
|
||||||
|
This property holds a boolean indicating whether the animation is currently running.
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\property Qt3DAnimation::QAbstractClipAnimator::running
|
\property Qt3DAnimation::QAbstractClipAnimator::running
|
||||||
|
|
@ -141,6 +146,13 @@ bool QAbstractClipAnimator::isRunning() const
|
||||||
return d->m_running;
|
return d->m_running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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
|
\property Qt3DAnimation::QAbstractClipAnimator::channelMapper
|
||||||
|
|
||||||
|
|
@ -198,6 +210,12 @@ int QAbstractClipAnimator::loopCount() const
|
||||||
Q_D(const QAbstractClipAnimator);
|
Q_D(const QAbstractClipAnimator);
|
||||||
return d->m_loops;
|
return d->m_loops;
|
||||||
}
|
}
|
||||||
|
/*!
|
||||||
|
\qmlproperty Clock Qt3DAnimation::AbstractClipAnimator::clock
|
||||||
|
|
||||||
|
The clock controls the speed with which an animation is played.
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\property Qt3DAnimation::QAbstractClipAnimator::clock
|
\property Qt3DAnimation::QAbstractClipAnimator::clock
|
||||||
|
|
||||||
|
|
@ -208,7 +226,11 @@ QClock *QAbstractClipAnimator::clock() const
|
||||||
Q_D(const QAbstractClipAnimator);
|
Q_D(const QAbstractClipAnimator);
|
||||||
return d->m_clock;
|
return d->m_clock;
|
||||||
}
|
}
|
||||||
|
/*!
|
||||||
|
\qmlproperty real Qt3DAnimation::AbstractClipAnimator::normalizedTime
|
||||||
|
|
||||||
|
This property holds the clips normalized time.
|
||||||
|
*/
|
||||||
/*!
|
/*!
|
||||||
\property Qt3DAnimation::QAbstractClipAnimator::normalizedTime
|
\property Qt3DAnimation::QAbstractClipAnimator::normalizedTime
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ QBlendedClipAnimatorPrivate::QBlendedClipAnimatorPrivate()
|
||||||
\qmltype BlendedClipAnimator
|
\qmltype BlendedClipAnimator
|
||||||
\instantiates Qt3DAnimation::QBlendedClipAnimator
|
\instantiates Qt3DAnimation::QBlendedClipAnimator
|
||||||
\inqmlmodule Qt3D.Animation
|
\inqmlmodule Qt3D.Animation
|
||||||
|
\inherits AbstractClipAnimator
|
||||||
\since 5.9
|
\since 5.9
|
||||||
|
|
||||||
\brief BlendedClipAnimator is a component providing animation playback capabilities of a tree
|
\brief BlendedClipAnimator is a component providing animation playback capabilities of a tree
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ bool QClipAnimatorPrivate::canPlay() const
|
||||||
\qmltype ClipAnimator
|
\qmltype ClipAnimator
|
||||||
\instantiates Qt3DAnimation::QClipAnimator
|
\instantiates Qt3DAnimation::QClipAnimator
|
||||||
\inqmlmodule Qt3D.Animation
|
\inqmlmodule Qt3D.Animation
|
||||||
|
\inherits AbstractClipAnimator
|
||||||
\since 5.9
|
\since 5.9
|
||||||
|
|
||||||
\brief ClipAnimator is a component providing simple animation playback capabilities.
|
\brief ClipAnimator is a component providing simple animation playback capabilities.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ TEMPLATE = subdirs
|
||||||
# QNX is not supported, and Linux GCC 4.9 on ARM chokes on the assimp
|
# 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).
|
# sources (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66964).
|
||||||
QT_FOR_CONFIG += 3dcore-private
|
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 += assimp
|
||||||
}
|
}
|
||||||
SUBDIRS += gltf
|
SUBDIRS += gltf
|
||||||
|
|
|
||||||
|
|
@ -529,6 +529,7 @@ void Scene3DItem::setWindowSurface(QObject *rootObject)
|
||||||
m_dummySurface = new QOffscreenSurface;
|
m_dummySurface = new QOffscreenSurface;
|
||||||
m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living
|
m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living
|
||||||
m_dummySurface->setFormat(rw->format());
|
m_dummySurface->setFormat(rw->format());
|
||||||
|
m_dummySurface->setScreen(rw->screen());
|
||||||
m_dummySurface->create();
|
m_dummySurface->create();
|
||||||
surfaceSelector->setSurface(m_dummySurface);
|
surfaceSelector->setSurface(m_dummySurface);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -616,6 +617,9 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
|
||||||
// If the render aspect wasn't created yet, do so now
|
// If the render aspect wasn't created yet, do so now
|
||||||
if (m_renderAspect == nullptr) {
|
if (m_renderAspect == nullptr) {
|
||||||
m_renderAspect = new QRenderAspect(QRenderAspect::Synchronous);
|
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);
|
m_aspectEngine->registerAspect(m_renderAspect);
|
||||||
|
|
||||||
// Before Synchronizing is in the SG Thread, we want beforeSync to be triggered
|
// Before Synchronizing is in the SG Thread, we want beforeSync to be triggered
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@
|
||||||
|
|
||||||
#include <Qt3DQuickExtras/private/qt3dquickwindowlogging_p.h>
|
#include <Qt3DQuickExtras/private/qt3dquickwindowlogging_p.h>
|
||||||
#include <Qt3DRender/private/qrendersurfaceselector_p.h>
|
#include <Qt3DRender/private/qrendersurfaceselector_p.h>
|
||||||
|
#include <Qt3DRender/private/qrenderaspect_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -132,6 +133,8 @@ Qt3DQuickWindow::Qt3DQuickWindow(QWindow *parent)
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
|
|
||||||
d->m_renderAspect = new Qt3DRender::QRenderAspect;
|
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_inputAspect = new Qt3DInput::QInputAspect;
|
||||||
d->m_logicAspect = new Qt3DLogic::QLogicAspect;
|
d->m_logicAspect = new Qt3DLogic::QLogicAspect;
|
||||||
d->m_engine = new Qt3DCore::Quick::QQmlAspectEngine;
|
d->m_engine = new Qt3DCore::Quick::QQmlAspectEngine;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ namespace Quick {
|
||||||
with the item; if an entity has a QObjectPicker component, the pick events from that picker
|
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.
|
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
|
\since 5.9
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -89,6 +91,8 @@ namespace Quick {
|
||||||
with the item; if an entity has an ObjectPicker component, the pick events from that picker
|
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.
|
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:
|
Usage:
|
||||||
\qml
|
\qml
|
||||||
Entity {
|
Entity {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QSurface;
|
class QSurface;
|
||||||
class QSize;
|
class QSize;
|
||||||
|
class QScreen;
|
||||||
|
|
||||||
namespace Qt3DCore {
|
namespace Qt3DCore {
|
||||||
class QAbstractFrameAdvanceService;
|
class QAbstractFrameAdvanceService;
|
||||||
|
|
@ -175,6 +176,8 @@ public:
|
||||||
|
|
||||||
// For QtQuick rendering
|
// For QtQuick rendering
|
||||||
virtual void setOpenGLContext(QOpenGLContext *ctx) = 0;
|
virtual void setOpenGLContext(QOpenGLContext *ctx) = 0;
|
||||||
|
virtual void setScreen(QScreen *) {}
|
||||||
|
virtual QScreen *screen() const { return nullptr; }
|
||||||
|
|
||||||
virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0;
|
virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0;
|
||||||
virtual QSurfaceFormat format() = 0;
|
virtual QSurfaceFormat format() = 0;
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ void OffscreenSurfaceHelper::createOffscreenSurface()
|
||||||
m_offscreenSurface = new QOffscreenSurface;
|
m_offscreenSurface = new QOffscreenSurface;
|
||||||
m_offscreenSurface->setParent(this);
|
m_offscreenSurface->setParent(this);
|
||||||
m_offscreenSurface->setFormat(m_renderer->format());
|
m_offscreenSurface->setFormat(m_renderer->format());
|
||||||
|
m_offscreenSurface->setScreen(m_renderer->screen());
|
||||||
m_offscreenSurface->create();
|
m_offscreenSurface->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,6 @@ bool PlatformSurfaceFilter::eventFilter(QObject *obj, QEvent *e)
|
||||||
// If we remove it, the call to isSurfaceValid will
|
// If we remove it, the call to isSurfaceValid will
|
||||||
// implicitely return false
|
// implicitely return false
|
||||||
PlatformSurfaceFilter::m_surfacesValidity.remove(m_surface);
|
PlatformSurfaceFilter::m_surfacesValidity.remove(m_surface);
|
||||||
if (m_obj) {
|
|
||||||
m_obj->removeEventFilter(this);
|
|
||||||
m_obj = nullptr;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ namespace Qt3DRender {
|
||||||
/*!
|
/*!
|
||||||
\qmltype ComputeCommand
|
\qmltype ComputeCommand
|
||||||
\since 5.7
|
\since 5.7
|
||||||
\inmodule Qt3DRender
|
\inqmlmodule Qt3D.Render
|
||||||
\inherits Component3D
|
\inherits Component3D
|
||||||
\instantiates Qt3DRender::QComputeCommand
|
\instantiates Qt3DRender::QComputeCommand
|
||||||
\brief Component to issue work for the compute shader on GPU.
|
\brief Component to issue work for the compute shader on GPU.
|
||||||
|
|
|
||||||
|
|
@ -562,6 +562,7 @@ void QRenderAspect::onRegistered()
|
||||||
|
|
||||||
// TO DO: Load proper Renderer class based on Qt configuration preferences
|
// TO DO: Load proper Renderer class based on Qt configuration preferences
|
||||||
d->m_renderer = new Render::Renderer(d->m_renderType);
|
d->m_renderer = new Render::Renderer(d->m_renderType);
|
||||||
|
d->m_renderer->setScreen(d->m_screen);
|
||||||
d->m_renderer->setNodeManagers(d->m_nodeManagers);
|
d->m_renderer->setNodeManagers(d->m_nodeManagers);
|
||||||
|
|
||||||
// Create a helper for deferring creation of an offscreen surface used during cleanup
|
// Create a helper for deferring creation of an offscreen surface used during cleanup
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QSurface;
|
class QSurface;
|
||||||
|
class QScreen;
|
||||||
|
|
||||||
namespace Qt3DRender {
|
namespace Qt3DRender {
|
||||||
|
|
||||||
|
|
@ -106,6 +107,7 @@ public:
|
||||||
QVector<Render::QRenderPlugin *> m_renderPlugins;
|
QVector<Render::QRenderPlugin *> m_renderPlugins;
|
||||||
QRenderAspect::RenderType m_renderType;
|
QRenderAspect::RenderType m_renderType;
|
||||||
Render::OffscreenSurfaceHelper *m_offscreenHelper;
|
Render::OffscreenSurfaceHelper *m_offscreenHelper;
|
||||||
|
QScreen *m_screen = nullptr;
|
||||||
|
|
||||||
static QMutex m_pluginLock;
|
static QMutex m_pluginLock;
|
||||||
static QVector<QString> m_pluginConfig;
|
static QVector<QString> m_pluginConfig;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -55,6 +56,9 @@ namespace {
|
||||||
// returns true and intersection point q; false otherwise
|
// returns true and intersection point q; false otherwise
|
||||||
bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRender::Render::Sphere &s, Vector3D *q = nullptr)
|
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 p = ray.origin();
|
||||||
const Vector3D d = ray.direction();
|
const Vector3D d = ray.direction();
|
||||||
const Vector3D m = p - s.center();
|
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)
|
inline void constructRitterSphere(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points)
|
||||||
{
|
{
|
||||||
// Calculate the sphere encompassing two axially extreme points
|
//def bounding_sphere(points):
|
||||||
sphereFromExtremePoints(s, 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
|
||||||
|
|
||||||
// Now make sure the sphere bounds all points by growing if needed
|
const Vector3D x = points[0];
|
||||||
s.expandToContain(points);
|
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(), [¢er](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
|
} // anonymous namespace
|
||||||
|
|
@ -169,6 +193,12 @@ void Sphere::initializeFromPoints(const QVector<Vector3D> &points)
|
||||||
|
|
||||||
void Sphere::expandToContain(const Vector3D &p)
|
void Sphere::expandToContain(const Vector3D &p)
|
||||||
{
|
{
|
||||||
|
if (isNull()) {
|
||||||
|
m_center = p;
|
||||||
|
m_radius = 0.0f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const Vector3D d = p - m_center;
|
const Vector3D d = p - m_center;
|
||||||
const float dist2 = d.lengthSquared();
|
const float dist2 = d.lengthSquared();
|
||||||
|
|
||||||
|
|
@ -184,6 +214,13 @@ void Sphere::expandToContain(const Vector3D &p)
|
||||||
|
|
||||||
void Sphere::expandToContain(const Sphere &sphere)
|
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 Vector3D d(sphere.m_center - m_center);
|
||||||
const float dist2 = d.lengthSquared();
|
const float dist2 = d.lengthSquared();
|
||||||
|
|
||||||
|
|
@ -206,6 +243,9 @@ void Sphere::expandToContain(const Sphere &sphere)
|
||||||
|
|
||||||
Sphere Sphere::transformed(const Matrix4x4 &mat) const
|
Sphere Sphere::transformed(const Matrix4x4 &mat) const
|
||||||
{
|
{
|
||||||
|
if (isNull())
|
||||||
|
return *this;
|
||||||
|
|
||||||
// Transform extremities in x, y, and z directions to find extremities
|
// Transform extremities in x, y, and z directions to find extremities
|
||||||
// of the resulting ellipsoid
|
// of the resulting ellipsoid
|
||||||
Vector3D x = mat.map(m_center + Vector3D(m_radius, 0.0f, 0.0f));
|
Vector3D x = mat.map(m_center + Vector3D(m_radius, 0.0f, 0.0f));
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ class Q_3DRENDERSHARED_PRIVATE_EXPORT Sphere : public RayCasting::BoundingSphere
|
||||||
public:
|
public:
|
||||||
inline Sphere(Qt3DCore::QNodeId i = Qt3DCore::QNodeId())
|
inline Sphere(Qt3DCore::QNodeId i = Qt3DCore::QNodeId())
|
||||||
: m_center()
|
: m_center()
|
||||||
, m_radius(0.0f)
|
, m_radius(-1.0f)
|
||||||
, m_id(i)
|
, m_id(i)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ public:
|
||||||
void setCenter(const Vector3D &c);
|
void setCenter(const Vector3D &c);
|
||||||
Vector3D center() const override;
|
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);
|
void setRadius(float r);
|
||||||
float radius() const override;
|
float radius() const override;
|
||||||
|
|
@ -131,6 +131,8 @@ inline Vector3D Sphere::center() const
|
||||||
|
|
||||||
inline void Sphere::setRadius(float r)
|
inline void Sphere::setRadius(float r)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(r >= 0.0f);
|
||||||
|
if (r >= 0.0f)
|
||||||
m_radius = r;
|
m_radius = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,11 +144,14 @@ inline float Sphere::radius() const
|
||||||
inline void Sphere::clear()
|
inline void Sphere::clear()
|
||||||
{
|
{
|
||||||
m_center = Vector3D();
|
m_center = Vector3D();
|
||||||
m_radius = 0.0f;
|
m_radius = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool intersects(const Sphere &a, const Sphere &b)
|
inline bool intersects(const Sphere &a, const Sphere &b)
|
||||||
{
|
{
|
||||||
|
if (a.isNull() || b.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
// Calculate squared distance between sphere centers
|
// Calculate squared distance between sphere centers
|
||||||
const Vector3D d = a.center() - b.center();
|
const Vector3D d = a.center() - b.center();
|
||||||
const float distSq = Vector3D::dotProduct(d, d);
|
const float distSq = Vector3D::dotProduct(d, d);
|
||||||
|
|
|
||||||
|
|
@ -90,30 +90,42 @@ public:
|
||||||
m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
|
m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
|
||||||
m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
|
m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
|
||||||
|
|
||||||
// Calculate squared distance for the pairs of points
|
FindMaxDistantPoint maxDistantPointY(m_manager);
|
||||||
const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared();
|
maxDistantPointY.setReferencePoint = true;
|
||||||
const float yDist2 = (findExtremePoints.yMaxPt - findExtremePoints.yMinPt).lengthSquared();
|
if (!maxDistantPointY.apply(positionAttribute, indexAttribute, drawVertexCount,
|
||||||
const float zDist2 = (findExtremePoints.zMaxPt - findExtremePoints.zMinPt).lengthSquared();
|
primitiveRestartEnabled, primitiveRestartIndex)) {
|
||||||
|
return false;
|
||||||
// Select most distant pair
|
|
||||||
Vector3D p = findExtremePoints.xMinPt;
|
|
||||||
Vector3D q = findExtremePoints.xMaxPt;
|
|
||||||
if (yDist2 > xDist2 && yDist2 > zDist2) {
|
|
||||||
p = findExtremePoints.yMinPt;
|
|
||||||
q = findExtremePoints.yMaxPt;
|
|
||||||
}
|
}
|
||||||
if (zDist2 > xDist2 && zDist2 > yDist2) {
|
if (maxDistantPointY.hasNoPoints)
|
||||||
p = findExtremePoints.zMinPt;
|
return false;
|
||||||
q = findExtremePoints.zMaxPt;
|
|
||||||
|
//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);
|
const float radius = (center - maxDistantPointCenter.maxDistPt).length();
|
||||||
m_volume.setCenter(c);
|
|
||||||
m_volume.setRadius((q - c).length());
|
|
||||||
|
|
||||||
ExpandSphere expandSphere(m_manager, m_volume);
|
m_volume = Qt3DRender::Render::Sphere(center, radius);
|
||||||
if (!expandSphere.apply(positionAttribute, indexAttribute, drawVertexCount,
|
|
||||||
primitiveRestartEnabled, primitiveRestartIndex))
|
if (m_volume.isNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -172,18 +184,34 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExpandSphere : public Buffer3fVisitor
|
class FindMaxDistantPoint : public Buffer3fVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExpandSphere(NodeManagers *manager, Sphere& volume)
|
FindMaxDistantPoint(NodeManagers *manager)
|
||||||
: Buffer3fVisitor(manager), m_volume(volume)
|
: 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
|
void visit(uint ndx, float x, float y, float z) override
|
||||||
{
|
{
|
||||||
Q_UNUSED(ndx);
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -202,12 +202,12 @@ void PickBoundingVolumeJob::setRoot(Entity *root)
|
||||||
|
|
||||||
void PickBoundingVolumeJob::setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents)
|
void PickBoundingVolumeJob::setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents)
|
||||||
{
|
{
|
||||||
m_pendingMouseEvents = pendingEvents;
|
m_pendingMouseEvents.append(pendingEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents)
|
void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents)
|
||||||
{
|
{
|
||||||
m_pendingKeyEvents = pendingEvents;
|
m_pendingKeyEvents.append(pendingEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PickBoundingVolumeJob::markPickersDirty()
|
void PickBoundingVolumeJob::markPickersDirty()
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ QEffectPrivate::QEffectPrivate()
|
||||||
|
|
||||||
An QEffect instance should be shared among several QMaterial instances when possible.
|
An QEffect instance should be shared among several QMaterial instances when possible.
|
||||||
|
|
||||||
|
\note QEffect node can not be disabled.
|
||||||
|
|
||||||
\code
|
\code
|
||||||
QEffect *effect = new QEffect();
|
QEffect *effect = new QEffect();
|
||||||
|
|
||||||
|
|
@ -111,6 +113,8 @@ QEffectPrivate::QEffectPrivate()
|
||||||
A Parameter defined on an Effect is overridden by a QParameter (of the same
|
A Parameter defined on an Effect is overridden by a QParameter (of the same
|
||||||
name) defined in a Material, TechniqueFilter, RenderPassFilter.
|
name) defined in a Material, TechniqueFilter, RenderPassFilter.
|
||||||
|
|
||||||
|
\note Effect node can not be disabled.
|
||||||
|
|
||||||
\code
|
\code
|
||||||
Effect {
|
Effect {
|
||||||
id: effect
|
id: effect
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ QFilterKeyPrivate::QFilterKeyPrivate()
|
||||||
|
|
||||||
Filter keys are used by QTechnique and QRenderPass to specify at which stage of rendering the
|
Filter keys are used by QTechnique and QRenderPass to specify at which stage of rendering the
|
||||||
technique or the render pass is used.
|
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.
|
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
|
Filter keys are used by Technique and RenderPass to specify at which stage of rendering the
|
||||||
technique or the render pass is used.
|
technique or the render pass is used.
|
||||||
|
|
||||||
|
\note FilterKey node can not be disabled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QFilterKey::QFilterKey(QNode *parent)
|
QFilterKey::QFilterKey(QNode *parent)
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,8 @@
|
||||||
\note when the targeted uniform is an array, the name should be the name
|
\note when the targeted uniform is an array, the name should be the name
|
||||||
of the uniform with [0] appended to it.
|
of the uniform with [0] appended to it.
|
||||||
|
|
||||||
|
\note Parameter node can not be disabled.
|
||||||
|
|
||||||
\code
|
\code
|
||||||
Parameter {
|
Parameter {
|
||||||
name: "diffuseValues[0]"
|
name: "diffuseValues[0]"
|
||||||
|
|
@ -138,6 +140,8 @@
|
||||||
\note when the targeted uniform is an array, the name should be the name
|
\note when the targeted uniform is an array, the name should be the name
|
||||||
of the uniform with [0] appended to it.
|
of the uniform with [0] appended to it.
|
||||||
|
|
||||||
|
\note QParameter node can not be disabled.
|
||||||
|
|
||||||
\code
|
\code
|
||||||
QParameter *param = new QParameter();
|
QParameter *param = new QParameter();
|
||||||
QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
|
QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,8 @@ QTechniquePrivate::~QTechniquePrivate()
|
||||||
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
|
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
|
||||||
will likely have no effect on Qt3D related rendering.
|
will likely have no effect on Qt3D related rendering.
|
||||||
|
|
||||||
|
\note Technique node can not be disabled.
|
||||||
|
|
||||||
\qml
|
\qml
|
||||||
Technique {
|
Technique {
|
||||||
id: gl3Technique
|
id: gl3Technique
|
||||||
|
|
@ -152,6 +154,8 @@ QTechniquePrivate::~QTechniquePrivate()
|
||||||
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
|
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
|
||||||
will likely have no effect on Qt3D related rendering.
|
will likely have no effect on Qt3D related rendering.
|
||||||
|
|
||||||
|
\note QTechnique node can not be disabled.
|
||||||
|
|
||||||
\code
|
\code
|
||||||
QTechnique *gl3Technique = new QTechnique();
|
QTechnique *gl3Technique = new QTechnique();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,9 @@ namespace Qt3DRender {
|
||||||
\note Instances of this component shouldn't be shared, not respecting that
|
\note Instances of this component shouldn't be shared, not respecting that
|
||||||
condition will most likely result in undefined behavior.
|
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
|
\since 5.6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -115,6 +118,9 @@ namespace Qt3DRender {
|
||||||
|
|
||||||
\note Instances of this component shouldn't be shared, not respecting that
|
\note Instances of this component shouldn't be shared, not respecting that
|
||||||
condition will most likely result in undefined behavior.
|
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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,16 @@ void Renderer::setOpenGLContext(QOpenGLContext *context)
|
||||||
m_glContext = 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
|
// Called in RenderThread context by the run method of RenderThread
|
||||||
// RenderThread has locked the mutex already and unlocks it when this
|
// RenderThread has locked the mutex already and unlocks it when this
|
||||||
// method termintates
|
// method termintates
|
||||||
|
|
@ -364,6 +374,8 @@ void Renderer::initialize()
|
||||||
// we need to create it
|
// we need to create it
|
||||||
if (!m_glContext) {
|
if (!m_glContext) {
|
||||||
ctx = new QOpenGLContext;
|
ctx = new QOpenGLContext;
|
||||||
|
if (m_screen)
|
||||||
|
ctx->setScreen(m_screen);
|
||||||
ctx->setShareContext(qt_gl_global_share_context());
|
ctx->setShareContext(qt_gl_global_share_context());
|
||||||
|
|
||||||
// TO DO: Shouldn't we use the highest context available and trust
|
// TO DO: Shouldn't we use the highest context available and trust
|
||||||
|
|
@ -393,6 +405,8 @@ void Renderer::initialize()
|
||||||
|
|
||||||
if (!ctx->shareContext()) {
|
if (!ctx->shareContext()) {
|
||||||
m_shareContext = new QOpenGLContext;
|
m_shareContext = new QOpenGLContext;
|
||||||
|
if (ctx->screen())
|
||||||
|
m_shareContext->setScreen(ctx->screen());
|
||||||
m_shareContext->setFormat(ctx->format());
|
m_shareContext->setFormat(ctx->format());
|
||||||
m_shareContext->setShareContext(ctx);
|
m_shareContext->setShareContext(ctx);
|
||||||
m_shareContext->create();
|
m_shareContext->create();
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QSurface;
|
class QSurface;
|
||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
|
class QScreen;
|
||||||
|
|
||||||
namespace Qt3DCore {
|
namespace Qt3DCore {
|
||||||
class QEntity;
|
class QEntity;
|
||||||
|
|
@ -293,6 +294,8 @@ public:
|
||||||
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
|
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
|
||||||
|
|
||||||
RendererCache *cache() { return &m_cache; }
|
RendererCache *cache() { return &m_cache; }
|
||||||
|
void setScreen(QScreen *scr) override;
|
||||||
|
QScreen *screen() const override;
|
||||||
|
|
||||||
#ifdef QT3D_RENDER_UNIT_TESTS
|
#ifdef QT3D_RENDER_UNIT_TESTS
|
||||||
public:
|
public:
|
||||||
|
|
@ -426,6 +429,7 @@ private:
|
||||||
bool m_shouldSwapBuffers;
|
bool m_shouldSwapBuffers;
|
||||||
|
|
||||||
QVector<FrameGraphNode *> m_frameGraphLeaves;
|
QVector<FrameGraphNode *> m_frameGraphLeaves;
|
||||||
|
QScreen *m_screen = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Render
|
} // namespace Render
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ namespace Qt3DRender {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmltype RenderState
|
\qmltype RenderState
|
||||||
|
\inqmlmodule Qt3D.Render
|
||||||
\brief An abstract base type for all render states.
|
\brief An abstract base type for all render states.
|
||||||
\since 5.7
|
\since 5.7
|
||||||
\inherits Node
|
\inherits Node
|
||||||
|
|
|
||||||
|
|
@ -204,13 +204,150 @@ class tst_BoundingSphere : public Qt3DCore::QBackendNodeTester
|
||||||
private:
|
private:
|
||||||
|
|
||||||
private Q_SLOTS:
|
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()
|
void checkExtraGeometries_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("qmlFile");
|
QTest::addColumn<QString>("qmlFile");
|
||||||
QTest::addColumn<QVector3D>("sphereCenter");
|
QTest::addColumn<QVector3D>("sphereCenter");
|
||||||
QTest::addColumn<float>("sphereRadius");
|
QTest::addColumn<float>("sphereRadius");
|
||||||
QTest::newRow("SphereMesh") << "qrc:/sphere.qml" << QVector3D(0.f, 0.f, 0.f) << 1.f;
|
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()
|
void checkExtraGeometries()
|
||||||
|
|
@ -235,9 +372,10 @@ private Q_SLOTS:
|
||||||
const auto boundingSphere = test->sceneRoot()->worldBoundingVolumeWithChildren();
|
const auto boundingSphere = test->sceneRoot()->worldBoundingVolumeWithChildren();
|
||||||
qDebug() << qmlFile << boundingSphere->radius() << boundingSphere->center();
|
qDebug() << qmlFile << boundingSphere->radius() << boundingSphere->center();
|
||||||
QCOMPARE(boundingSphere->radius(), sphereRadius);
|
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(qFuzzyIsNull(boundingSphere->center().x() - sphereCenter.x()));
|
||||||
QVERIFY(qAbs(boundingSphere->center().z() - sphereCenter.z()) < 0.000001f);
|
QVERIFY(qFuzzyIsNull(boundingSphere->center().y() - sphereCenter.y()));
|
||||||
|
QVERIFY(qFuzzyIsNull(boundingSphere->center().z() - sphereCenter.z()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkCustomGeometry_data()
|
void checkCustomGeometry_data()
|
||||||
|
|
@ -247,10 +385,10 @@ private Q_SLOTS:
|
||||||
QTest::addColumn<QVector3D>("expectedCenter");
|
QTest::addColumn<QVector3D>("expectedCenter");
|
||||||
QTest::addColumn<float>("expectedRadius");
|
QTest::addColumn<float>("expectedRadius");
|
||||||
QTest::addColumn<bool>("withPrimitiveRestart");
|
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("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("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("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;
|
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();
|
float radius = entityBackend->localBoundingVolume()->radius();
|
||||||
qDebug() << radius << center;
|
qDebug() << radius << center;
|
||||||
|
|
||||||
// truncate and compare integers only
|
QCOMPARE(radius, expectedRadius);
|
||||||
QCOMPARE(int(radius), int(expectedRadius));
|
QCOMPARE(center.x(), expectedCenter.x());
|
||||||
QCOMPARE(int(center.x()), int(expectedCenter.x()));
|
QCOMPARE(center.y(), expectedCenter.y());
|
||||||
QCOMPARE(int(center.y()), int(expectedCenter.y()));
|
QCOMPARE(center.z(), expectedCenter.z());
|
||||||
QCOMPARE(int(center.z()), int(expectedCenter.z()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkCustomPackedGeometry()
|
void checkCustomPackedGeometry()
|
||||||
{
|
{
|
||||||
int drawVertexCount = 6;
|
int drawVertexCount = 6;
|
||||||
QVector3D expectedCenter(-0.488892f, 0.0192147f, -75.4804f);
|
QVector3D expectedCenter(0.0f, 0.0f, -75.0f);
|
||||||
float expectedRadius = 25.5442f;
|
float expectedRadius = 25.03997f;
|
||||||
|
|
||||||
// two triangles with different Z
|
// two triangles with different Z
|
||||||
QByteArray vdata;
|
QByteArray vdata;
|
||||||
|
|
@ -467,11 +604,10 @@ private Q_SLOTS:
|
||||||
float radius = entityBackend->localBoundingVolume()->radius();
|
float radius = entityBackend->localBoundingVolume()->radius();
|
||||||
qDebug() << radius << center;
|
qDebug() << radius << center;
|
||||||
|
|
||||||
// truncate and compare integers only
|
QCOMPARE(radius, expectedRadius);
|
||||||
QVERIFY(int(radius) == int(expectedRadius));
|
QCOMPARE(center.x(), expectedCenter.x());
|
||||||
QVERIFY(int(center.x()) == int(expectedCenter.x()));
|
QCOMPARE(center.y(), expectedCenter.y());
|
||||||
QVERIFY(int(center.y()) == int(expectedCenter.y()));
|
QCOMPARE(center.z(), expectedCenter.z());
|
||||||
QVERIFY(int(center.z()) == int(expectedCenter.z()));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@
|
||||||
#include <QtTest/QTest>
|
#include <QtTest/QTest>
|
||||||
#include <Qt3DCore/qentity.h>
|
#include <Qt3DCore/qentity.h>
|
||||||
#include <Qt3DCore/qtransform.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/nodemanagers_p.h>
|
||||||
#include <Qt3DRender/private/managers_p.h>
|
#include <Qt3DRender/private/managers_p.h>
|
||||||
#include <Qt3DRender/private/entity_p.h>
|
#include <Qt3DRender/private/entity_p.h>
|
||||||
|
|
@ -43,6 +47,40 @@ namespace {
|
||||||
Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *parent)
|
Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *parent)
|
||||||
{
|
{
|
||||||
Qt3DCore::QEntity *entity = new 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);
|
Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(parent);
|
||||||
const QVector3D t = QVector3D(1.0f, 0.0f, 0.0f) * distance;
|
const QVector3D t = QVector3D(1.0f, 0.0f, 0.0f) * distance;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue