| 1 | // Copyright (C) 2019 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
| 3 | |
| 4 | #ifndef QSSGVIEW3D_H |
| 5 | #define QSSGVIEW3D_H |
| 6 | |
| 7 | // |
| 8 | // W A R N I N G |
| 9 | // ------------- |
| 10 | // |
| 11 | // This file is not part of the Qt API. It exists purely as an |
| 12 | // implementation detail. This header file may change from version to |
| 13 | // version without notice, or even be removed. |
| 14 | // |
| 15 | // We mean it. |
| 16 | // |
| 17 | |
| 18 | #include <QtQuick/QQuickItem> |
| 19 | #include <QtCore/qurl.h> |
| 20 | |
| 21 | #include <QtQuick3D/qtquick3dglobal.h> |
| 22 | #include <QtQuick3D/private/qquick3dpickresult_p.h> |
| 23 | #if QT_CONFIG(quick_shadereffect) |
| 24 | #include <QtQuick/private/qquickshadereffectsource_p.h> |
| 25 | #endif |
| 26 | |
| 27 | #include <QtQuick3DRuntimeRender/private/qssgrenderpickresult_p.h> |
| 28 | |
| 29 | #include "qquick3dsceneenvironment_p.h" |
| 30 | #include "qquick3drenderstats_p.h" |
| 31 | #include "qquick3dlightmapbaker_p.h" |
| 32 | |
| 33 | QT_BEGIN_NAMESPACE |
| 34 | |
| 35 | class QSSGView3DPrivate; |
| 36 | class QQuick3DCamera; |
| 37 | class QQuick3DSceneEnvironment; |
| 38 | class QQuick3DNode; |
| 39 | class QQuick3DSceneRootNode; |
| 40 | class QQuick3DSceneRenderer; |
| 41 | class QQuick3DRenderStats; |
| 42 | class QQuick3DSceneManager; |
| 43 | |
| 44 | class SGFramebufferObjectNode; |
| 45 | class QQuick3DSGRenderNode; |
| 46 | class QQuick3DSGDirectRenderer; |
| 47 | |
| 48 | class Q_QUICK3D_EXPORT QQuick3DViewport : public QQuickItem |
| 49 | { |
| 50 | Q_OBJECT |
| 51 | Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false FINAL) |
| 52 | Q_PROPERTY(QQuick3DCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged FINAL) |
| 53 | Q_PROPERTY(QQuick3DSceneEnvironment *environment READ environment WRITE setEnvironment NOTIFY environmentChanged FINAL) |
| 54 | Q_PROPERTY(QQuick3DNode *scene READ scene NOTIFY sceneChanged) |
| 55 | Q_PROPERTY(QQuick3DNode *importScene READ importScene WRITE setImportScene NOTIFY importSceneChanged FINAL) |
| 56 | Q_PROPERTY(RenderMode renderMode READ renderMode WRITE setRenderMode NOTIFY renderModeChanged FINAL) |
| 57 | #if QT_CONFIG(quick_shadereffect) |
| 58 | Q_PROPERTY(QQuickShaderEffectSource::Format renderFormat READ renderFormat WRITE setRenderFormat NOTIFY renderFormatChanged FINAL REVISION(6, 4)) |
| 59 | #endif |
| 60 | Q_PROPERTY(QQuick3DRenderStats *renderStats READ renderStats CONSTANT) |
| 61 | Q_PROPERTY(QQmlListProperty<QQuick3DObject> extensions READ extensions FINAL REVISION(6, 6)) |
| 62 | Q_PROPERTY(int explicitTextureWidth READ explicitTextureWidth WRITE setExplicitTextureWidth NOTIFY explicitTextureWidthChanged FINAL REVISION(6, 7)) |
| 63 | Q_PROPERTY(int explicitTextureHeight READ explicitTextureHeight WRITE setExplicitTextureHeight NOTIFY explicitTextureHeightChanged FINAL REVISION(6, 7)) |
| 64 | Q_PROPERTY(QSize effectiveTextureSize READ effectiveTextureSize NOTIFY effectiveTextureSizeChanged FINAL REVISION(6, 7)) |
| 65 | Q_CLASSINFO("DefaultProperty" , "data" ) |
| 66 | |
| 67 | QML_NAMED_ELEMENT(View3D) |
| 68 | |
| 69 | public: |
| 70 | enum RenderMode { |
| 71 | Offscreen, |
| 72 | Underlay, |
| 73 | Overlay, |
| 74 | Inline |
| 75 | }; |
| 76 | Q_ENUM(RenderMode) |
| 77 | |
| 78 | explicit QQuick3DViewport(QQuickItem *parent = nullptr); |
| 79 | ~QQuick3DViewport() override; |
| 80 | |
| 81 | QQmlListProperty<QObject> data(); |
| 82 | |
| 83 | QQuick3DCamera *camera() const; |
| 84 | QQuick3DSceneEnvironment *environment() const; |
| 85 | QQuick3DNode *scene() const; |
| 86 | QQuick3DNode *importScene() const; |
| 87 | RenderMode renderMode() const; |
| 88 | #if QT_CONFIG(quick_shadereffect) |
| 89 | Q_REVISION(6, 4) QQuickShaderEffectSource::Format renderFormat() const; |
| 90 | #endif |
| 91 | QQuick3DRenderStats *renderStats() const; |
| 92 | |
| 93 | QQuick3DSceneRenderer *createRenderer() const; |
| 94 | |
| 95 | bool isTextureProvider() const override; |
| 96 | QSGTextureProvider *textureProvider() const override; |
| 97 | void releaseResources() override; |
| 98 | |
| 99 | Q_INVOKABLE QVector3D mapFrom3DScene(const QVector3D &scenePos) const; |
| 100 | Q_INVOKABLE QVector3D mapTo3DScene(const QVector3D &viewPos) const; |
| 101 | |
| 102 | Q_INVOKABLE QQuick3DPickResult pick(float x, float y) const; |
| 103 | Q_REVISION(6, 8) Q_INVOKABLE QQuick3DPickResult pick(float x, float y, QQuick3DModel *model) const; |
| 104 | Q_REVISION(6, 8) Q_INVOKABLE QList<QQuick3DPickResult> pickSubset(float x, float y, const QJSValue &models) const; |
| 105 | Q_REVISION(6, 2) Q_INVOKABLE QList<QQuick3DPickResult> pickAll(float x, float y) const; |
| 106 | Q_REVISION(6, 2) Q_INVOKABLE QQuick3DPickResult rayPick(const QVector3D &origin, const QVector3D &direction) const; |
| 107 | Q_REVISION(6, 2) Q_INVOKABLE QList<QQuick3DPickResult> rayPickAll(const QVector3D &origin, const QVector3D &direction) const; |
| 108 | |
| 109 | void processPointerEventFromRay(const QVector3D &origin, const QVector3D &direction, QPointerEvent *event) const; |
| 110 | bool singlePointPick(QSinglePointEvent *event, const QVector3D &origin, const QVector3D &direction); |
| 111 | |
| 112 | Q_REVISION(6, 8) Q_INVOKABLE void setTouchpoint(QQuickItem *target, const QPointF &position, int pointId, bool active); |
| 113 | |
| 114 | QQuick3DLightmapBaker *maybeLightmapBaker(); |
| 115 | QQuick3DLightmapBaker *lightmapBaker(); |
| 116 | |
| 117 | Q_INVOKABLE void bakeLightmap(); |
| 118 | |
| 119 | QQmlListProperty<QQuick3DObject> extensions(); |
| 120 | |
| 121 | Q_REVISION(6, 7) int explicitTextureWidth() const; |
| 122 | Q_REVISION(6, 7) int explicitTextureHeight() const; |
| 123 | Q_REVISION(6, 7) QSize effectiveTextureSize() const; |
| 124 | |
| 125 | // Private helpers |
| 126 | [[nodiscard]] bool extensionListDirty() const { return m_extensionListDirty; } |
| 127 | [[nodiscard]] const QList<QQuick3DObject *> &extensionList() const { return m_extensions; } |
| 128 | void clearExtensionListDirty() { m_extensionListDirty = false; } |
| 129 | |
| 130 | Q_REVISION(6, 7) Q_INVOKABLE void rebuildExtensionList(); |
| 131 | |
| 132 | enum class PrivateInstanceType : quint8 { XrViewInstance = 1 }; |
| 133 | explicit QQuick3DViewport(PrivateInstanceType type, QQuickItem *parent = nullptr); |
| 134 | [[nodiscard]] bool isXrViewInstance() const { return m_isXrViewInstance; } |
| 135 | |
| 136 | static void updateCameraForLayer(const QQuick3DViewport &view3D, QSSGRenderLayer &layerNode); |
| 137 | |
| 138 | protected: |
| 139 | void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; |
| 140 | QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override; |
| 141 | void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override; |
| 142 | |
| 143 | bool event(QEvent *) override; |
| 144 | void componentComplete() override; |
| 145 | |
| 146 | public Q_SLOTS: |
| 147 | void setCamera(QQuick3DCamera *camera); |
| 148 | void setEnvironment(QQuick3DSceneEnvironment * environment); |
| 149 | void setImportScene(QQuick3DNode *inScene); |
| 150 | void setRenderMode(QQuick3DViewport::RenderMode renderMode); |
| 151 | #if QT_CONFIG(quick_shadereffect) |
| 152 | Q_REVISION(6, 4) void setRenderFormat(QQuickShaderEffectSource::Format format); |
| 153 | #endif |
| 154 | Q_REVISION(6, 7) void setExplicitTextureWidth(int width); |
| 155 | Q_REVISION(6, 7) void setExplicitTextureHeight(int height); |
| 156 | void cleanupDirectRenderer(); |
| 157 | |
| 158 | // Setting this true enables picking for all the models, regardless of |
| 159 | // the models pickable property. |
| 160 | void setGlobalPickingEnabled(bool isEnabled); |
| 161 | |
| 162 | private Q_SLOTS: |
| 163 | void invalidateSceneGraph(); |
| 164 | void updateInputProcessing(); |
| 165 | void onReleaseCachedResources(); |
| 166 | |
| 167 | Q_SIGNALS: |
| 168 | void cameraChanged(); |
| 169 | void environmentChanged(); |
| 170 | void sceneChanged(); |
| 171 | void importSceneChanged(); |
| 172 | void renderModeChanged(); |
| 173 | Q_REVISION(6, 4) void renderFormatChanged(); |
| 174 | Q_REVISION(6, 7) void explicitTextureWidthChanged(); |
| 175 | Q_REVISION(6, 7) void explicitTextureHeightChanged(); |
| 176 | Q_REVISION(6, 7) void effectiveTextureSizeChanged(); |
| 177 | |
| 178 | private: |
| 179 | void setMultiViewCameras(QQuick3DCamera **firstCamera, int count); |
| 180 | template <size_t N> |
| 181 | void setMultiViewCameras(QQuick3DCamera *(&cameras)[N]) |
| 182 | { |
| 183 | static_assert(N > 1, "Use setCamera for single view" ); |
| 184 | setMultiViewCameras(cameras, N); |
| 185 | } |
| 186 | |
| 187 | friend class QQuick3DExtensionListHelper; |
| 188 | friend class QQuick3DXrManager; |
| 189 | friend class QQuick3DXrManagerPrivate; |
| 190 | friend class QQuick3DRenderLayerHelpers; |
| 191 | |
| 192 | Q_DISABLE_COPY(QQuick3DViewport) |
| 193 | struct SubsceneInfo { |
| 194 | QQuick3DObject* obj = nullptr; |
| 195 | QVarLengthArray<QPointF, 16> eventPointScenePositions; |
| 196 | }; |
| 197 | QQuick3DSceneRenderer *getRenderer() const; |
| 198 | void updateDynamicTextures(); |
| 199 | QSGNode *setupOffscreenRenderer(QSGNode *node); |
| 200 | QSGNode *setupInlineRenderer(QSGNode *node); |
| 201 | void setupDirectRenderer(RenderMode mode); |
| 202 | bool checkIsVisible() const; |
| 203 | bool internalPick(QPointerEvent *event, const QVector3D &origin = QVector3D(), const QVector3D &direction = QVector3D()) const; |
| 204 | QPair<QQuickItem *, QPointF> getItemAndPosition(const QSSGRenderPickResult &pickResult); |
| 205 | QVarLengthArray<QSSGRenderPickResult, 20> getPickResults(QQuick3DSceneRenderer *renderer, const QVector3D &origin, const QVector3D &direction) const; |
| 206 | QVarLengthArray<QSSGRenderPickResult, 20> getPickResults(QQuick3DSceneRenderer *renderer, const QEventPoint &eventPoint) const; |
| 207 | bool forwardEventToSubscenes(QPointerEvent *event, |
| 208 | bool useRayPicking, |
| 209 | QQuick3DSceneRenderer *renderer, |
| 210 | const QFlatMap<QQuickItem *, SubsceneInfo> &visitedSubscenes) const; |
| 211 | |
| 212 | void processPickedObject(const QSSGRenderPickResult &pickResult, |
| 213 | int pointIndex, |
| 214 | QPointerEvent *event, |
| 215 | QFlatMap<QQuickItem *, SubsceneInfo> &vistedSubscenes) const; |
| 216 | QQuickItem *getSubSceneRootItem(QQuick3DMaterial *material) const; |
| 217 | QQuick3DPickResult getNearestPickResult(const QVarLengthArray<QSSGRenderPickResult, 20> &pickResults) const; |
| 218 | QQuick3DPickResult processPickResult(const QSSGRenderPickResult &pickResult) const; |
| 219 | QQuick3DObject *findFrontendNode(const QSSGRenderGraphObject *backendObject) const; |
| 220 | QQuick3DSceneManager *findChildSceneManager(QQuick3DObject *inObject, QQuick3DSceneManager *manager = nullptr); |
| 221 | QQuick3DCamera *m_camera = nullptr; |
| 222 | QVarLengthArray<QQuick3DCamera *, 2> m_multiViewCameras; |
| 223 | QQuick3DSceneEnvironment *m_environment = nullptr; |
| 224 | mutable QPointer<QQuick3DSceneEnvironment> m_builtInEnvironment; |
| 225 | QQuick3DSceneRootNode *m_sceneRoot = nullptr; |
| 226 | QQuick3DNode *m_importScene = nullptr; |
| 227 | mutable SGFramebufferObjectNode *m_node = nullptr; |
| 228 | mutable QQuick3DSGRenderNode *m_renderNode = nullptr; |
| 229 | mutable QQuick3DSGDirectRenderer *m_directRenderer = nullptr; |
| 230 | bool m_renderModeDirty = false; |
| 231 | RenderMode m_renderMode = Offscreen; |
| 232 | #if QT_CONFIG(quick_shadereffect) |
| 233 | QQuickShaderEffectSource::Format m_renderFormat = QQuickShaderEffectSource::RGBA8; |
| 234 | #endif |
| 235 | int m_explicitTextureWidth = 0; |
| 236 | int m_explicitTextureHeight = 0; |
| 237 | QSize m_effectiveTextureSize; |
| 238 | float m_widthMultiplier = 1.0f; |
| 239 | float m_heightMultiplier = 1.0f; |
| 240 | QQuick3DRenderStats *m_renderStats = nullptr; |
| 241 | bool m_enableInputProcessing = false; |
| 242 | QQuick3DLightmapBaker *m_lightmapBaker = nullptr; |
| 243 | QList<QQuick3DObject *> m_extensions; |
| 244 | bool m_extensionListDirty = false; |
| 245 | bool m_isXrViewInstance = false; |
| 246 | |
| 247 | struct TouchState { |
| 248 | QQuickItem *target = nullptr; |
| 249 | QPointF position; |
| 250 | bool isPressed = false; |
| 251 | }; |
| 252 | QPointingDevice *m_syntheticTouchDevice = nullptr; |
| 253 | QVarLengthArray<TouchState, 2> m_touchState{2}; |
| 254 | |
| 255 | QPointer<QQuickItem> m_prevMouseItem = nullptr; |
| 256 | QPointF m_prevMousePos; |
| 257 | |
| 258 | Q_QUICK3D_PROFILE_ID |
| 259 | }; |
| 260 | |
| 261 | QT_END_NAMESPACE |
| 262 | |
| 263 | #endif // QSSGVIEW3D_H |
| 264 | |