diff options
19 files changed, 175 insertions, 147 deletions
diff --git a/src/quick3d/quick3drender/items/quick3draycaster.cpp b/src/quick3d/quick3drender/items/quick3draycaster.cpp index b8f086983..d0c282a1c 100644 --- a/src/quick3d/quick3drender/items/quick3draycaster.cpp +++ b/src/quick3d/quick3drender/items/quick3draycaster.cpp @@ -43,78 +43,12 @@ #include <Qt3DCore/QEntity> -#include <QQmlEngine> -#include <QJSValue> - QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { namespace Quick { -void Quick3DRayCasterPrivate::dispatchHits(const QAbstractRayCaster::Hits &hits) -{ - m_hits = hits; - updateHitEntites(m_hits, m_scene); - - Q_Q(Quick3DRayCaster); - if (!m_engine) - m_engine = qmlEngine(q->parent()); - - m_jsHits = convertHits(m_hits, m_engine); - - bool v = q->blockNotifications(true); - emit q->hitsChanged(m_jsHits); - q->blockNotifications(v); -} - -QJSValue Quick3DRayCasterPrivate::convertHits(const QAbstractRayCaster::Hits &hits, QQmlEngine *engine) -{ - auto jsHits = engine->newArray(hits.length()); - for (int i=0; i<hits.size(); i++) { - QJSValue v = engine->newObject(); - v.setProperty(QLatin1String("type"), hits[i].type()); - v.setProperty(QLatin1String("entity"), engine->newQObject(hits[i].entity())); - v.setProperty(QLatin1String("distance"), hits[i].distance()); - { - QJSValue p = engine->newObject(); - p.setProperty(QLatin1String("x"), hits[i].localIntersection().x()); - p.setProperty(QLatin1String("y"), hits[i].localIntersection().y()); - p.setProperty(QLatin1String("z"), hits[i].localIntersection().z()); - v.setProperty(QLatin1String("localIntersection"), p); - } - { - QJSValue p = engine->newObject(); - p.setProperty(QLatin1String("x"), hits[i].worldIntersection().x()); - p.setProperty(QLatin1String("y"), hits[i].worldIntersection().y()); - p.setProperty(QLatin1String("z"), hits[i].worldIntersection().z()); - v.setProperty(QLatin1String("worldIntersection"), p); - } - - switch (hits[i].type()) { - case Qt3DRender::QRayCasterHit::TriangleHit: - v.setProperty(QLatin1String("primitiveIndex"), hits[i].primitiveIndex()); - v.setProperty(QLatin1String("vertex1Index"), hits[i].vertex1Index()); - v.setProperty(QLatin1String("vertex2Index"), hits[i].vertex2Index()); - v.setProperty(QLatin1String("vertex3Index"), hits[i].vertex3Index()); - break; - case Qt3DRender::QRayCasterHit::LineHit: - v.setProperty(QLatin1String("primitiveIndex"), hits[i].primitiveIndex()); - v.setProperty(QLatin1String("vertex1Index"), hits[i].vertex1Index()); - v.setProperty(QLatin1String("vertex2Index"), hits[i].vertex2Index()); - break; - case Qt3DRender::QRayCasterHit::PointHit: - v.setProperty(QLatin1String("primitiveIndex"), hits[i].primitiveIndex()); - break; - default: break; - } - - jsHits.setProperty(i, v); - } - - return jsHits; -} - void Quick3DRayCasterPrivate::appendLayer(QQmlListProperty<QLayer> *list, QLayer *layer) { QAbstractRayCaster *filter = qobject_cast<QAbstractRayCaster *>(list->object); @@ -134,7 +68,7 @@ int Quick3DRayCasterPrivate::layerCount(QQmlListProperty<QLayer> *list) { QAbstractRayCaster *filter = qobject_cast<QAbstractRayCaster *>(list->object); if (filter) - return filter->layers().count(); + return int(filter->layers().size()); return 0; } @@ -153,15 +87,9 @@ Quick3DRayCaster::Quick3DRayCaster(QObject *parent) { } -QJSValue Quick3DRayCaster::hits() const -{ - Q_D(const Quick3DRayCaster); - return d->m_jsHits; -} - QQmlListProperty<Qt3DRender::QLayer> Qt3DRender::Render::Quick::Quick3DRayCaster::qmlLayers() { - return QQmlListProperty<QLayer>(this, 0, + return QQmlListProperty<QLayer>(this, nullptr, &Quick3DRayCasterPrivate::appendLayer, &Quick3DRayCasterPrivate::layerCount, &Quick3DRayCasterPrivate::layerAt, diff --git a/src/quick3d/quick3drender/items/quick3draycaster_p.h b/src/quick3d/quick3drender/items/quick3draycaster_p.h index 31778dc3b..20a55a7bb 100644 --- a/src/quick3d/quick3drender/items/quick3draycaster_p.h +++ b/src/quick3d/quick3drender/items/quick3draycaster_p.h @@ -69,17 +69,12 @@ class Quick3DRayCasterPrivate; class Q_3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DRayCaster : public QRayCaster { Q_OBJECT - Q_PROPERTY(QJSValue hits READ hits NOTIFY hitsChanged) Q_PROPERTY(QQmlListProperty<Qt3DRender::QLayer> layers READ qmlLayers) public: - explicit Quick3DRayCaster(QObject *parent = 0); + explicit Quick3DRayCaster(QObject *parent = nullptr); - QJSValue hits() const; QQmlListProperty<QLayer> qmlLayers(); -Q_SIGNALS: - void hitsChanged(const QJSValue &hits); - private: Q_DECLARE_PRIVATE(Quick3DRayCaster) }; diff --git a/src/quick3d/quick3drender/items/quick3draycaster_p_p.h b/src/quick3d/quick3drender/items/quick3draycaster_p_p.h index ef875eb43..dec8dcfb6 100644 --- a/src/quick3d/quick3drender/items/quick3draycaster_p_p.h +++ b/src/quick3d/quick3drender/items/quick3draycaster_p_p.h @@ -57,8 +57,6 @@ #include <Qt3DQuickRender/private/quick3draycaster_p.h> #include <Qt3DQuick/private/quick3dnode_p.h> -#include <QtQml/QJSValue> - QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -70,11 +68,6 @@ class Q_3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DRayCasterPrivate : public QAbs public: explicit Quick3DRayCasterPrivate() : QAbstractRayCasterPrivate() { } - QJSValue m_jsHits; - QQmlEngine *m_engine = nullptr; - - void dispatchHits(const QAbstractRayCaster::Hits &hits) override; - static QJSValue convertHits(const QAbstractRayCaster::Hits &hits, QQmlEngine *engine); static void appendLayer(QQmlListProperty<QLayer> *list, QLayer *bar); static QLayer *layerAt(QQmlListProperty<QLayer> *list, int index); static int layerCount(QQmlListProperty<QLayer> *list); diff --git a/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp b/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp index dd3d1f758..03d6268c3 100644 --- a/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp +++ b/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp @@ -53,33 +53,14 @@ namespace Qt3DRender { namespace Render { namespace Quick { -void Quick3DScreenRayCasterPrivate::dispatchHits(const QAbstractRayCaster::Hits &hits) -{ - m_hits = hits; - updateHitEntites(m_hits, m_scene); - - Q_Q(Quick3DScreenRayCaster); - if (!m_engine) - m_engine = qmlEngine(q->parent()); - - m_jsHits = Quick3DRayCasterPrivate::convertHits(m_hits, m_engine); - emit q->hitsChanged(m_jsHits); -} - Quick3DScreenRayCaster::Quick3DScreenRayCaster(QObject *parent) : QScreenRayCaster(*new Quick3DScreenRayCasterPrivate(), qobject_cast<Qt3DCore::QNode *>(parent)) { } -QJSValue Quick3DScreenRayCaster::hits() const -{ - Q_D(const Quick3DScreenRayCaster); - return d->m_jsHits; -} - QQmlListProperty<Qt3DRender::QLayer> Qt3DRender::Render::Quick::Quick3DScreenRayCaster::qmlLayers() { - return QQmlListProperty<QLayer>(this, 0, + return QQmlListProperty<QLayer>(this, nullptr, &Quick3DRayCasterPrivate::appendLayer, &Quick3DRayCasterPrivate::layerCount, &Quick3DRayCasterPrivate::layerAt, diff --git a/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h b/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h index 63d3f0428..4f1f19a1c 100644 --- a/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h +++ b/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h @@ -56,8 +56,6 @@ #include <Qt3DQuickRender/private/qt3dquickrender_global_p.h> #include <Qt3DQuick/private/quick3dnode_p.h> -#include <QtQml/QJSValue> - QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -69,17 +67,12 @@ class Quick3DScreenRayCasterPrivate; class Q_3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DScreenRayCaster : public QScreenRayCaster { Q_OBJECT - Q_PROPERTY(QJSValue hits READ hits NOTIFY hitsChanged) Q_PROPERTY(QQmlListProperty<Qt3DRender::QLayer> layers READ qmlLayers) public: - explicit Quick3DScreenRayCaster(QObject *parent = 0); + explicit Quick3DScreenRayCaster(QObject *parent = nullptr); - QJSValue hits() const; QQmlListProperty<QLayer> qmlLayers(); -Q_SIGNALS: - void hitsChanged(const QJSValue &hits); - private: Q_DECLARE_PRIVATE(Quick3DScreenRayCaster) }; diff --git a/src/quick3d/quick3drender/items/quick3dscreenraycaster_p_p.h b/src/quick3d/quick3drender/items/quick3dscreenraycaster_p_p.h index ad5d0b941..e84430a7b 100644 --- a/src/quick3d/quick3drender/items/quick3dscreenraycaster_p_p.h +++ b/src/quick3d/quick3drender/items/quick3dscreenraycaster_p_p.h @@ -71,11 +71,6 @@ class Q_3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DScreenRayCasterPrivate : publi public: explicit Quick3DScreenRayCasterPrivate() : QAbstractRayCasterPrivate() { } - QJSValue m_jsHits; - QQmlEngine *m_engine = nullptr; - - void dispatchHits(const QAbstractRayCaster::Hits &hits) override; - Q_DECLARE_PUBLIC(Quick3DScreenRayCaster) }; diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp index 3718928b4..7c7ddc71a 100644 --- a/src/render/jobs/raycastingjob.cpp +++ b/src/render/jobs/raycastingjob.cpp @@ -66,13 +66,17 @@ class EntityCasterGatherer : public EntityVisitor public: using EntityCasterList = QList<QPair<Entity *, RayCaster *>>; EntityCasterList m_result; + RayCaster *m_trigger; - explicit EntityCasterGatherer(NodeManagers *manager) : EntityVisitor(manager) { setPruneDisabled(true); } + explicit EntityCasterGatherer(NodeManagers *manager, RayCaster *trigger = nullptr) + : EntityVisitor(manager), m_trigger(trigger) { + setPruneDisabled(true); + } Operation visit(Entity *entity) override { const std::vector<RayCaster *> &components = entity->renderComponents<RayCaster>(); for (const auto c: components) { - if (c->isEnabled()) + if ((m_trigger == nullptr && c->isEnabled()) || (m_trigger != nullptr && m_trigger == c)) m_result.push_back(qMakePair(entity, c)); } @@ -159,22 +163,17 @@ bool RayCastingJob::runHelper() if (!m_oneEnabledAtLeast) return false; - const bool trianglePickingRequested = (m_renderSettings->pickMethod() & QPickingSettings::TrianglePicking); - const bool edgePickingRequested = (m_renderSettings->pickMethod() & QPickingSettings::LinePicking); - const bool pointPickingRequested = (m_renderSettings->pickMethod() & QPickingSettings::PointPicking); - const bool primitivePickingRequested = pointPickingRequested | edgePickingRequested | trianglePickingRequested; - const bool frontFaceRequested = - m_renderSettings->faceOrientationPickingMode() != QPickingSettings::BackFace; - const bool backFaceRequested = - m_renderSettings->faceOrientationPickingMode() != QPickingSettings::FrontFace; - const float pickWorldSpaceTolerance = m_renderSettings->pickWorldSpaceTolerance(); - EntityCasterGatherer gatherer(m_manager); gatherer.apply(m_node); const EntityCasterGatherer::EntityCasterList &entities = gatherer.m_result; + return pick(entities); +} - PickingUtils::ViewportCameraAreaGatherer vcaGatherer; - const std::vector<PickingUtils::ViewportCameraAreaDetails> &vcaDetails = vcaGatherer.gather(m_frameGraphRoot); +bool RayCastingJob::pick(const QList<QPair<Entity *, RayCaster *>> &entities) +{ + const PickingUtils::PickConfiguration pickConfiguration(m_frameGraphRoot, m_renderSettings); + if (pickConfiguration.vcaDetails.empty()) + return false; const float sceneRayLength = m_node->worldBoundingVolumeWithChildren()->radius() * 3.f; @@ -189,7 +188,7 @@ bool RayCastingJob::runHelper() rays.back().transform(*pair.first->worldTransform()); break; case QAbstractRayCasterPrivate::ScreenScapeRayCaster: - for (const PickingUtils::ViewportCameraAreaDetails &vca : vcaDetails) { + for (const PickingUtils::ViewportCameraAreaDetails &vca : pickConfiguration.vcaDetails) { const auto ray = rayForViewportAndCamera(vca, nullptr, pair.second->position()); if (ray.isValid()) rays.push_back(ray); @@ -204,10 +203,10 @@ bool RayCastingJob::runHelper() PickingUtils::HierarchicalEntityPicker entityPicker(ray, false); entityPicker.setFilterLayers(pair.second->layerIds(), pair.second->filterMode()); if (entityPicker.collectHits(m_manager, m_node)) { - if (trianglePickingRequested) { + if (pickConfiguration.trianglePickingRequested) { PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; - gathererFunctor.m_frontFaceRequested = frontFaceRequested; - gathererFunctor.m_backFaceRequested = backFaceRequested; + gathererFunctor.m_frontFaceRequested = pickConfiguration.frontFaceRequested; + gathererFunctor.m_backFaceRequested = pickConfiguration.backFaceRequested; gathererFunctor.m_manager = m_manager; gathererFunctor.m_ray = ray; gathererFunctor.m_objectPickersRequired = false; @@ -216,11 +215,11 @@ bool RayCastingJob::runHelper() std::make_move_iterator(hits.begin()), std::make_move_iterator(hits.end())); } - if (edgePickingRequested) { + if (pickConfiguration.edgePickingRequested) { PickingUtils::LineCollisionGathererFunctor gathererFunctor; gathererFunctor.m_manager = m_manager; gathererFunctor.m_ray = ray; - gathererFunctor.m_pickWorldSpaceTolerance = pickWorldSpaceTolerance; + gathererFunctor.m_pickWorldSpaceTolerance = pickConfiguration.pickWorldSpaceTolerance; gathererFunctor.m_objectPickersRequired = false; const PickingUtils::HitList &hits = gathererFunctor.computeHits(entityPicker.entities(), QPickingSettings::AllPicks); sphereHits.insert(sphereHits.end(), @@ -228,11 +227,11 @@ bool RayCastingJob::runHelper() std::make_move_iterator(hits.end())); PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits); } - if (pointPickingRequested) { + if (pickConfiguration.pointPickingRequested) { PickingUtils::PointCollisionGathererFunctor gathererFunctor; gathererFunctor.m_manager = m_manager; gathererFunctor.m_ray = ray; - gathererFunctor.m_pickWorldSpaceTolerance = pickWorldSpaceTolerance; + gathererFunctor.m_pickWorldSpaceTolerance = pickConfiguration.pickWorldSpaceTolerance; gathererFunctor.m_objectPickersRequired = false; const PickingUtils::HitList &hits = gathererFunctor.computeHits(entityPicker.entities(), QPickingSettings::AllPicks); sphereHits.insert(sphereHits.end(), @@ -240,7 +239,7 @@ bool RayCastingJob::runHelper() std::make_move_iterator(hits.end())); PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits); } - if (!primitivePickingRequested) { + if (!pickConfiguration.primitivePickingRequested) { const PickingUtils::HitList &hits = entityPicker.hits(); sphereHits.insert(sphereHits.end(), std::make_move_iterator(hits.begin()), @@ -256,6 +255,37 @@ bool RayCastingJob::runHelper() return true; } +QAbstractRayCaster::Hits RayCastingJob::pick(Qt3DRender::QAbstractRayCaster *rayCaster) +{ + const PickingUtils::PickConfiguration pickConfiguration(m_frameGraphRoot, m_renderSettings); + if (pickConfiguration.vcaDetails.empty()) + return {}; + + auto backendRayCaster = m_manager->rayCasterManager()->lookupResource(rayCaster->id()); + if (!backendRayCaster) + return {}; + + backendRayCaster->syncFromFrontEnd(rayCaster, false); + + EntityCasterGatherer gatherer(m_manager, backendRayCaster); + gatherer.apply(m_node); + const EntityCasterGatherer::EntityCasterList &entities = gatherer.m_result; + + if (!pick(entities)) + return {}; + + Q_D(RayCastingJob); + QAbstractRayCaster::Hits res; + for (const auto &hit: d->dispatches) { + if (hit.first->peerId() == rayCaster->id()) { + res = hit.second; + break; + } + } + d->dispatches.clear(); + return res; +} + void RayCastingJob::dispatchHits(RayCaster *rayCaster, const PickingUtils::HitList &sphereHits) { QAbstractRayCaster::Hits hits; diff --git a/src/render/jobs/raycastingjob_p.h b/src/render/jobs/raycastingjob_p.h index 061166918..fd9360501 100644 --- a/src/render/jobs/raycastingjob_p.h +++ b/src/render/jobs/raycastingjob_p.h @@ -79,6 +79,9 @@ public: void markCastersDirty(); bool runHelper() override; + QAbstractRayCaster::Hits pick(QAbstractRayCaster *rayCaster); + bool pick(const QList<QPair<Entity *, RayCaster *>> &entities); + protected: void dispatchHits(RayCaster *rayCaster, const PickingUtils::HitList &sphereHits); diff --git a/src/render/picking/qabstractraycaster.cpp b/src/render/picking/qabstractraycaster.cpp index f21d3b9ae..473a0d3e3 100644 --- a/src/render/picking/qabstractraycaster.cpp +++ b/src/render/picking/qabstractraycaster.cpp @@ -39,10 +39,14 @@ #include "qabstractraycaster.h" #include "qabstractraycaster_p.h" +#include <Qt3DCore/qaspectengine.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/private/qcomponent_p.h> #include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/private/qaspectengine_p.h> #include <Qt3DRender/qlayer.h> +#include <Qt3DRender/qrenderaspect.h> +#include <Qt3DRender/private/qrenderaspect_p.h> QT_BEGIN_NAMESPACE @@ -71,6 +75,24 @@ void QAbstractRayCasterPrivate::updateHitEntites(QAbstractRayCaster::Hits &hits, hits[i].setEntity(qobject_cast<Qt3DCore::QEntity *>(scene->lookupNode(hits[i].entityId()))); } +QAbstractRayCaster::Hits QAbstractRayCasterPrivate::pick() +{ + Qt3DRender::QRenderAspect *renderAspect = nullptr; + const auto aspects = m_scene->engine()->aspects(); + for (auto a: aspects) { + renderAspect = qobject_cast<Qt3DRender::QRenderAspect *>(a); + if (renderAspect) + break; + } + if (!renderAspect) + return {}; + + Q_Q(QAbstractRayCaster); + auto dRenderAspect = Qt3DRender::QRenderAspectPrivate::get(renderAspect); + dispatchHits(dRenderAspect->m_rayCastingJob->pick(q)); + return m_hits; +} + void QAbstractRayCasterPrivate::dispatchHits(const QAbstractRayCaster::Hits &hits) { Q_Q(QAbstractRayCaster); diff --git a/src/render/picking/qabstractraycaster_p.h b/src/render/picking/qabstractraycaster_p.h index 230832994..aef054938 100644 --- a/src/render/picking/qabstractraycaster_p.h +++ b/src/render/picking/qabstractraycaster_p.h @@ -88,6 +88,7 @@ public: QAbstractRayCaster::FilterMode m_filterMode = QAbstractRayCaster::AcceptAnyMatchingLayers; QList<QLayer *> m_layers; + QAbstractRayCaster::Hits pick(); virtual void dispatchHits(const QAbstractRayCaster::Hits &hits); Q_DECLARE_PUBLIC(QAbstractRayCaster) diff --git a/src/render/picking/qraycaster.cpp b/src/render/picking/qraycaster.cpp index f32ea32f1..1f418b4c8 100644 --- a/src/render/picking/qraycaster.cpp +++ b/src/render/picking/qraycaster.cpp @@ -203,6 +203,16 @@ void QRayCaster::trigger(const QVector3D &origin, const QVector3D &direction, fl setEnabled(true); } +QAbstractRayCaster::Hits QRayCaster::pick(const QVector3D &origin, const QVector3D &direction, float length) +{ + setOrigin(origin); + setDirection(direction); + setLength(length); + + auto d = QAbstractRayCasterPrivate::get(this); + return d->pick(); +} + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/picking/qraycaster.h b/src/render/picking/qraycaster.h index b565c2c25..950579068 100644 --- a/src/render/picking/qraycaster.h +++ b/src/render/picking/qraycaster.h @@ -72,6 +72,8 @@ public Q_SLOTS: void trigger(); void trigger(const QVector3D& origin, const QVector3D& direction, float length); + Hits pick(const QVector3D& origin, const QVector3D& direction, float length); + Q_SIGNALS: void originChanged(const QVector3D &origin); void directionChanged(const QVector3D &direction); diff --git a/src/render/picking/qraycasterhit.cpp b/src/render/picking/qraycasterhit.cpp index 6e81c05d0..1a253dfb5 100644 --- a/src/render/picking/qraycasterhit.cpp +++ b/src/render/picking/qraycasterhit.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qraycasterhit.h" +#include <Qt3DCore/qentity.h> QT_BEGIN_NAMESPACE @@ -50,6 +51,10 @@ public: QRayCasterHitData(QRayCasterHit::HitType type, Qt3DCore::QNodeId id, float distance, const QVector3D &localIntersect, const QVector3D &worldIntersect, uint primitiveIndex, uint v1 = 0, uint v2 = 0, uint v3 = 0); + QRayCasterHitData(const QRayCasterHitData& other) : m_type(other.m_type), m_entityId(other.m_entityId), m_entity(other.m_entity), + m_distance(other.m_distance), m_localIntersection(other.m_localIntersection), + m_worldIntersection(other.m_worldIntersection), m_primitiveIndex(other.m_primitiveIndex), + m_vertex1Index(other.m_vertex1Index), m_vertex2Index(other.m_vertex2Index), m_vertex3Index(other.m_vertex3Index) { } QRayCasterHit::HitType m_type = QRayCasterHit::EntityHit; Qt3DCore::QNodeId m_entityId; @@ -121,7 +126,6 @@ QRayCasterHit::QRayCasterHit(QRayCasterHit::HitType type, Qt3DCore::QNodeId id, uint primitiveIndex, uint v1, uint v2, uint v3) : d(new QRayCasterHitData(type, id, distance, localIntersect, worldIntersect, primitiveIndex, v1, v2, v3)) { - } QRayCasterHit::QRayCasterHit(const QRayCasterHit &other) @@ -221,6 +225,38 @@ uint QRayCasterHit::vertex3Index() const return d->m_vertex3Index; } +QString QRayCasterHit::toString() +{ + QString res; + if (!d->m_entity) + return QLatin1String("{}"); + if (d->m_entity->objectName().length()) + res = d->m_entity->objectName(); + else + res = QLatin1String("Entity"); + + res += QString(QLatin1String(" (%1) Distance: %2 Local: (%3, %4, %5) World: (%6, %7, %8)")) + .arg(d->m_entity->id().id()).arg(double(d->m_distance)) + .arg(double(d->m_localIntersection.x())).arg(double(d->m_localIntersection.y())).arg(double(d->m_localIntersection.z())) + .arg(double(d->m_worldIntersection.x())).arg(double(d->m_worldIntersection.y())).arg(double(d->m_worldIntersection.z())); + + switch (d->m_type) { + case TriangleHit: + res += QString(QLatin1String(" Type: Triangle Index: %1 Vertices: %2 / %3 / %4")).arg(d->m_primitiveIndex).arg(d->m_vertex1Index).arg(d->m_vertex2Index).arg(d->m_vertex3Index); + break; + case LineHit: + res += QString(QLatin1String(" Type: Line Index: %1 Vertices: %2 / %3")).arg(d->m_primitiveIndex).arg(d->m_vertex1Index).arg(d->m_vertex2Index); + break; + case PointHit: + res += QString(QLatin1String(" Type: Point Index: %1")).arg(d->m_primitiveIndex); + break; + case EntityHit: + res += QLatin1String(" Type: Entity"); + break; + } + return res; +} + /*! \internal */ void QRayCasterHit::setEntity(Qt3DCore::QEntity *entity) const { diff --git a/src/render/picking/qraycasterhit.h b/src/render/picking/qraycasterhit.h index 9f62889fd..3b1f64921 100644 --- a/src/render/picking/qraycasterhit.h +++ b/src/render/picking/qraycasterhit.h @@ -56,6 +56,16 @@ class QAbstractRayCasterPrivate; class Q_3DRENDERSHARED_EXPORT QRayCasterHit { Q_GADGET + Q_PROPERTY(QRayCasterHit::HitType type READ type CONSTANT) + Q_PROPERTY(Qt3DCore::QNodeId entityId READ entityId CONSTANT) + Q_PROPERTY(Qt3DCore::QEntity *entity READ entity CONSTANT) + Q_PROPERTY(float distance READ distance CONSTANT) + Q_PROPERTY(QVector3D localIntersection READ localIntersection CONSTANT) + Q_PROPERTY(QVector3D worldIntersection READ worldIntersection CONSTANT) + Q_PROPERTY(uint primitiveIndex READ primitiveIndex CONSTANT) + Q_PROPERTY(uint vertex1Index READ vertex1Index CONSTANT) + Q_PROPERTY(uint vertex2Index READ vertex2Index CONSTANT) + Q_PROPERTY(uint vertex3Index READ vertex3Index CONSTANT) public: enum HitType { TriangleHit, @@ -85,6 +95,8 @@ public: uint vertex2Index() const; uint vertex3Index() const; + Q_INVOKABLE QString toString(); + private: friend class QAbstractRayCasterPrivate; void setEntity(Qt3DCore::QEntity *entity) const; diff --git a/src/render/picking/qscreenraycaster.cpp b/src/render/picking/qscreenraycaster.cpp index 3e47c2a01..a8535187f 100644 --- a/src/render/picking/qscreenraycaster.cpp +++ b/src/render/picking/qscreenraycaster.cpp @@ -140,6 +140,14 @@ void QScreenRayCaster::trigger(const QPoint &position) setEnabled(true); } +QAbstractRayCaster::Hits QScreenRayCaster::pick(const QPoint &position) +{ + setPosition(position); + + auto d = QAbstractRayCasterPrivate::get(this); + return d->pick(); +} + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/picking/qscreenraycaster.h b/src/render/picking/qscreenraycaster.h index 216ed47f5..800f5f7f9 100644 --- a/src/render/picking/qscreenraycaster.h +++ b/src/render/picking/qscreenraycaster.h @@ -52,7 +52,6 @@ namespace Qt3DRender { class Q_3DRENDERSHARED_EXPORT QScreenRayCaster : public QAbstractRayCaster { Q_OBJECT - Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged) public: explicit QScreenRayCaster(QNode *parent = nullptr); @@ -65,6 +64,7 @@ public Q_SLOTS: void trigger(); void trigger(const QPoint &position); + Hits pick(const QPoint &position); Q_SIGNALS: void positionChanged(const QPoint &position); diff --git a/tests/manual/raycasting-qml/CMakeLists.txt b/tests/manual/raycasting-qml/CMakeLists.txt index 7b1549f3f..24be78aae 100644 --- a/tests/manual/raycasting-qml/CMakeLists.txt +++ b/tests/manual/raycasting-qml/CMakeLists.txt @@ -21,7 +21,16 @@ qt_add_manual_test(raycasting-qml # Resources: set(raycasting-qml_resource_files - "main.qml" + main.qml + CylinderEntity.qml + LineEntity.qml + LineMaterial.qml +) +set(raycasting-shader_resource_files + shaders/es2/simpleColor.frag + shaders/es2/simpleColor.vert + shaders/gl3/simpleColor.frag + shaders/gl3/simpleColor.vert ) qt_add_resource(raycasting-qml "raycasting-qml" @@ -31,6 +40,13 @@ qt_add_resource(raycasting-qml "raycasting-qml" ${raycasting-qml_resource_files} ) +qt_add_resource(raycasting-qml "shaders" + PREFIX + "/" + FILES + ${raycasting-shader_resource_files} +) +target_sources(raycasting-qml PRIVATE ${raycasting-qml_resource_files} ${raycasting-shader_resource_files}) #### Keys ignored in scope 1:.:.:raycasting-qml.pro:<TRUE>: # OTHER_FILES = "main.qml" diff --git a/tests/manual/raycasting-qml/LineEntity.qml b/tests/manual/raycasting-qml/LineEntity.qml index 6071881f3..62cf911d1 100644 --- a/tests/manual/raycasting-qml/LineEntity.qml +++ b/tests/manual/raycasting-qml/LineEntity.qml @@ -83,7 +83,6 @@ Entity { Buffer { id: vertexBuffer - type: Buffer.VertexBuffer data: buildVertexBufferData(root.origin, root.direction, root.length) } diff --git a/tests/manual/raycasting-qml/main.qml b/tests/manual/raycasting-qml/main.qml index c6cc8445f..33aa96752 100644 --- a/tests/manual/raycasting-qml/main.qml +++ b/tests/manual/raycasting-qml/main.qml @@ -121,6 +121,10 @@ Entity { if (event.text.toLowerCase() == "s") { raycaster.origin.y += .1; raycaster.trigger() } if (event.text.toLowerCase() == "d") { raycaster.origin.y -= .1; raycaster.trigger() } } + onSpacePressed: { + var syncHits = raycaster.pick(raycaster.origin, raycaster.direction, raycaster.length) + printHits("Synchronous hits", syncHits) + } } components: [ external_forward_renderer, inputSettings, headLight, raycaster, screenRayCaster, mouseHandler, kbHandler ] |