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); |
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 | protected: |
133 | void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; |
134 | QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override; |
135 | void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override; |
136 | |
137 | bool event(QEvent *) override; |
138 | void componentComplete() override; |
139 | |
140 | public Q_SLOTS: |
141 | void setCamera(QQuick3DCamera *camera); |
142 | void setEnvironment(QQuick3DSceneEnvironment * environment); |
143 | void setImportScene(QQuick3DNode *inScene); |
144 | void setRenderMode(QQuick3DViewport::RenderMode renderMode); |
145 | #if QT_CONFIG(quick_shadereffect) |
146 | Q_REVISION(6, 4) void setRenderFormat(QQuickShaderEffectSource::Format format); |
147 | #endif |
148 | Q_REVISION(6, 7) void setExplicitTextureWidth(int width); |
149 | Q_REVISION(6, 7) void setExplicitTextureHeight(int height); |
150 | void cleanupDirectRenderer(); |
151 | |
152 | // Setting this true enables picking for all the models, regardless of |
153 | // the models pickable property. |
154 | void setGlobalPickingEnabled(bool isEnabled); |
155 | |
156 | private Q_SLOTS: |
157 | void invalidateSceneGraph(); |
158 | void updateInputProcessing(); |
159 | void onReleaseCachedResources(); |
160 | |
161 | Q_SIGNALS: |
162 | void cameraChanged(); |
163 | void environmentChanged(); |
164 | void sceneChanged(); |
165 | void importSceneChanged(); |
166 | void renderModeChanged(); |
167 | Q_REVISION(6, 4) void renderFormatChanged(); |
168 | Q_REVISION(6, 7) void explicitTextureWidthChanged(); |
169 | Q_REVISION(6, 7) void explicitTextureHeightChanged(); |
170 | Q_REVISION(6, 7) void effectiveTextureSizeChanged(); |
171 | |
172 | private: |
173 | void setMultiViewCameras(QQuick3DCamera **firstCamera, int count); |
174 | template <size_t N> |
175 | void setMultiViewCameras(QQuick3DCamera *(&cameras)[N]) |
176 | { |
177 | static_assert(N > 1, "Use setCamera for single view" ); |
178 | setMultiViewCameras(cameras, N); |
179 | } |
180 | |
181 | friend class QQuick3DExtensionListHelper; |
182 | friend class QQuick3DXrManager; |
183 | friend class QQuick3DXrManagerPrivate; |
184 | friend class QQuick3DRenderLayerHelpers; |
185 | |
186 | Q_DISABLE_COPY(QQuick3DViewport) |
187 | struct SubsceneInfo { |
188 | QQuick3DObject* obj = nullptr; |
189 | QVarLengthArray<QPointF, 16> eventPointScenePositions; |
190 | }; |
191 | QQuick3DSceneRenderer *getRenderer() const; |
192 | void updateDynamicTextures(); |
193 | QSGNode *setupOffscreenRenderer(QSGNode *node); |
194 | QSGNode *setupInlineRenderer(QSGNode *node); |
195 | void setupDirectRenderer(RenderMode mode); |
196 | bool checkIsVisible() const; |
197 | bool internalPick(QPointerEvent *event, const QVector3D &origin = QVector3D(), const QVector3D &direction = QVector3D()) const; |
198 | QPair<QQuickItem *, QPointF> getItemAndPosition(const QSSGRenderPickResult &pickResult); |
199 | QVarLengthArray<QSSGRenderPickResult, 20> getPickResults(QQuick3DSceneRenderer *renderer, const QVector3D &origin, const QVector3D &direction) const; |
200 | QVarLengthArray<QSSGRenderPickResult, 20> getPickResults(QQuick3DSceneRenderer *renderer, const QEventPoint &eventPoint) const; |
201 | bool forwardEventToSubscenes(QPointerEvent *event, |
202 | bool useRayPicking, |
203 | QQuick3DSceneRenderer *renderer, |
204 | const QFlatMap<QQuickItem *, SubsceneInfo> &visitedSubscenes) const; |
205 | |
206 | void processPickedObject(const QSSGRenderPickResult &pickResult, |
207 | int pointIndex, |
208 | QPointerEvent *event, |
209 | QFlatMap<QQuickItem *, SubsceneInfo> &vistedSubscenes) const; |
210 | QQuickItem *getSubSceneRootItem(QQuick3DMaterial *material) const; |
211 | QQuick3DPickResult getNearestPickResult(const QVarLengthArray<QSSGRenderPickResult, 20> &pickResults) const; |
212 | QQuick3DPickResult processPickResult(const QSSGRenderPickResult &pickResult) const; |
213 | QQuick3DObject *findFrontendNode(const QSSGRenderGraphObject *backendObject) const; |
214 | QQuick3DSceneManager *findChildSceneManager(QQuick3DObject *inObject, QQuick3DSceneManager *manager = nullptr); |
215 | QQuick3DCamera *m_camera = nullptr; |
216 | QVarLengthArray<QQuick3DCamera *, 2> m_multiViewCameras; |
217 | QQuick3DSceneEnvironment *m_environment = nullptr; |
218 | QQuick3DSceneRootNode *m_sceneRoot = nullptr; |
219 | QQuick3DNode *m_importScene = nullptr; |
220 | mutable SGFramebufferObjectNode *m_node = nullptr; |
221 | mutable QQuick3DSGRenderNode *m_renderNode = nullptr; |
222 | mutable QQuick3DSGDirectRenderer *m_directRenderer = nullptr; |
223 | bool m_renderModeDirty = false; |
224 | RenderMode m_renderMode = Offscreen; |
225 | #if QT_CONFIG(quick_shadereffect) |
226 | QQuickShaderEffectSource::Format m_renderFormat = QQuickShaderEffectSource::RGBA8; |
227 | #endif |
228 | int m_explicitTextureWidth = 0; |
229 | int m_explicitTextureHeight = 0; |
230 | QSize m_effectiveTextureSize; |
231 | float m_widthMultiplier = 1.0f; |
232 | float m_heightMultiplier = 1.0f; |
233 | QQuick3DRenderStats *m_renderStats = nullptr; |
234 | bool m_enableInputProcessing = false; |
235 | QQuick3DLightmapBaker *m_lightmapBaker = nullptr; |
236 | QList<QQuick3DObject *> m_extensions; |
237 | bool m_extensionListDirty = false; |
238 | |
239 | struct TouchState { |
240 | QQuickItem *target = nullptr; |
241 | QPointF position; |
242 | bool isPressed = false; |
243 | }; |
244 | QPointingDevice *m_syntheticTouchDevice = nullptr; |
245 | QVarLengthArray<TouchState, 2> m_touchState{2}; |
246 | |
247 | QPointer<QQuickItem> m_prevMouseItem = nullptr; |
248 | QPointF m_prevMousePos; |
249 | |
250 | Q_QUICK3D_PROFILE_ID |
251 | }; |
252 | |
253 | QT_END_NAMESPACE |
254 | |
255 | #endif // QSSGVIEW3D_H |
256 | |