├── vr-window
├── vr.qrc
├── materials.qrc
├── vr-window.pro
├── main.cpp
├── StereoFrameGraph.qml
└── main.qml
├── qt3d-vr-example.pro
├── .gitignore
├── virtualreality
├── frontend
│ ├── qtrackedtransform.h
│ ├── qtrackedtransform.cpp
│ ├── querytrackedobjectsjob_p.h
│ ├── querytrackedobjectsjob.cpp
│ ├── qvirtualrealityaspect_p.h
│ ├── qvirtualrealityaspect.h
│ ├── qvirtualrealitymesh.h
│ ├── qvirtualrealitymesh.cpp
│ ├── qvirtualrealityaspect.cpp
│ ├── qvirtualrealitycamera.h
│ └── qvirtualrealitycamera.cpp
├── trackedtransform.cpp
├── qt3dvr_global.h
├── trackedtransform_p.h
├── qvirtualrealitygeometry_p.h
├── vrbackends
│ ├── ovr
│ │ ├── framebufferovr.h
│ │ ├── virtualrealityapiovr.h
│ │ ├── framebufferovr.cpp
│ │ └── virtualrealityapiovr.cpp
│ └── openvr
│ │ ├── virtualrealityapiopenvr.h
│ │ └── virtualrealityapiopenvr.cpp
├── qvirtualrealityapi.cpp
├── qvirtualrealitygeometry.h
├── qvirtualrealityapi.h
├── virtualreality.pro
├── qvirtualrealityapi_p.h
├── handler.cpp
├── qheadmounteddisplay.h
├── handler_p.h
├── qvirtualrealityapibackend.h
├── qvirtualrealitygeometry.cpp
└── qheadmounteddisplay.cpp
├── vr-sdks.pri
├── README.md
└── LICENSE
/vr-window/vr.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 | StereoFrameGraph.qml
5 |
6 |
7 |
--------------------------------------------------------------------------------
/qt3d-vr-example.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 | # Needed to ensure that things are built right, which you have to do yourself :(
3 | CONFIG += ordered
4 |
5 | # All the projects in your application are sub-projects of your solution
6 | SUBDIRS = virtualreality \
7 | vr-window
8 |
9 | vr-window.depends = virtualreality
10 |
--------------------------------------------------------------------------------
/vr-window/materials.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 | BasicCamera.qml
5 | TrefoilKnot.qml
6 | PlaneEntity.qml
7 | RenderableEntity.qml
8 | HousePlant.qml
9 | Barrel.qml
10 | Chest.qml
11 | SortedForwardRenderer.qml
12 | Lights.qml
13 |
14 |
15 |
--------------------------------------------------------------------------------
/vr-window/vr-window.pro:
--------------------------------------------------------------------------------
1 | !include( ../vr-sdks.pri ) {
2 | error( "Couldn't find the vr-sdks.pri file!" )
3 | }
4 |
5 | QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras
6 |
7 | CONFIG += link_prl
8 |
9 | HEADERS += \
10 |
11 | SOURCES += \
12 | main.cpp
13 |
14 | OTHER_FILES += \
15 | main.qml \
16 | *.qml
17 |
18 | RESOURCES += \
19 | vr.qrc
20 |
21 | win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../virtualreality/release/ -lvirtualreality
22 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../virtualreality/debug/ -lvirtualreality
23 | else:unix: LIBS += -L$$OUT_PWD/../virtualreality/ -lvirtualreality
24 |
25 | INCLUDEPATH += $$PWD/../virtualreality
26 | DEPENDPATH += $$PWD/../virtualreality
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # https://dev.to/nishina555/how-to-ignore-files-already-managed-with-git-locally-19oo
2 | # skip file as it is user specific
3 | # $ git update-index --skip-worktree vr-sdks.pri ( adjust paths to openvr headers and libs )
4 | # $ git update-index --skip-worktree virtualreality/virtualreality.pro ( adjust openvr lib name )
5 |
6 | # user file
7 | # *.user
8 | qt3d-vr-example.pro.user
9 |
10 | # autosave
11 | *.autosave
12 |
13 |
14 |
15 | # Prerequisites
16 | *.d
17 |
18 | # Compiled Object files
19 | *.slo
20 | *.lo
21 | *.o
22 | *.obj
23 |
24 | # Precompiled Headers
25 | *.gch
26 | *.pch
27 |
28 | # Compiled Dynamic libraries
29 | *.so
30 | *.dylib
31 | *.dll
32 |
33 | # Fortran module files
34 | *.mod
35 | *.smod
36 |
37 | # Compiled Static libraries
38 | *.lai
39 | *.la
40 | *.a
41 | *.lib
42 |
43 | # Executables
44 | *.exe
45 | *.out
46 | *.app
47 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qtrackedtransform.h:
--------------------------------------------------------------------------------
1 | #ifndef QTRACKEDTRANSFORM_H
2 | #define QTRACKEDTRANSFORM_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | QT_BEGIN_NAMESPACE
11 |
12 | namespace Qt3DVirtualReality {
13 |
14 | class QTrackedTransformPrivate;
15 |
16 | //class QTrackedTransform : public Qt3DCore::QComponent
17 | //{
18 | //public:
19 | // QTrackedTransform();
20 |
21 | // // QNode interface
22 | //protected:
23 | // void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
24 | // {
25 | // }
26 |
27 | //private:
28 | // Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const
29 | // {
30 | // }
31 | //};
32 |
33 | } // namespace Qt3DVirtualReality
34 |
35 | QT_END_NAMESPACE
36 |
37 | #endif // QTRACKEDTRANSFORM_H
38 |
--------------------------------------------------------------------------------
/virtualreality/trackedtransform.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "trackedtransform_p.h"
16 |
17 | QT_BEGIN_NAMESPACE
18 |
19 | Qt3DVirtualReality::TrackedTransform::TrackedTransform()
20 | {
21 |
22 | }
23 |
24 | QT_END_NAMESPACE
25 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qtrackedtransform.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "qtrackedtransform.h"
16 |
17 | QT_BEGIN_NAMESPACE
18 |
19 | //Qt3DVirtualReality::QTrackedTransform::QTrackedTransform()
20 | //{
21 |
22 | //}
23 |
24 | QT_END_NAMESPACE
25 |
--------------------------------------------------------------------------------
/vr-sdks.pri:
--------------------------------------------------------------------------------
1 | # Custom Configuration
2 |
3 | ###### OpenVR ######
4 | # Put openvr_api.dll in executable folder
5 | # Incompatible configuration of the dll can be visualized using the tool "dependency walker"
6 |
7 | WITH_VR_SDK_OPENVR = true
8 | VR_SDK_OPENVR_INCLUDE = "D:/devel/openvr/headers"
9 | VR_SDK_OPENVR_LIB_PATH = "D:/devel/openvr/lib/win64"
10 |
11 |
12 | ###### OculusVR ######
13 | # LibOVR.lib compiles with static runtime by default (/MT, /MTd).
14 | # This can be changed by recompiling the lib using visual studio (simple task)
15 | # For 32bit you might add "_ITERATOR_DEBUG_LEVEL=0" under C/C++ -> Preprocessor -> Preprocessordefinitions
16 |
17 | WITH_VR_SDK_OCULUSVR = true
18 | VR_SDK_OCULUSVR_INCLUDE = "D:/devel/OculusSDK/LibOVR/Include"
19 | #VR_SDK_OCULUSVR_LIB_PATH = "D:/devel/OculusSDK/LibOVR/Lib/Windows/x64/Release/VS2015"
20 | VR_SDK_OCULUSVR_LIB_PATH = "D:/devel/OculusSDK/LibOVR/Lib/Windows/x64/Debug/VS2015"
21 |
22 |
23 | ###### OSVR ######
24 | # Not yet implemented
25 |
26 | WITH_VR_SDK_OSVR = false
27 |
28 | ###### OpenXR ######
29 |
30 | WITH_VR_OPENXR = false
31 |
--------------------------------------------------------------------------------
/virtualreality/qt3dvr_global.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DVR_GLOBAL_H
16 | #define QT3DVR_GLOBAL_H
17 |
18 | #include
19 |
20 | QT_BEGIN_NAMESPACE
21 |
22 | #if defined(QT_SHARED) || !defined(QT_STATIC)
23 | # if defined(QT3DVR_LIBRARY)
24 | # define QT3DVR_EXPORT Q_DECL_EXPORT
25 | # else
26 | # define QT3DVR_EXPORT Q_DECL_IMPORT
27 | # endif
28 | #else
29 | # define QT3DVR_EXPORT
30 | #endif
31 |
32 | QT_END_NAMESPACE
33 |
34 | #endif // QT3DVR_GLOBAL_H
35 |
--------------------------------------------------------------------------------
/virtualreality/trackedtransform_p.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef TRACKEDTRANSFORM_P_H
16 | #define TRACKEDTRANSFORM_P_H
17 |
18 | #include
19 |
20 | QT_BEGIN_NAMESPACE
21 |
22 | namespace Qt3DVirtualReality {
23 |
24 | class TrackedTransform : public Qt3DCore::QBackendNode
25 | {
26 | public:
27 | TrackedTransform();
28 |
29 | // QBackendNode interface
30 | protected:
31 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
32 | {
33 | }
34 |
35 | private:
36 | void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
37 | {
38 | }
39 | };
40 |
41 | } //namespace Qt3DVirtualReality
42 |
43 | QT_END_NAMESPACE
44 |
45 | #endif // TRACKEDTRANSFORM_P_H
46 |
--------------------------------------------------------------------------------
/virtualreality/frontend/querytrackedobjectsjob_p.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DVIRTUALREALITY_QUERYTRACKEDPOBJECTS_P_H
16 | #define QT3DVIRTUALREALITY_QUERYTRACKEDPOBJECTS_P_H
17 |
18 | #include
19 |
20 | QT_BEGIN_NAMESPACE
21 |
22 | namespace Qt3DVirtualReality {
23 |
24 | class QVirtualRealityApiBackend;
25 |
26 | class QueryTrackedObjectsJob : public Qt3DCore::QAspectJob
27 | {
28 | public:
29 | QueryTrackedObjectsJob();
30 | void setVirtualRealityApiBackend(QVirtualRealityApiBackend *apibackend);
31 |
32 | void run() Q_DECL_OVERRIDE;
33 |
34 | private:
35 | QVirtualRealityApiBackend *m_apibackend;
36 | };
37 |
38 | } // namespace Qt3DVirtualReality
39 |
40 | QT_END_NAMESPACE
41 |
42 | #endif // QT3DLOGIC_LOGIC_CALLBACKJOB_P_H
43 |
--------------------------------------------------------------------------------
/virtualreality/frontend/querytrackedobjectsjob.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "querytrackedobjectsjob_p.h"
16 |
17 | #include
18 |
19 | #include //TODO: remove DBG
20 |
21 | QT_BEGIN_NAMESPACE
22 |
23 | namespace Qt3DVirtualReality {
24 |
25 | namespace JobTypes {
26 |
27 | enum JobType {
28 | QueryTrackedObjects = 16384
29 | };
30 |
31 | } // JobTypes
32 |
33 | QueryTrackedObjectsJob::QueryTrackedObjectsJob()
34 | : QAspectJob()
35 | , m_apibackend(nullptr)
36 | {
37 | SET_JOB_RUN_STAT_TYPE(this, JobTypes::QueryTrackedObjects, 0);
38 | }
39 |
40 | void QueryTrackedObjectsJob::setVirtualRealityApiBackend(QVirtualRealityApiBackend *apibackend)
41 | {
42 | m_apibackend = apibackend;
43 | }
44 |
45 | void QueryTrackedObjectsJob::run()
46 | {
47 | qDebug() << "TODO:DBG:Running query object tracked vr!";
48 | }
49 |
50 | } // namespace Qt3DVirtualReality
51 |
52 | QT_END_NAMESPACE
53 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qvirtualrealityaspect_p.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DVIRTUALREALITY_QVIRTUALREALITYASPECT_P_H
16 | #define QT3DVIRTUALREALITY_QVIRTUALREALITYASPECT_P_H
17 |
18 | #include "qvirtualrealityaspect.h"
19 | #include
20 | #include
21 | #include "querytrackedobjectsjob_p.h"
22 |
23 | QT_BEGIN_NAMESPACE
24 |
25 | namespace Qt3DVirtualReality {
26 |
27 | class QHeadMountedDisplay;
28 | class QVirtualRealityApi;
29 | class QVirtualRealityApiBackend;
30 |
31 | class QVirtualRealityAspectPrivate : public Qt3DCore::QAbstractAspectPrivate
32 | {
33 | QVirtualRealityAspectPrivate();
34 |
35 | Q_DECLARE_PUBLIC(QVirtualRealityAspect)
36 |
37 | void onEngineAboutToShutdown() Q_DECL_OVERRIDE;
38 | void registerBackendTypes();
39 |
40 | qint64 m_time;
41 | bool m_initialized;
42 | QSharedPointer m_queryTrackedObjectsJob;
43 |
44 |
45 | QHeadMountedDisplay *m_hmd;
46 | //QVirtualRealityApi *m_api;
47 | QVirtualRealityApiBackend *m_apibackend;
48 | };
49 |
50 | } // namespace Qt3DLogic
51 |
52 | QT_END_NAMESPACE
53 |
54 | #endif // QT3DVIRTUALREALITY_QVIRTUALREALITYASPECT_P_H
55 |
--------------------------------------------------------------------------------
/virtualreality/qvirtualrealitygeometry_p.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 |
16 | #ifndef QT3DEXTRAS_QVIRTUALREALITYGEOMETRY_P_H
17 | #define QT3DEXTRAS_QVIRTUALREALITYGEOMETRY_P_H
18 |
19 | #include
20 | #include
21 |
22 | QT_BEGIN_NAMESPACE
23 |
24 | namespace Qt3DRender {
25 |
26 | class QAttribute;
27 | class QBuffer;
28 |
29 | } // namespace Qt3DRender
30 |
31 | namespace Qt3DVirtualReality {
32 |
33 | class QVirtualRealityGeometryPrivate : public Qt3DRender::QGeometryPrivate
34 | {
35 | public:
36 | QVirtualRealityGeometryPrivate();
37 |
38 | void init();
39 |
40 | Q_DECLARE_PUBLIC(QVirtualRealityGeometry)
41 |
42 | int m_trackedObjectIndex;
43 | Qt3DRender::QAttribute *m_positionAttribute;
44 | Qt3DRender::QAttribute *m_normalAttribute;
45 | Qt3DRender::QAttribute *m_texCoordAttribute;
46 | Qt3DRender::QAttribute *m_indexAttribute;
47 | Qt3DRender::QBuffer *m_positionBuffer;
48 | Qt3DRender::QBuffer *m_vertexBuffer;
49 | Qt3DRender::QBuffer *m_indexBuffer;
50 | QVirtualRealityApiBackend *m_apibackend;
51 | };
52 |
53 | } // Qt3DVirtualReality
54 |
55 | QT_END_NAMESPACE
56 |
57 | #endif // QT3DEXTRAS_QVIRTUALREALITYGEOMETRY_P_H
58 |
59 |
--------------------------------------------------------------------------------
/virtualreality/vrbackends/ovr/framebufferovr.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #if(QT3DVR_COMPILE_WITH_OCULUSVR)
16 | #ifndef QVRRENDERTARGET
17 | #define QVRRENDERTARGET
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | //#include "GL/CAPI_GLE.h"
25 | #include "Extras/OVR_Math.h"
26 | #include "OVR_CAPI_GL.h"
27 | #include
28 |
29 | #if defined(_WIN32)
30 | #include // for GetDefaultAdapterLuid
31 | //#pragma comment(lib, "dxgi.lib")
32 | #endif
33 |
34 | using namespace OVR;
35 |
36 | class FramebufferOvr;
37 |
38 | class OvrSwapChain
39 | {
40 | QSize m_texSize;
41 | ovrSession m_session;
42 | //GLuint m_texIdDepthBuffer;
43 | QOpenGLFunctions_3_2_Core *m_funcs;
44 | QVector m_framebuffers;
45 | ovrTextureSwapChain m_textureChain;
46 | public:
47 | OvrSwapChain(ovrSession session, QSize size);
48 | ~OvrSwapChain();
49 |
50 | QSize size() const;
51 | void bindCurrentChainIndexFramebuffer();
52 | void bindFramebuffer(int index);
53 | int chainLength() const;
54 | void commit();
55 | const ovrTextureSwapChain &ovrTextureChain() const;
56 | };
57 |
58 | #endif
59 | #endif
60 |
--------------------------------------------------------------------------------
/vr-window/main.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include "qvirtualrealityapi.h"
22 | #include "qheadmounteddisplay.h"
23 |
24 | int main(int argc, char* argv[])
25 | {
26 | qDebug() << "VR Window demo";
27 | QGuiApplication app(argc, argv);
28 | Qt3DVirtualReality::QVirtualRealityApi::Type requestedVrApi(Qt3DVirtualReality::QVirtualRealityApi::OpenVR);
29 | bool apiAvialable = Qt3DVirtualReality::QVirtualRealityApi::isRuntimeInstalled(requestedVrApi);
30 | if(!apiAvialable)
31 | {
32 | qDebug() << "Vr API not available. Try to choose another VR SDK or recompile with support for other VR SDK.";
33 | return 1;
34 | }
35 | qDebug() << "Starting...";
36 | Qt3DVirtualReality::QVirtualRealityApi vrapi(requestedVrApi);
37 | Qt3DVirtualReality::QHeadMountedDisplayFormat fmt;
38 | Qt3DVirtualReality::QHeadMountedDisplay *hmd(vrapi.getHmd(0, fmt));
39 | if( hmd == nullptr ) {
40 | qDebug() << "Head Mounted disply could not be initialized";
41 | return 1;
42 | }
43 | // Expose the head mounted display as a context property so we can set the aspect ratio
44 | hmd->engine()->qmlEngine()->rootContext()->setContextProperty("_hmd", hmd);
45 | hmd->setSource(QUrl("qrc:/main.qml"));
46 |
47 | hmd->run();
48 | return app.exec();
49 | }
50 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qvirtualrealityaspect.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DVIRTUALREALITY_QVIRTUALREALITYASPECT_H
16 | #define QT3DVIRTUALREALITY_QVIRTUALREALITYASPECT_H
17 |
18 | #include
19 | #include
20 |
21 | QT_BEGIN_NAMESPACE
22 |
23 | namespace Qt3DRender {
24 | class QRenderAspect;
25 | }
26 |
27 | namespace Qt3DVirtualReality {
28 |
29 | class QVirtualRealityAspectPrivate;
30 | class QHeadMountedDisplay;
31 | //class QVirtualRealityApi;
32 | class QVirtualRealityApiBackend;
33 |
34 | //TO DO: might needs access to RenderAspect. UpdateWorldTransformJob must depend on QueryTrackedObjectsJob
35 |
36 | class QT3DVR_EXPORT QVirtualRealityAspect : public Qt3DCore::QAbstractAspect
37 | {
38 | Q_OBJECT
39 | public:
40 | explicit QVirtualRealityAspect(QObject *parent = nullptr);
41 | ~QVirtualRealityAspect();
42 |
43 | void setHeadmountedDisplay(QHeadMountedDisplay *hmd);
44 | //void setVirtualRealityApi(QVirtualRealityApi *api);
45 | void setVirtualRealityApiBackend(QVirtualRealityApiBackend *apiBackend);
46 | private:
47 | QVariant executeCommand(const QStringList &args) Q_DECL_OVERRIDE;
48 | QVector jobsToExecute(qint64 time) Q_DECL_OVERRIDE;
49 | void onRegistered() Q_DECL_OVERRIDE;
50 | void onUnregistered() Q_DECL_OVERRIDE;
51 |
52 | protected:
53 | explicit QVirtualRealityAspect(QVirtualRealityAspectPrivate &dd, QObject *parent);
54 | Q_DECLARE_PRIVATE(QVirtualRealityAspect)
55 | };
56 |
57 | } // namespace Qt3DVirtualReality
58 |
59 | QT_END_NAMESPACE
60 |
61 | #endif // QT3DVIRTUALREALITY_QVIRTUALREALITYASPECT_H
62 |
--------------------------------------------------------------------------------
/virtualreality/qvirtualrealityapi.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "qvirtualrealityapi.h"
16 | #include "qheadmounteddisplay.h"
17 | #include "qvirtualrealityapi_p.h"
18 |
19 | #include
20 | namespace Qt3DVirtualReality {
21 |
22 | QVirtualRealityApi::QVirtualRealityApi(Qt3DVirtualReality::QVirtualRealityApi::Type type)
23 | : QVirtualRealityApi()
24 | {
25 | Q_D(QVirtualRealityApi);
26 | d->setType(type);
27 | }
28 |
29 | QVirtualRealityApi::QVirtualRealityApi()
30 | : Qt3DVirtualReality::QVirtualRealityApi(*new Qt3DVirtualReality::QVirtualRealityApiPrivate)
31 | {}
32 |
33 |
34 | QVirtualRealityApi::QVirtualRealityApi(Qt3DVirtualReality::QVirtualRealityApiPrivate &dd, QObject *parent)
35 | : QObject(dd, parent)
36 | {}
37 |
38 | QVirtualRealityApi::~QVirtualRealityApi()
39 | {
40 | Q_D(QVirtualRealityApi);
41 | d->m_apibackend->shutdown();
42 | }
43 |
44 | bool QVirtualRealityApi::isHmdPresent()
45 | {
46 | Q_D(QVirtualRealityApi);
47 | return d->m_apibackend->isHmdPresent();
48 | }
49 |
50 | bool QVirtualRealityApi::isRuntimeInstalled(Qt3DVirtualReality::QVirtualRealityApi::Type type)
51 | {
52 | return QVirtualRealityApiPrivate::isRuntimeInstalled(type);
53 | }
54 |
55 | QHeadMountedDisplay* QVirtualRealityApi::getHmd(int hmdId, const QHeadMountedDisplayFormat &format)
56 | {
57 | Q_D(QVirtualRealityApi);
58 | Qt3DVirtualReality::QHeadMountedDisplay *hmd(new Qt3DVirtualReality::QHeadMountedDisplay(hmdId, format, this, d->m_apibackend));
59 | hmd->context()->makeCurrent(static_cast(hmd->surface()));
60 | d->initialize();
61 | return hmd;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qvirtualrealitymesh.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QVIRTUALREALITYMESH_H
16 | #define QVIRTUALREALITYMESH_H
17 |
18 | #include
19 | #include
20 |
21 | QT_BEGIN_NAMESPACE
22 |
23 | namespace Qt3DVirtualReality {
24 |
25 | class QVirtualRealityApiBackend; //TO DO: temp
26 |
27 | class QT3DVR_EXPORT QVirtualRealityMesh : public Qt3DRender::QGeometryRenderer
28 | {
29 | Q_OBJECT
30 | Q_PROPERTY(int trackedObjectId READ trackedObjectId WRITE setTrackedObjectId NOTIFY trackedObjectIdChanged)
31 | public:
32 | explicit QVirtualRealityMesh(Qt3DCore::QNode *parent = nullptr);
33 | ~QVirtualRealityMesh();
34 |
35 | int trackedObjectId() const;
36 |
37 | void setVrApiBackendTmp(QVirtualRealityApiBackend *apibackend); //TO DO: temp
38 |
39 | public Q_SLOTS:
40 |
41 | void setTrackedObjectId(int trackedObjectId);
42 |
43 | Q_SIGNALS:
44 |
45 | void trackedObjectIdChanged(int trackedObjectId);
46 |
47 | private:
48 | // As this is a default provided geometry renderer, no one should be able
49 | // to modify the QGeometryRenderer's properties
50 |
51 | void setInstanceCount(int instanceCount);
52 | void setVertexCount(int vertexCount);
53 | void setIndexOffset(int indexOffset);
54 | void setFirstInstance(int firstInstance);
55 | void setRestartIndexValue(int index);
56 | void setPrimitiveRestartEnabled(bool enabled);
57 | void setGeometry(Qt3DRender::QGeometry *geometry);
58 | void setPrimitiveType(PrimitiveType primitiveType);
59 | int m_trackedObjectId;
60 | };
61 |
62 | } // namespace Qt3DVirtualReality
63 |
64 | QT_END_NAMESPACE
65 |
66 | #endif // QVIRTUALREALITYMESH_H
67 |
--------------------------------------------------------------------------------
/virtualreality/vrbackends/ovr/virtualrealityapiovr.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #if(QT3DVR_COMPILE_WITH_OCULUSVR)
16 | #ifndef VIRTUALREALITYAPIOVR_H
17 | #define VIRTUALREALITYAPIOVR_H
18 | #include "../../qvirtualrealityapibackend.h"
19 | #include "OVR_CAPI_GL.h"
20 |
21 | class OvrSwapChain;
22 |
23 | class VirtualRealityApiOvr : public Qt3DVirtualReality::QVirtualRealityApiBackend
24 | {
25 | public:
26 | static bool isRuntimeInstalled();
27 | VirtualRealityApiOvr();
28 | ~VirtualRealityApiOvr();
29 | bool isHmdPresent();
30 |
31 | void initialize();
32 | void shutdown();
33 | bool bindFrambufferObject(int hmdId);
34 |
35 | qreal refreshRate(int hmdId) const;
36 | QMatrix4x4 headPose(int hmdId);
37 | QSize getRenderTargetSize();
38 |
39 | int timeUntilNextFrame();
40 |
41 | void swapToHeadset();
42 |
43 | void getEyeMatrices(QMatrix4x4 &leftEye, QMatrix4x4 &rightEye);
44 |
45 | void getProjectionMatrices(QMatrix4x4 &leftProjection, QMatrix4x4 &rightProjection);
46 |
47 | QList currentlyTrackedObjects();
48 | void getTrackedObject(int id, QMatrix4x4 &transform);
49 | TrackedObjectType getTrackedObjectType(int id);
50 | void getTrackedObjectModel(int id, QVector &vertices, QVector &indices, QOpenGLTexture *texture);
51 |
52 | void getMirrorTexture(QOpenGLTexture *outMirrorTexture);
53 |
54 | bool isTriggerTmp();
55 | private:
56 | bool m_sessionStarted;
57 | ovrSession m_session;
58 | ovrGraphicsLuid m_luid;
59 | //TO DO: decouple using hmdId
60 | ovrHmdDesc m_hmdDesc;
61 | ovrPosef m_eyeRenderPose[2];
62 | double m_sensorSampleTime;
63 | long long m_frameIndex;
64 | OvrSwapChain *m_swapChain;
65 |
66 | bool initializeIfHmdIsPresent();
67 | };
68 |
69 | #endif
70 | #endif
71 |
--------------------------------------------------------------------------------
/virtualreality/qvirtualrealitygeometry.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DEXTRAS_QVIRTUALREALITYGEOMETRY_H
16 | #define QT3DEXTRAS_QVIRTUALREALITYGEOMETRY_H
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | QT_BEGIN_NAMESPACE
23 |
24 | namespace Qt3DRender {
25 | class QAttribute;
26 | } // Render
27 |
28 | namespace Qt3DVirtualReality {
29 |
30 | class QVirtualRealityGeometryPrivate;
31 |
32 | class QT3DVR_EXPORT QVirtualRealityGeometry : public Qt3DRender::QGeometry
33 | {
34 | Q_OBJECT
35 | Q_PROPERTY(int trackedObjectIndex READ trackedObjectIndex WRITE setTrackedObjectIndex NOTIFY trackedObjectIndexChanged)
36 | Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT)
37 | Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT)
38 | Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT)
39 | Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT)
40 |
41 | public:
42 | explicit QVirtualRealityGeometry(QNode *parent = nullptr);
43 | ~QVirtualRealityGeometry();
44 |
45 | void updateVertices();
46 | void updateIndices();
47 |
48 | //TO DO: this should be there e.g. through backend/aspects
49 | void setVrApiBackendTmp(QVirtualRealityApiBackend *apibackend);
50 |
51 | int trackedObjectIndex() const;
52 | Qt3DRender::QAttribute *positionAttribute() const;
53 | Qt3DRender::QAttribute *normalAttribute() const;
54 | Qt3DRender::QAttribute *texCoordAttribute() const;
55 | Qt3DRender::QAttribute *indexAttribute() const;
56 |
57 | public Q_SLOTS:
58 | void setTrackedObjectIndex(int trackedObjectIndex);
59 |
60 | Q_SIGNALS:
61 | void trackedObjectIndexChanged(int trackedObjectIndex);
62 |
63 | protected:
64 | QVirtualRealityGeometry(QVirtualRealityGeometryPrivate &dd, QNode *parent = nullptr);
65 |
66 | private:
67 | Q_DECLARE_PRIVATE(QVirtualRealityGeometry)
68 | };
69 |
70 | } // namespace Qt3DVirtualReality
71 |
72 | QT_END_NAMESPACE
73 |
74 | #endif // QT3DEXTRAS_QVIRTUALREALITYGEOMETRY_H
75 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qvirtualrealitymesh.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "qvirtualrealitymesh.h"
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include "qvirtualrealitygeometry.h"
23 |
24 | QT_BEGIN_NAMESPACE
25 |
26 | namespace Qt3DVirtualReality {
27 |
28 | #ifndef _USE_MATH_DEFINES
29 | # define _USE_MATH_DEFINES // For MSVC
30 | #endif
31 |
32 |
33 | /*!
34 | * \qmltype VirtualrealityMesh
35 | * \instantiates Qt3DVirtualReality::QVirtualRealityMesh
36 | * \inqmlmodule Qt3D.VirtualReality
37 | * \brief A conical mesh.
38 | */
39 |
40 | /*!
41 | * \qmlproperty real VirtualrealityMesh::length
42 | *
43 | * Holds the length.
44 | */
45 |
46 | /*!
47 | * \class Qt3DVirtualReality::QVirtualrealityMesh
48 | * \inheaderfile Qt3DVirtualReality/QVirtualrealityMesh
49 | * \inmodule Qt3DVirtualReality
50 | *
51 | * \inherits Qt3DRender::QGeometryRenderer
52 | *
53 | * \brief A mesh queried from VR SDK.
54 | */
55 |
56 | QVirtualRealityMesh::QVirtualRealityMesh(QNode *parent)
57 | : QGeometryRenderer(parent)
58 | {
59 | QVirtualRealityGeometry *geometry = new QVirtualRealityGeometry(this);
60 | QObject::connect(geometry, &QVirtualRealityGeometry::trackedObjectIndexChanged, this, &QVirtualRealityMesh::trackedObjectIdChanged);
61 |
62 | QGeometryRenderer::setGeometry(geometry);
63 | }
64 |
65 | /*! \internal */
66 | QVirtualRealityMesh::~QVirtualRealityMesh()
67 | {
68 | }
69 |
70 | int QVirtualRealityMesh::trackedObjectId() const
71 | {
72 | return static_cast(geometry())->trackedObjectIndex();
73 | }
74 |
75 | void QVirtualRealityMesh::setVrApiBackendTmp(QVirtualRealityApiBackend *apibackend)
76 | {
77 | static_cast(geometry())->setVrApiBackendTmp(apibackend);
78 | }
79 |
80 | void QVirtualRealityMesh::setTrackedObjectId(int trackedObjectId)
81 | {
82 | static_cast(geometry())->setTrackedObjectIndex(trackedObjectId);
83 | }
84 |
85 | }
86 |
87 | // namespace Qt3DVirtualReality
88 | QT_END_NAMESPACE
89 |
--------------------------------------------------------------------------------
/virtualreality/qvirtualrealityapi.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DVIRTUALREALITYAPI_H
16 | #define QT3DVIRTUALREALITYAPI_H
17 |
18 | #include "qt3dvr_global.h"
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | QT_BEGIN_NAMESPACE
25 |
26 | namespace Qt3DVirtualReality {
27 |
28 | class QHeadMountedDisplay;
29 | class QVirtualRealityApiPrivate;
30 |
31 | class QHeadMountedDisplayFormat {
32 | // void setSize(const QSize& size);
33 | // const QSize& size();
34 | // void setRenderingSurface(GLuint textureId);
35 | // GLuint renderingSurface();
36 | };
37 | /**
38 | * @brief The QVrApi class
39 | * TODO: Uses virtual methods internally to decide which concrete implementation was chosen. Alternatively the public interface could use template parameters.
40 | */
41 | class QT3DVR_EXPORT QVirtualRealityApi : public QObject
42 | {
43 | Q_OBJECT
44 | public:
45 | enum Type
46 | {
47 | OculusVR, // OculusVR
48 | OSVR, // OpenSourceVR (e.g. Razer)
49 | OpenVR // HTC Vive / SteamVR
50 | };
51 |
52 | ///
53 | /// \brief QVirtualRealityApi() Tries to choose the most specific API for the connected HMD.
54 | /// 1) Ovr, 2) OpenVR, 3) OSVR
55 | ///
56 | QVirtualRealityApi();
57 | ///
58 | /// \brief QVirtualRealityApi Initialize with known API of given type
59 | /// \param type
60 | ///
61 | explicit QVirtualRealityApi(QVirtualRealityApi::Type type);
62 | ~QVirtualRealityApi();
63 |
64 | QVirtualRealityApi &operator=(const QVirtualRealityApi &other);
65 |
66 | ///
67 | /// \brief type
68 | /// \return type of API used to connect to the headmounted display
69 | ///
70 | QVirtualRealityApi::Type type() const;
71 |
72 | bool isHmdPresent();
73 | static bool isRuntimeInstalled(QVirtualRealityApi::Type type);
74 | bool supportsSetSurface() const;
75 |
76 | QHeadMountedDisplay *getHmd(int hmdId, const QHeadMountedDisplayFormat &format);
77 |
78 | private:
79 | QVirtualRealityApi(QVirtualRealityApiPrivate &dd, QObject *parent = nullptr);
80 | Q_DECLARE_PRIVATE(QVirtualRealityApi)
81 | };
82 |
83 | }
84 |
85 | QT_END_NAMESPACE
86 |
87 | #endif
88 |
--------------------------------------------------------------------------------
/virtualreality/virtualreality.pro:
--------------------------------------------------------------------------------
1 | !include( ../vr-sdks.pri ) {
2 | error( "Couldn't find the vr-sdks.pri file!" )
3 | }
4 |
5 | TARGET = virtualreality
6 |
7 | TEMPLATE = lib
8 |
9 | DEFINES += QT3DVR_LIBRARY
10 |
11 | #MODULE = virtualreality
12 | QT += qml quick \
13 | core core-private 3dcore 3dcore-private 3drender 3drender-private 3dinput 3dlogic 3dquick \
14 | qml qml-private 3dquick 3drender 3drender-private 3dlogic
15 |
16 | # Qt3D is free of Q_FOREACH - make sure it stays that way:
17 | DEFINES += QT_NO_FOREACH
18 |
19 | #load(qt_module)
20 |
21 | CONFIG += c++11
22 |
23 | # track dependecies
24 | CONFIG += create_prl
25 |
26 | SOURCES += \
27 | vrbackends/ovr/virtualrealityapiovr.cpp \
28 | vrbackends/ovr/framebufferovr.cpp \
29 | vrbackends/openvr/virtualrealityapiopenvr.cpp \
30 | qvirtualrealityapi.cpp \
31 | qheadmounteddisplay.cpp \
32 | frontend/qvirtualrealityaspect.cpp \
33 | frontend/qvirtualrealitycamera.cpp \
34 | frontend/qvirtualrealitymesh.cpp \
35 | frontend/querytrackedobjectsjob.cpp \
36 | qvirtualrealitygeometry.cpp \
37 | handler.cpp \
38 | frontend/qtrackedtransform.cpp \
39 | trackedtransform.cpp
40 |
41 | HEADERS += \
42 | vrbackends/ovr/virtualrealityapiovr.h \
43 | vrbackends/ovr/framebufferovr.h \
44 | vrbackends/openvr/virtualrealityapiopenvr.h \
45 | qvirtualrealityapi.h \
46 | qvirtualrealityapi_p.h \
47 | qvirtualrealityapibackend.h \
48 | qheadmounteddisplay.h \
49 | qt3dvr_global.h \
50 | frontend/qvirtualrealityaspect.h \
51 | frontend/qvirtualrealityaspect_p.h \
52 | frontend/qvirtualrealitycamera.h \
53 | frontend/qvirtualrealitymesh.h \
54 | frontend/querytrackedobjectsjob_p.h \
55 | qvirtualrealitygeometry.h \
56 | qvirtualrealitygeometry_p.h \
57 | handler_p.h \
58 | frontend/qtrackedtransform.h \
59 | trackedtransform_p.h
60 |
61 | ###### OpenVR ######
62 | if($$WITH_VR_SDK_OPENVR) {
63 | message("Building with OpenVR support")
64 | INCLUDEPATH += $$VR_SDK_OPENVR_INCLUDE
65 | LIBS += -L$$VR_SDK_OPENVR_LIB_PATH
66 | LIBS += "$$VR_SDK_OPENVR_LIB_PATH/libopenvr_api.so"
67 | #LIBS += -L$$VR_SDK_OPENVR_LIB_PATH -lopenvr_api
68 | DEFINES+="QT3DVR_COMPILE_WITH_OPENVR=1"
69 | } else {
70 | DEFINES+="QT3DVR_COMPILE_WITH_OPENVR=0"
71 | }
72 |
73 | ###### OculusVR ######
74 | if($$WITH_VR_SDK_OCULUSVR) {
75 | message("Building with Oculus support")
76 | INCLUDEPATH += $$VR_SDK_OCULUSVR_INCLUDE
77 | LIBS += -L$$VR_SDK_OCULUSVR_LIB_PATH -lLibOVR
78 | DEFINES+="QT3DVR_COMPILE_WITH_OCULUSVR=1"
79 | } else {
80 | DEFINES+="QT3DVR_COMPILE_WITH_OCULUSVR=0"
81 | }
82 |
83 | ###### OSVR ######
84 | if($$WITH_VR_SDK_OSVR) {
85 | message("Building with OSVR support")
86 | INCLUDEPATH += $$VR_SDK_OSVR_INCLUDE
87 | LIBS += -L$$VR_SDK_OSVR_LIB_PATH -l
88 | DEFINES+="QT3DVR_COMPILE_WITH_OSVR=1"
89 | } else {
90 | DEFINES+="QT3DVR_COMPILE_WITH_OSVR=0"
91 | }
92 |
93 | win32 {
94 | LIBS += -ldxgi
95 | }
96 |
--------------------------------------------------------------------------------
/virtualreality/qvirtualrealityapi_p.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DVIRTUALREALITYAPI_P_H
16 | #define QT3DVIRTUALREALITYAPI_P_H
17 |
18 | #include "qvirtualrealityapi.h"
19 |
20 | #include
21 | #include
22 | #include "qvirtualrealityapibackend.h"
23 |
24 | #if(QT3DVR_COMPILE_WITH_OCULUSVR)
25 | # include "vrbackends/ovr/virtualrealityapiovr.h"
26 | #endif
27 | #if(QT3DVR_COMPILE_WITH_OPENVR)
28 | # include "vrbackends/openvr/virtualrealityapiopenvr.h"
29 | #endif
30 | #if(QT3DVR_COMPILE_WITH_OSVR)
31 | # include "vrbackends/osvr/vrapiosvr.h"
32 | #endif
33 |
34 | QT_BEGIN_NAMESPACE
35 |
36 | namespace Qt3DVirtualReality {
37 |
38 | class QVirtualRealityApiPrivate : public QObjectPrivate
39 | {
40 | public:
41 |
42 | Q_DECLARE_PUBLIC(QVirtualRealityApi)
43 |
44 | //VrApiBackend
45 | QVirtualRealityApiBackend *m_apibackend;
46 |
47 | void setType(QVirtualRealityApi::Type vendor) {
48 | #if(QT3DVR_COMPILE_WITH_OCULUSVR)
49 | if(QVirtualRealityApi::OculusVR == vendor) {
50 | m_apibackend = new VirtualRealityApiOvr();
51 | return;
52 | }
53 | #endif
54 | #if(QT3DVR_COMPILE_WITH_OPENVR)
55 | if(QVirtualRealityApi::OpenVR == vendor) {
56 | m_apibackend = new VirtualRealityApiOpenVR();
57 | return;
58 | }
59 | #endif
60 | }
61 | static bool isRuntimeInstalled(QVirtualRealityApi::Type vendor) {
62 | #if(QT3DVR_COMPILE_WITH_OCULUSVR)
63 | if(QVirtualRealityApi::OculusVR == vendor) {
64 | return VirtualRealityApiOvr::isRuntimeInstalled();
65 | }
66 | #endif
67 | #if(QT3DVR_COMPILE_WITH_OPENVR)
68 | if(QVirtualRealityApi::OpenVR == vendor) {
69 | return VirtualRealityApiOpenVR::isRuntimeInstalled();
70 | }
71 | #endif
72 | }
73 | void initialize() {
74 | if(!m_initialized) {
75 | Q_ASSERT(m_apibackend != nullptr);
76 | m_apibackend->initialize();
77 | m_initialized = true;
78 | }
79 | }
80 | QVirtualRealityApiPrivate()
81 | : m_apibackend(nullptr)
82 | , m_initialized(false)
83 | {
84 |
85 | }
86 |
87 | ~QVirtualRealityApiPrivate() {
88 | if(m_apibackend)
89 | delete m_apibackend;
90 | }
91 | private:
92 | bool m_initialized;
93 | };
94 |
95 | }
96 |
97 | QT_END_NAMESPACE
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # qt3d-vr-example
2 | Qt3d example with support for OpenVR and OculusVR natively
3 |
4 | ## Setup
5 | Change _vr-sdks.pri_ to fit your directory structure and installation path for vr sdks.
6 | The current implementation uses private headers of Qt3d 5.9.
7 | If the application crashes at startup, it could be that the vr library is incompatible to your build.
8 |
9 | ### OpenVR
10 | You might have to put _openvr_api.dll_ into the executable directory.
11 | Incompatible configurations of the dll with your build can be visualized using the tool "dependency walker".
12 |
13 | ### OculusVR (LibOVR.lib)
14 | Note that the Oculus SDK (LibOVR.lib) is built with incompatible ABI to QtCreator/Visual Studio standard settings.
15 | * LibOVR.lib compiles with static runtime by default (/MT, /MTd).
16 | * Recompiling the lib using is the recommended way to solve this (simple task).
17 | * Visual Studio projects for LibOVR.lib are part of the OculusSDK
18 | * In the Visual Studio Property Pages go to "C/C++ -> Codegeneration -> Runtime Library" and select Multithreaded-Debug (/MTd) for the Debug configuration. (...and /MT for the release config)
19 | * For 32bit you might add "\_ITERATOR_DEBUG_LEVEL=0" under C/C++ -> Preprocessor -> Preprocessordefinitions
20 |
21 | # API
22 |
23 | The project vr-window is an example usage.
24 | The project virtualreality is a library.
25 |
26 | In order to render to the headset, QHeadMountedDisplay must be used in favor of QQuickWindow.
27 | VR Will render only to the Headset. It is not possible to mirror something to the desktop yet (e.g. as a Qml element). This is because VR takes control of the rendering thread. In the future mirroring might be possible, but will very likely use a different Qml scene.
28 |
29 | ```cpp
30 | int main(int argc, char* argv[])
31 | QGuiApplication app(argc, argv);
32 | auto requestedVrApi = QVirtualRealityApi::OculusVR;
33 | bool apiAvialable = QVirtualRealityApi::isRuntimeInstalled(requestedVrApi);
34 | if(!apiAvialable) {
35 | ...
36 | }
37 | QVirtualRealityApi vrapi(requestedVrApi);
38 | QHeadMountedDisplayFormat fmt;
39 | QHeadMountedDisplay *hmd(vrapi.getHmd(0, fmt));
40 | hmd->setSource(QUrl("qrc:/main.qml"));
41 | hmd->run();
42 | return app.exec();
43 | ```
44 |
45 | In the qt3d scene, VrCamera must be used to enable head tracking. Moreover the rendertarget must have two viewports for stereoscopic rendering.
46 |
47 | ```qml
48 | VrCamera {
49 | id: vrCam
50 | offset: Qt.vector3d(80.0,-90.0,0.0)
51 | }
52 | ```
53 |
54 | And in the framegraph the setup looks like this:
55 | ```qml
56 | StereoFrameGraph {
57 | id: stereoFrameGraph
58 | leftCamera: vrCam.leftCamera
59 | rightCamera: vrCam.rightCamera
60 | }
61 | RenderSurfaceSelector {
62 | id: surfaceSelector
63 | externalRenderTargetSize: _hmd.renderTargetSize
64 |
65 | // Draw with left eye
66 | CameraSelector {
67 | camera: vrCam.leftCamera
68 | Viewport {
69 | ...
70 | normalizedRect: Qt.rect(0,0,0.5,1)
71 | }
72 | }
73 |
74 | // Draw with right eye
75 | CameraSelector {
76 | camera: vrCam.rightCamera
77 | Viewport {
78 | ...
79 | normalizedRect: Qt.rect(0.5,0,0.5,1)
80 | }
81 | }
82 | }
83 | ```
84 |
--------------------------------------------------------------------------------
/virtualreality/handler.cpp:
--------------------------------------------------------------------------------
1 | ///****************************************************************************
2 | //**
3 | //** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
4 | //** Contact: https://www.qt.io/licensing/
5 | //**
6 | //** This file is part of the Qt3D module of the Qt Toolkit.
7 | //**
8 | //** $QT_BEGIN_LICENSE:LGPL$
9 | //** Commercial License Usage
10 | //** Licensees holding valid commercial Qt licenses may use this file in
11 | //** accordance with the commercial license agreement provided with the
12 | //** Software or, alternatively, in accordance with the terms contained in
13 | //** a written agreement between you and The Qt Company. For licensing terms
14 | //** and conditions see https://www.qt.io/terms-conditions. For further
15 | //** information use the contact form at https://www.qt.io/contact-us.
16 | //**
17 | //** GNU Lesser General Public License Usage
18 | //** Alternatively, this file may be used under the terms of the GNU Lesser
19 | //** General Public License version 3 as published by the Free Software
20 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 | //** packaging of this file. Please review the following information to
22 | //** ensure the GNU Lesser General Public License version 3 requirements
23 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 | //**
25 | //** GNU General Public License Usage
26 | //** Alternatively, this file may be used under the terms of the GNU
27 | //** General Public License version 2.0 or (at your option) the GNU General
28 | //** Public license version 3 or any later version approved by the KDE Free
29 | //** Qt Foundation. The licenses are as published by the Free Software
30 | //** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 | //** included in the packaging of this file. Please review the following
32 | //** information to ensure the GNU General Public License requirements will
33 | //** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 | //** https://www.gnu.org/licenses/gpl-3.0.html.
35 | //**
36 | //** $QT_END_LICENSE$
37 | //**
38 | //****************************************************************************/
39 |
40 | //#include "handler_p.h"
41 | //#include "manager_p.h"
42 | //#include "managers_p.h"
43 | //#include
44 |
45 | //QT_BEGIN_NAMESPACE
46 |
47 | //namespace Qt3DVirtualReality {
48 |
49 | //Handler::Handler()
50 | // //: m_logicManager(nullptr)
51 | //{
52 | //}
53 |
54 | //void Handler::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
55 | //{
56 | // Q_UNUSED(change);
57 | // //m_logicManager->appendHandler(this);
58 | //}
59 |
60 | //void Handler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
61 | //{
62 | // QBackendNode::sceneChangeEvent(e);
63 | //}
64 |
65 | //HandlerFunctor::HandlerFunctor(Manager *manager)
66 | // //: m_manager(manager)
67 | //{
68 | //}
69 |
70 | //Qt3DCore::QBackendNode *HandlerFunctor::create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const
71 | //{
72 | // Handler *handler = m_manager->logicHandlerManager()->getOrCreateResource(change->subjectId());
73 | // handler->setManager(m_manager);
74 | // return handler;
75 | //}
76 |
77 | //Qt3DCore::QBackendNode *HandlerFunctor::get(Qt3DCore::QNodeId id) const
78 | //{
79 | // return m_manager->logicHandlerManager()->lookupResource(id);
80 | //}
81 |
82 | //void HandlerFunctor::destroy(Qt3DCore::QNodeId id) const
83 | //{
84 | // m_manager->removeHandler(id);
85 | //}
86 |
87 | //} // namespace Qt3DVirtualReality
88 |
89 | //QT_END_NAMESPACE
90 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qvirtualrealityaspect.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "qvirtualrealityaspect.h"
16 | #include "qvirtualrealityaspect_p.h"
17 | #include "querytrackedobjectsjob_p.h"
18 |
19 | using namespace Qt3DCore;
20 |
21 | namespace Qt3DVirtualReality {
22 |
23 | QVirtualRealityAspectPrivate::QVirtualRealityAspectPrivate()
24 | : QAbstractAspectPrivate()
25 | , m_time(0)
26 | , m_initialized(false)
27 | , m_queryTrackedObjectsJob(new Qt3DVirtualReality::QueryTrackedObjectsJob)
28 | , m_hmd(nullptr)
29 | , m_apibackend(nullptr)
30 | {
31 | }
32 |
33 | void QVirtualRealityAspectPrivate::onEngineAboutToShutdown()
34 | {
35 |
36 | }
37 |
38 | void QVirtualRealityAspectPrivate::registerBackendTypes()
39 | {
40 | Q_Q(QVirtualRealityAspect);
41 | //q->registerBackendType();
42 | //q->registerBackendType();
43 | }
44 |
45 | /*!
46 | Constructs a new QVirtualRealityAspect instance with \a parent.
47 | */
48 | QVirtualRealityAspect::QVirtualRealityAspect(QObject *parent)
49 | : QVirtualRealityAspect(*new QVirtualRealityAspectPrivate(), parent) {}
50 |
51 | QVirtualRealityAspect::QVirtualRealityAspect(QVirtualRealityAspectPrivate &dd, QObject *parent)
52 | : QAbstractAspect(dd, parent)
53 | {
54 | Q_D(QVirtualRealityAspect);
55 | setObjectName(QStringLiteral("Virtual Reality Aspect"));
56 | d->registerBackendTypes();
57 | }
58 |
59 | QVirtualRealityAspect::~QVirtualRealityAspect()
60 | {
61 | }
62 |
63 | void QVirtualRealityAspect::setHeadmountedDisplay(QHeadMountedDisplay *hmd)
64 | {
65 | Q_D(QVirtualRealityAspect);
66 | d->m_hmd = hmd;
67 | }
68 |
69 | void QVirtualRealityAspect::setVirtualRealityApiBackend(QVirtualRealityApiBackend *apiBackend)
70 | {
71 | Q_D(QVirtualRealityAspect);
72 | d->m_apibackend = apiBackend;
73 | d->m_queryTrackedObjectsJob->setVirtualRealityApiBackend(d->m_apibackend);
74 | }
75 |
76 | QVector QVirtualRealityAspect::jobsToExecute(qint64 time)
77 | {
78 | Q_D(QVirtualRealityAspect);
79 | QVector jobs;
80 | jobs.append(d->m_queryTrackedObjectsJob);
81 | return jobs;
82 | }
83 |
84 | void QVirtualRealityAspect::onRegistered()
85 | {
86 | }
87 |
88 | void QVirtualRealityAspect::onUnregistered()
89 | {
90 | }
91 |
92 | ///*! \internal */
93 | //void QVirtualRealityAspect::onEngineStartup()
94 | //{
95 | // Q_D(QLogicAspect);
96 | // d->m_executor->setScene(d->m_arbiter->scene());
97 | //}
98 |
99 | QVariant QVirtualRealityAspect::executeCommand(const QStringList &args)
100 | {
101 | return QVariant();
102 | }
103 |
104 | } // namespace Qt3DVirtualReality
105 |
106 | QT_END_NAMESPACE
107 |
108 | QT3D_REGISTER_NAMESPACED_ASPECT("virtualreality", QT_PREPEND_NAMESPACE(Qt3DVirtualReality), QVirtualRealityAspect)
109 |
110 |
--------------------------------------------------------------------------------
/virtualreality/qheadmounteddisplay.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DHEADMOUNTEDDISPLAY_H
16 | #define QT3DHEADMOUNTEDDISPLAY_H
17 |
18 | #include "qvirtualrealityapi.h"
19 |
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include
29 |
30 | QT_BEGIN_NAMESPACE
31 |
32 | class QQmlIncubationController;
33 |
34 | namespace Qt3DCore {
35 | class QAbstractAspect;
36 | namespace Quick {
37 | class QQmlAspectEngine;
38 | }
39 | }
40 |
41 | namespace Qt3DRender {
42 | class QRenderAspect;
43 | class QCamera;
44 | }
45 |
46 | namespace Qt3DInput {
47 | class QInputAspect;
48 | }
49 |
50 | namespace Qt3DLogic {
51 | class QLogicAspect;
52 | }
53 |
54 | namespace Qt3DVirtualReality {
55 |
56 | class QVirtualRealityApiBackend;
57 |
58 | class QT3DVR_EXPORT QHeadMountedDisplay : public QObject /*: public QQuickItem*/ {
59 | Q_OBJECT
60 | Q_PROPERTY(QObject* surface READ surface NOTIFY surfaceChanged)
61 | Q_PROPERTY(QSize renderTargetSize READ renderTargetSize NOTIFY renderTargetSizeChanged)
62 |
63 | public:
64 | QHeadMountedDisplay(int hmdId, const QHeadMountedDisplayFormat &formathmd, QVirtualRealityApi *api, QVirtualRealityApiBackend *apibackend);
65 | ~QHeadMountedDisplay();
66 |
67 | void registerAspect(Qt3DCore::QAbstractAspect *aspect);
68 | void registerAspect(const QString &name);
69 |
70 | void setSource(const QUrl &source);
71 | Qt3DCore::Quick::QQmlAspectEngine *engine() const;
72 |
73 | // Hmd specific
74 | qreal refreshRate();
75 | qreal superSamplingFactor();
76 |
77 | QObject* surface() const;
78 | QSize renderTargetSize() const;
79 |
80 | int timeUntilNextFrame();
81 | QOpenGLContext *context();
82 | signals:
83 | void requestRun();
84 | void surfaceChanged(QSurface* surface);
85 | void renderTargetSizeChanged(QSize renderTargetSize);
86 | void sceneCreated(QObject *rootObject);
87 |
88 | public slots:
89 | void run();
90 |
91 | private:
92 | void onSceneCreated(QObject *rootObject);
93 | void setWindowSurface(QObject *rootObject);
94 |
95 | QScopedPointer m_engine;
96 |
97 | // Aspects
98 | Qt3DRender::QRenderAspect *m_renderAspect;
99 | Qt3DInput::QInputAspect *m_inputAspect;
100 | Qt3DLogic::QLogicAspect *m_logicAspect;
101 | Qt3DVirtualReality::QVirtualRealityAspect *m_virtualRealityAspect;
102 |
103 | QUrl m_source;
104 | bool m_initialized;
105 | QPointer m_camera;
106 | QQmlIncubationController *m_incubationController;
107 | QVirtualRealityApi *m_api;
108 | QVirtualRealityApiBackend *m_apibackend;
109 | int m_hmdId;
110 | QOpenGLFramebufferObject *m_fbo;
111 | QOpenGLContext *m_context;
112 | QOffscreenSurface *m_surface;
113 | QObject *m_rootItem;
114 | };
115 |
116 | } // Qt3DVirtualReality
117 |
118 | QT_END_NAMESPACE
119 |
120 | #endif
121 |
--------------------------------------------------------------------------------
/virtualreality/handler_p.h:
--------------------------------------------------------------------------------
1 | ///****************************************************************************
2 | //**
3 | //** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
4 | //** Contact: https://www.qt.io/licensing/
5 | //**
6 | //** This file is part of the Qt3D module of the Qt Toolkit.
7 | //**
8 | //** $QT_BEGIN_LICENSE:LGPL$
9 | //** Commercial License Usage
10 | //** Licensees holding valid commercial Qt licenses may use this file in
11 | //** accordance with the commercial license agreement provided with the
12 | //** Software or, alternatively, in accordance with the terms contained in
13 | //** a written agreement between you and The Qt Company. For licensing terms
14 | //** and conditions see https://www.qt.io/terms-conditions. For further
15 | //** information use the contact form at https://www.qt.io/contact-us.
16 | //**
17 | //** GNU Lesser General Public License Usage
18 | //** Alternatively, this file may be used under the terms of the GNU Lesser
19 | //** General Public License version 3 as published by the Free Software
20 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 | //** packaging of this file. Please review the following information to
22 | //** ensure the GNU Lesser General Public License version 3 requirements
23 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 | //**
25 | //** GNU General Public License Usage
26 | //** Alternatively, this file may be used under the terms of the GNU
27 | //** General Public License version 2.0 or (at your option) the GNU General
28 | //** Public license version 3 or any later version approved by the KDE Free
29 | //** Qt Foundation. The licenses are as published by the Free Software
30 | //** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 | //** included in the packaging of this file. Please review the following
32 | //** information to ensure the GNU General Public License requirements will
33 | //** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 | //** https://www.gnu.org/licenses/gpl-3.0.html.
35 | //**
36 | //** $QT_END_LICENSE$
37 | //**
38 | //****************************************************************************/
39 |
40 | //#ifndef QT3DVIRTUALREALITY_HANDLER_H
41 | //#define QT3DVIRTUALREALITY_HANDLER_H
42 |
43 | ////
44 | //// W A R N I N G
45 | //// -------------
46 | ////
47 | //// This file is not part of the Qt API. It exists for the convenience
48 | //// of other Qt classes. This header file may change from version to
49 | //// version without notice, or even be removed.
50 | ////
51 | //// We mean it.
52 | ////
53 |
54 | //#include
55 | //#include
56 | //#include
57 |
58 | //QT_BEGIN_NAMESPACE
59 |
60 | //namespace Qt3DVirtualReality {
61 |
62 | //class Handler : public Qt3DCore::QBackendNode
63 | //{
64 | //public:
65 | // Handler();
66 |
67 | // //void setManager(Manager *manager) { m_logicManager = manager; }
68 | // //Manager *logicManager() const { return m_logicManager; }
69 |
70 | //protected:
71 | // void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
72 |
73 | //private:
74 | // void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
75 |
76 | // //Manager *m_logicManager;
77 | //};
78 |
79 |
80 | //class HandlerFunctor : public Qt3DCore::QBackendNodeMapper
81 | //{
82 | //public:
83 | // //explicit HandlerFunctor(Manager *handler);
84 |
85 | // Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const Q_DECL_OVERRIDE;
86 | // Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const Q_DECL_OVERRIDE;
87 | // void destroy(Qt3DCore::QNodeId id) const Q_DECL_OVERRIDE;
88 |
89 | //private:
90 | // //Manager *m_manager;
91 | //};
92 |
93 | //} // namespace Qt3DVirtualReality
94 |
95 | //QT_END_NAMESPACE
96 |
97 | //#endif // QT3DVIRTUALREALITY_HANDLER_H
98 |
--------------------------------------------------------------------------------
/virtualreality/vrbackends/openvr/virtualrealityapiopenvr.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #if(QT3DVR_COMPILE_WITH_OPENVR)
16 | #ifndef VIRTUALREALITYAPIOPENVR_H
17 | #define VIRTUALREALITYAPIOPENVR_H
18 |
19 | #include "../../qvirtualrealityapibackend.h"
20 | #include "openvr.h"
21 | class QSurfaceFormat;
22 |
23 | struct TrackedObjectModel {
24 | TrackedObjectModel(QVector t_vertices, QVector t_indices, QOpenGLTexture* t_texture) :
25 | vertices(t_vertices), indices(t_indices), texture(t_texture) {}
26 |
27 | QVector vertices;
28 | QVector indices;
29 | QOpenGLTexture* texture;
30 | };
31 |
32 | class VirtualRealityApiOpenVR : public Qt3DVirtualReality::QVirtualRealityApiBackend
33 | {
34 | public:
35 | static bool isRuntimeInstalled();
36 | VirtualRealityApiOpenVR();
37 | bool isHmdPresent();
38 |
39 | void initialize();
40 | void shutdown();
41 | bool bindFrambufferObject(int hmdId);
42 |
43 | qreal refreshRate(int hmdId) const;
44 | QMatrix4x4 headPose(int hmdId);
45 | QSize getRenderTargetSize();
46 |
47 | int timeUntilNextFrame();
48 |
49 | void swapToHeadset();
50 |
51 | void getEyeMatrices(QMatrix4x4 &leftEye, QMatrix4x4 &rightEye);
52 |
53 | void getProjectionMatrices(QMatrix4x4 &leftProjection, QMatrix4x4 &rightProjection);
54 |
55 | QList currentlyTrackedObjects();
56 | void getTrackedObject(int id, QMatrix4x4 &transform);
57 | TrackedObjectType getTrackedObjectType(int id);
58 | void getTrackedObjectModel(int id, QVector &vertices, QVector &indices, QOpenGLTexture *texture);
59 |
60 | void getMirrorTexture(QOpenGLTexture *outMirrorTexture);
61 |
62 | bool isTriggerTmp();
63 | private:
64 | QOpenGLFramebufferObject *m_fbo;
65 | double m_sensorSampleTime;
66 | long long m_frameIndex;
67 | vr::IVRSystem *m_hmd;
68 | std::string m_driver;
69 | std::string m_display;
70 | vr::TrackedDevicePose_t m_trackedDevicePose[ vr::k_unMaxTrackedDeviceCount ];
71 | QMatrix4x4 m_devicePose[ vr::k_unMaxTrackedDeviceCount ];
72 | bool m_showTrackedDevice[ vr::k_unMaxTrackedDeviceCount ];
73 |
74 | int m_trackedControllerCount;
75 | int m_trackedControllerCountLast;
76 | int m_validPoseCount;
77 | int m_validPoseCountLast;
78 | std::string m_poseClasses; // what classes we saw poses for this frame
79 | char m_devClassChar[ vr::k_unMaxTrackedDeviceCount ]; // for each device, a character representing its class
80 |
81 | QMatrix4x4 m_hmdPose;
82 | QMatrix4x4 m_eyePosLeft;
83 | QMatrix4x4 m_eyePosRight;
84 |
85 | bool m_isTrigger;
86 |
87 | QMatrix4x4 getHmdMatrixProjectionEye(vr::Hmd_Eye nEye);
88 | QMatrix4x4 getHmdMatrixPoseEye(vr::Hmd_Eye nEye);
89 | QMatrix4x4 getCurrentViewMatrix(vr::Hmd_Eye nEye);
90 | void updateHmdMatrixPose();
91 | QMatrix4x4 convertSteamVrMatrixToQMatrix4x4(const vr::HmdMatrix34_t matPose);
92 | QMatrix4x4 convertSteamVrMatrixToQMatrix4x4(const vr::HmdMatrix44_t matPose);
93 | void processVrEvent(const vr::VREvent_t &event);
94 | void setupCameras();
95 | bool m_poseNewEnough; //TO DO: openvr in example only updates poses once a frame
96 |
97 | QMap m_models;
98 | };
99 |
100 | #endif
101 | #endif
102 |
--------------------------------------------------------------------------------
/vr-window/StereoFrameGraph.qml:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the Qt3D module of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | import Qt3D.Core 2.0
52 | import Qt3D.Render 2.0
53 |
54 | Viewport {
55 |
56 | property alias leftCamera: leftCameraSelector.camera
57 | property alias rightCamera: rightCameraSelector.camera
58 | // property alias window: surfaceSelector.surface
59 |
60 | RenderSurfaceSelector {
61 | id: surfaceSelector
62 | //surface: _hmd.surface
63 | externalRenderTargetSize: _hmd.renderTargetSize
64 |
65 | // ColorMask is reset by default
66 | // By default reset to the default if not specified
67 | ClearBuffers {
68 | buffers: ClearBuffers.ColorDepthBuffer
69 | clearColor: "white" //Qt.rgba(0.2,0.9,0.9,0.5)
70 | NoDraw {} // We just want to clear the buffers
71 | }
72 |
73 | // Draw with left eye
74 | CameraSelector {
75 | id: leftCameraSelector
76 | Viewport {
77 | RenderStateSet {
78 | renderStates: [
79 | DepthTest { depthFunction: DepthTest.Less }
80 | ]
81 | }
82 | normalizedRect: Qt.rect(0,0,0.5,1)
83 | }
84 | }
85 |
86 | // Draw with right eye
87 | CameraSelector {
88 | id: rightCameraSelector
89 | Viewport {
90 | RenderStateSet {
91 | renderStates: [
92 | DepthTest { depthFunction: DepthTest.Less }
93 | ]
94 | }
95 | normalizedRect: Qt.rect(0.5,0,0.5,1)
96 | }
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/vr-window/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.1
2 | import Qt3D.Core 2.0
3 | import Qt3D.Render 2.0
4 | import Qt3D.Input 2.0
5 | import Qt3D.Extras 2.0
6 |
7 | import QtQuick 2.0 as QQ2
8 |
9 | import vr 2.0
10 |
11 | Entity {
12 | id: root
13 |
14 | components: RenderSettings {
15 | StereoFrameGraph {
16 | id: stereoFrameGraph
17 | leftCamera: vrCam.leftCamera
18 | rightCamera: vrCam.rightCamera
19 | }
20 | }
21 | Item {
22 | id: cameraProps
23 | readonly property real cameraRadius: obstaclesRepeater.radius - 50
24 | readonly property vector3d circlePosition: Qt.vector3d(cameraRadius * Math.cos(circleRotation), 0.0, cameraRadius * Math.sin(circleRotation))
25 | readonly property vector3d tan: circlePosition.crossProduct(Qt.vector3d(0, 1, 0).normalized())
26 | property real circleRotation: 0
27 |
28 | QQ2.NumberAnimation {
29 | target: cameraProps
30 | property: "circleRotation"
31 | from: 0; to: Math.PI * 2
32 | duration: 10000
33 | loops: QQ2.Animation.Infinite
34 | running: false
35 | }
36 | }
37 | // Camera
38 | VrCamera {
39 | id: vrCam
40 | //offset: Qt.vector3d(80.0,-90.0,0.0)
41 | //offsetOrientation:
42 | //offset: cameraProps.circlePosition.plus(Qt.vector3d(0, 45 * Math.sin(cameraProps.circleRotation * 2), 0)).plus(cameraProps.tan.times(-2))
43 | }
44 |
45 | // Torus obsctacles
46 | NodeInstantiator {
47 | id: obstaclesRepeater
48 | model: 40
49 | readonly property real radius: 3.0
50 | readonly property real det: 1.0 / model
51 | delegate: Entity {
52 | components: [
53 | TorusMesh {
54 | radius: 0.5
55 | minorRadius: 0.05
56 | rings: 100
57 | slices: 20
58 | },
59 | Transform {
60 | id: transform
61 | readonly property real angle: Math.PI * 2.0 * index * obstaclesRepeater.det
62 | translation: Qt.vector3d(obstaclesRepeater.radius * Math.cos(transform.angle),
63 | 0.0,
64 | obstaclesRepeater.radius * Math.sin(transform.angle))
65 | rotation: fromAxisAndAngle(Qt.vector3d(0.0, 1.0, 0.0), -transform.angle * 180 / Math.PI)
66 | },
67 | PhongMaterial {
68 | diffuse: Qt.rgba(Math.abs(Math.cos(transform.angle)), 204 / 255, 75 / 255, 1)
69 | specular: "white"
70 | shininess: 20.0
71 | }
72 | ]
73 | }
74 | }
75 | NodeInstantiator {
76 | id: trackedObjectsRepeater
77 | // TO DO: a model does not yet work here (array with indices). temporarily using a number
78 | model: 4 // default: 1 -> head, 2&3 -> base station, 4&5 -> controller/hands
79 | // different setup? : 1&2 -> base stations, 3&4 -> controllers, 5 -> ?
80 | delegate: Entity {
81 | Timer {
82 | running: true
83 | repeat: true
84 | interval: 1
85 | onTriggered: {
86 | // this is a temporary workaround and there are no property change events here
87 | trackedTransform.matrix = vrCam.trackedObjectMatrixTmp(index+1)
88 | }
89 | }
90 | components: [
91 | TrackedObjectMesh {
92 | trackedObjectId: index+1
93 | },
94 | // TorusMesh {
95 | // radius: 0.1
96 | // minorRadius: 0.05
97 | // rings: 100
98 | // slices: 20
99 | // },
100 | Transform {
101 | id: trackedTransform
102 | },
103 | PhongMaterial {
104 | specular: "white"
105 | ambient: Qt.rgba(1.0*index,1.0*(index-1.0),0.0,1.0)
106 | shininess: 20.0
107 | }
108 | ]
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/virtualreality/qvirtualrealityapibackend.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QT3DVIRTUALREALITYAPIBACKEND_H
16 | #define QT3DVIRTUALREALITYAPIBACKEND_H
17 |
18 | #include "qt3dvr_global.h"
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | QT_BEGIN_NAMESPACE
27 |
28 | namespace Qt3DVirtualReality {
29 |
30 | /*!
31 | * \brief The QVirtualRealityApiBackend class hides the concrete implementation for a vr headset.
32 | * It should make it easy to add more Virtual reality devices. However, becaus we can't look into the future
33 | * this interface might be extended with new features.
34 | */
35 | class QVirtualRealityApiBackend
36 | {
37 | public:
38 | enum TrackedObjectType {
39 | Head,
40 | LeftHand,
41 | RightHand,
42 | LighthouseOrSensor,
43 | Other
44 | };
45 | virtual bool isHmdPresent() = 0;
46 |
47 | /*!
48 | * \brief initialize is to initialize the concrete vr framework.
49 | * This is called while correct opengl context is current and already initialized
50 | * It is also known, that the runtime is installed at this point
51 | */
52 | virtual void initialize() = 0;
53 | virtual void shutdown() = 0;
54 | /*!
55 | * \brief bindFrambufferObject for rendering. Has to bind the framebuffer of the current
56 | * headset for rendering.
57 | * \return success
58 | */
59 | virtual bool bindFrambufferObject(int hmdId) = 0;
60 |
61 | /*!
62 | * \brief refreshRate of the selected headset. E.g. 90 Hz
63 | * \param hmdId
64 | * \return
65 | */
66 | virtual qreal refreshRate(int hmdId) const = 0;
67 |
68 | /*!
69 | * \brief headPose estimated for the next frame
70 | * //TO DO: add estimation parameters.
71 | * It is likely that this function never returns the same headpose twice.
72 | * \param hmdId
73 | * \return
74 | */
75 | virtual QMatrix4x4 headPose(int hmdId) = 0;
76 |
77 | //TO DO: introduce getRecomendedSize()
78 | virtual QSize getRenderTargetSize() = 0;
79 |
80 | virtual int timeUntilNextFrame() = 0;
81 | virtual void swapToHeadset() = 0;
82 |
83 | /*!
84 | * \brief getEyeMatrices without projection applied. Relative to transform-origin.
85 | * //TO DO: Add transform origin concept. Introduce a way to get interpupilar distance and offset to headPose.?
86 | * \param leftEye
87 | * \param rightEye
88 | */
89 | virtual void getEyeMatrices(QMatrix4x4 &leftEye, QMatrix4x4 &rightEye) = 0;
90 |
91 | /*!
92 | * \brief getProjectionMatrices get correct projection matrix for each eye. These can be asymetrical.
93 | * \param leftProjection
94 | * \param rightProjection
95 | */
96 | virtual void getProjectionMatrices(QMatrix4x4 &leftProjection, QMatrix4x4 &rightProjection) = 0;
97 |
98 | virtual QList currentlyTrackedObjects() = 0;
99 | virtual void getTrackedObject(int id, QMatrix4x4 &transform) = 0;
100 | virtual TrackedObjectType getTrackedObjectType(int id) = 0;
101 | virtual void getTrackedObjectModel(int id, QVector &vertices, QVector &indices, QOpenGLTexture *texture) = 0;
102 |
103 | virtual bool isTriggerTmp() = 0;
104 | /*!
105 | * \brief getMirrorTexture
106 | * Used to get a texture witch can be rendered in another window/thread.
107 | * Some SDKs will not automaticly fill the QOpenGLTextue itself but return an OpenGL texture name.
108 | * This method has to be called every time the mirror should update to allow copying in this case.
109 | * It might work for some SDKs, but not for others.
110 | * \param outMirrorTexture
111 | */
112 | virtual void getMirrorTexture(QOpenGLTexture *outMirrorTexture) = 0;
113 |
114 | };
115 |
116 | }
117 |
118 | QT_END_NAMESPACE
119 |
120 | #endif
121 |
--------------------------------------------------------------------------------
/virtualreality/vrbackends/ovr/framebufferovr.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #if(QT3DVR_COMPILE_WITH_OCULUSVR)
16 | #include "framebufferovr.h"
17 | #include
18 | #include
19 | #include
20 |
21 | class FramebufferOvr
22 | {
23 | GLuint m_colorAttachment;
24 | GLuint m_depthBuffer;
25 | GLuint m_framebuffer;
26 | QOpenGLFunctions_3_2_Core *m_funcs;
27 | public:
28 | FramebufferOvr(GLuint colorAttachment0TextureId, GLuint depthBufferRenderbufferId, QOpenGLFunctions_3_2_Core *funcs)
29 | : m_colorAttachment(colorAttachment0TextureId)
30 | , m_depthBuffer(depthBufferRenderbufferId)
31 | , m_funcs(funcs)
32 | {
33 | m_funcs->glGenFramebuffers(1, &m_framebuffer);
34 | m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
35 |
36 | m_funcs->glBindTexture(GL_TEXTURE_2D, m_colorAttachment);
37 | m_funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
38 | m_funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
39 | m_funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
40 | m_funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
41 |
42 | if(depthBufferRenderbufferId > 0) {
43 | Q_ASSERT(funcs->glIsRenderbuffer(m_depthBuffer));
44 | funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
45 | GL_RENDERBUFFER, m_depthBuffer);
46 | }
47 | int sampleCount = 1;
48 | GLenum texTarget = (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
49 | m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texTarget, m_colorAttachment, 0);
50 |
51 | m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0);
52 | }
53 | ~FramebufferOvr() {
54 |
55 | }
56 |
57 | GLuint getTextureId() {
58 | return m_colorAttachment;
59 | }
60 | void bind() {
61 | m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
62 | }
63 | };
64 |
65 | OvrSwapChain::OvrSwapChain( ovrSession session, QSize size)
66 | :m_session(session),
67 | m_texSize(size),
68 | m_textureChain(0)
69 | {
70 | m_funcs = QOpenGLContext::currentContext()->versionFunctions();
71 | if(!m_funcs)
72 | {
73 | qDebug() << "Could not get OpenGLFunctions 3.2";
74 | return;
75 | }
76 | ovrTextureSwapChainDesc desc = {};
77 | desc.Type = ovrTexture_2D;
78 | desc.ArraySize = 1;
79 | desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
80 | desc.Width = m_texSize.width();
81 | desc.Height = m_texSize.height();
82 | desc.MipLevels = 1;
83 | desc.SampleCount = 1;
84 | desc.StaticImage = ovrFalse;
85 |
86 | // We have to use the internally created texture from this method.
87 | // No way to use a native QOpenGLTexture for rendering, without copying it.
88 | ovrResult result = ovr_CreateTextureSwapChainGL(m_session, &desc, &m_textureChain);
89 |
90 | if(!OVR_SUCCESS(result))
91 | {
92 | ovrErrorInfo inf;
93 | ovr_GetLastErrorInfo(&inf);
94 | qDebug() << inf.ErrorString;
95 | }
96 | int length = 0;
97 | ovr_GetTextureSwapChainLength(m_session, m_textureChain, &length);
98 |
99 | if(OVR_SUCCESS(result))
100 | {
101 | GLuint depthBufferId;
102 | m_funcs->glGenRenderbuffers(1, &depthBufferId);
103 | m_funcs->glBindRenderbuffer(GL_RENDERBUFFER, depthBufferId);
104 | Q_ASSERT(m_funcs->glIsRenderbuffer(depthBufferId));
105 | m_funcs->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_texSize.width(), m_texSize.height());
106 |
107 | for (int i = 0; i < length; ++i)
108 | {
109 | GLuint chainTextureId;
110 | ovr_GetTextureSwapChainBufferGL(m_session, m_textureChain, i, &chainTextureId);
111 | m_framebuffers.push_back(new FramebufferOvr(chainTextureId, depthBufferId, m_funcs));
112 | }
113 | }
114 |
115 | if (!m_textureChain)
116 | {
117 | ovrErrorInfo inf;
118 | ovr_GetLastErrorInfo(&inf);
119 | qDebug() << inf.ErrorString;
120 | }
121 | }
122 |
123 | OvrSwapChain::~OvrSwapChain()
124 | {
125 | if (m_textureChain)
126 | {
127 | ovr_DestroyTextureSwapChain(m_session, m_textureChain);
128 | m_textureChain = nullptr;
129 | }
130 | for(QVector::iterator iter(m_framebuffers.begin()) ; iter != m_framebuffers.end() ; ++iter) {
131 | delete *iter;
132 | }
133 | }
134 |
135 | QSize OvrSwapChain::size() const
136 | {
137 | return m_texSize;
138 | }
139 |
140 | void OvrSwapChain::commit()
141 | {
142 | Q_ASSERT(m_textureChain != nullptr);
143 | ovr_CommitTextureSwapChain(m_session, m_textureChain);
144 | }
145 |
146 | const ovrTextureSwapChain& OvrSwapChain::ovrTextureChain() const
147 | {
148 | return m_textureChain;
149 | }
150 |
151 | void OvrSwapChain::bindCurrentChainIndexFramebuffer()
152 | {
153 | Q_ASSERT(m_textureChain != nullptr);
154 | int curIndex;
155 | ovr_GetTextureSwapChainCurrentIndex(m_session, m_textureChain, &curIndex);
156 | m_framebuffers[curIndex]->bind();
157 | }
158 |
159 | void OvrSwapChain::bindFramebuffer(int index)
160 | {
161 | //nyi
162 | }
163 |
164 | int OvrSwapChain::chainLength() const
165 | {
166 | //nyi
167 | return 0;
168 | }
169 | #endif
170 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qvirtualrealitycamera.h:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #ifndef QVRCAMERA
16 | #define QVRCAMERA
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include //TO DO: THis include is only for transforms over camera
22 |
23 | QT_BEGIN_NAMESPACE
24 |
25 | namespace Qt3DVirtualReality {
26 |
27 | class QVirtualrealityCamera : public Qt3DCore::QEntity
28 | {
29 | Q_OBJECT
30 | Q_PROPERTY(Qt3DRender::QCameraLens * leftCameraLens READ leftCameraLens NOTIFY leftCameraLensChanged)
31 | Q_PROPERTY(Qt3DRender::QCameraLens * rightCameraLens READ rightCameraLens NOTIFY rightCameraLensChanged)
32 | Q_PROPERTY(Qt3DCore::QEntity * leftCamera READ leftCamera NOTIFY leftCameraChanged)
33 | Q_PROPERTY(Qt3DCore::QEntity * rightCamera READ rightCamera NOTIFY rightCameraChanged)
34 | Q_PROPERTY(float disparity READ disparity NOTIFY disparityChanged)
35 | // Q_PROPERTY(QVector3D headPosPredicted READ headPosPredicted NOTIFY headPosPredictedChanged)
36 | // Q_PROPERTY(QQuaternion headOrientationPredicted READ headOrientationPredicted NOTIFY headOrientationPredictedChanged)
37 | Q_PROPERTY(QVector3D offset READ offset WRITE setOffset NOTIFY offsetChanged)
38 | Q_PROPERTY(QQuaternion offsetOrientation READ offsetOrientation WRITE setOffsetOrientation NOTIFY offsetOrientationChanged)
39 | // Q_PROPERTY(QMatrix4x4 viewMatrixPredicted READ viewMatrixPredicted NOTIFY viewMatrixPredictedChanged)
40 | Q_PROPERTY(float playerHeight READ playerHeight NOTIFY playerHeightChanged)
41 | Q_PROPERTY(QRectF leftNormalizedViewportRect READ leftNormalizedViewportRect WRITE setLeftNormalizedViewportRect NOTIFY leftNormalizedViewportRectChanged)
42 | Q_PROPERTY(QRectF rightNormalizedViewportRect READ rightNormalizedViewportRect WRITE setRightNormalizedViewportRect NOTIFY rightNormalizedViewportRectChanged)
43 | public:
44 | QVirtualrealityCamera(QNode *parent = nullptr);
45 |
46 | Qt3DCore::QEntity * leftCamera();
47 | Qt3DCore::QEntity * rightCamera();
48 |
49 | void setProjections(const QMatrix4x4& leftProjection, const QMatrix4x4& rightProjection);
50 | void update(const QMatrix4x4 &viewLeft, const QMatrix4x4 &viewRight);
51 | float disparity() const;
52 |
53 | // QMatrix4x4 headPosPredicted() const;
54 | // QMatrix4x4 headOrientationPredicted() const;
55 | QVector3D offset() const;
56 | // QMatrix4x4 viewMatrixPredicted() const;
57 | float playerHeight() const;
58 | QRectF leftNormalizedViewportRect() const;
59 | QRectF rightNormalizedViewportRect() const;
60 | QQuaternion offsetOrientation() const;
61 |
62 | // Transforms should be handled by special "VrTransform" Class, which has two backend nodes (one in renderaspect and one in vr aspect).
63 | // Then it should always uptade before rendering. For the moment, this will create a minimium viable product.
64 | Q_INVOKABLE QMatrix4x4 trackedObjectMatrixTmp(int trackedObjectId);
65 | Q_INVOKABLE QList trackedObjectsTmp();
66 | void setVrBackendTmp(QVirtualRealityApiBackend* backend); //only for trackedObjectMatrixTmp
67 | Q_INVOKABLE bool isTriggerTmp();
68 | Qt3DRender::QCameraLens * leftCameraLens() const
69 | {
70 | return m_leftCameraLens;
71 | }
72 |
73 | Qt3DRender::QCameraLens * rightCameraLens() const
74 | {
75 | return m_rightCameraLens;
76 | }
77 |
78 | public Q_SLOTS:
79 |
80 | void setOffset(QVector3D offset);
81 | void setLeftNormalizedViewportRect(QRectF leftNormalizedViewportRect);
82 | void setRightNormalizedViewportRect(QRectF rightNormalizedViewportRect);
83 | void setOffsetOrientation(QQuaternion offsetOrientation);
84 |
85 | Q_SIGNALS:
86 |
87 | void disparityChanged(float disparity);
88 | // void headPosPredictedChanged(QVector3D headPosPredicted);
89 | // void headOrientationPredictedChanged(QMatrix4x4 headOrientationPredicted);
90 | void offsetChanged(QVector3D offset);
91 | // void viewMatrixPredictedChanged(QMatrix4x4 viewMatrixPredicted);
92 | void playerHeightChanged(float playerHeight);
93 | void leftNormalizedViewportRectChanged(QRectF leftNormalizedViewportRect);
94 | void rightNormalizedViewportRectChanged(QRectF rightNormalizedViewportRect);
95 | void leftCameraChanged(Qt3DCore::QEntity * leftCamera);
96 | void rightCameraChanged(Qt3DCore::QEntity * rightCamera);
97 | void offsetOrientationChanged(QQuaternion offsetOrientation);
98 | void leftCameraLensChanged(Qt3DRender::QCameraLens * leftCameraLens);
99 | void rightCameraLensChanged(Qt3DRender::QCameraLens * rightCameraLens);
100 |
101 | private:
102 | Qt3DRender::QCameraLens *m_leftCameraLens;
103 | Qt3DRender::QCameraLens *m_rightCameraLens;
104 | Qt3DCore::QTransform *m_leftTransform;
105 | Qt3DCore::QTransform *m_rightTransform;
106 | Qt3DCore::QEntity *m_leftCamera;
107 | Qt3DCore::QEntity *m_rightCamera;
108 | float m_disparity;
109 | // QVector3D m_headPosPredicted;
110 | // QQuaternion m_headOrientationPredicted;
111 | QVector3D m_offset;
112 | // QMatrix4x4 m_viewMatrixPredicted;
113 | float m_playerHeight;
114 | QRectF m_leftNormalizedViewportRect;
115 | QRectF m_rightNormalizedViewportRect;
116 | QQuaternion m_offsetOrientation;
117 | QVirtualRealityApiBackend *m_apibackend; //TO DO: tmp
118 |
119 | };
120 |
121 | } // namespace Qt3DVirtualReality
122 |
123 | QT_END_NAMESPACE
124 |
125 | #endif
126 |
--------------------------------------------------------------------------------
/virtualreality/frontend/qvirtualrealitycamera.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "qvirtualrealitycamera.h"
16 | #include
17 | #include
18 | #include
19 |
20 | #include
21 |
22 | QT_BEGIN_NAMESPACE
23 |
24 | namespace Qt3DVirtualReality {
25 |
26 | QVirtualrealityCamera::QVirtualrealityCamera(QNode *parent)
27 | :m_leftCamera(new Qt3DCore::QEntity(parent)),
28 | m_rightCamera(new Qt3DCore::QEntity(parent)), // TODO: Delete?
29 | m_leftCameraLens(new Qt3DRender::QCameraLens(parent)),//m_leftCamera)),
30 | m_rightCameraLens(new Qt3DRender::QCameraLens(parent)),//m_rightCamera)),
31 | m_leftTransform(new Qt3DCore::QTransform(parent)),//m_leftCamera)),
32 | m_rightTransform(new Qt3DCore::QTransform(parent)),//m_rightCamera)),
33 | m_apibackend(nullptr)
34 | {
35 | m_leftCamera->addComponent(m_leftCameraLens);
36 | m_rightCamera->addComponent(m_rightCameraLens);
37 | m_leftCamera->addComponent(m_leftTransform);
38 | m_rightCamera->addComponent(m_rightTransform);
39 |
40 | // m_leftCamera->setAspectRatio(9.0/16.0);
41 | // m_rightCamera->setAspectRatio(9.0/16.0);
42 | // m_leftCamera->setNearPlane(0.1);
43 | // m_rightCamera->setNearPlane(0.1);
44 | // m_leftCamera->setFarPlane(1000.0f);
45 | // m_rightCamera->setFarPlane(1000.0f);
46 | // m_leftCamera->setUpVector(QVector3D(0.0f,1.0f,0.0f));
47 | // m_rightCamera->setUpVector(QVector3D(0.0f,1.0f,0.0f));
48 | // m_leftCamera->setFieldOfView(100.0);
49 | // m_rightCamera->setFieldOfView(100.0);
50 | // //m_leftCamera->set
51 | Q_EMIT leftCameraChanged(m_leftCamera);
52 | Q_EMIT rightCameraChanged(m_rightCamera);
53 | }
54 |
55 | Qt3DCore::QEntity *QVirtualrealityCamera::leftCamera()
56 | {
57 | return m_leftCamera;
58 | }
59 |
60 | Qt3DCore::QEntity *QVirtualrealityCamera::rightCamera()
61 | {
62 | return m_rightCamera;
63 | }
64 |
65 | void QVirtualrealityCamera::setProjections(const QMatrix4x4 &leftProjection, const QMatrix4x4 &rightProjection)
66 | {
67 | m_leftCameraLens->setProjectionMatrix(leftProjection);
68 | m_rightCameraLens->setProjectionMatrix(rightProjection);
69 | Q_EMIT leftCameraLensChanged(m_leftCameraLens);
70 | Q_EMIT rightCameraLensChanged(m_rightCameraLens);
71 | }
72 |
73 | void QVirtualrealityCamera::update(const QMatrix4x4 &viewLeft, const QMatrix4x4 &viewRight)
74 | {
75 | // Vector3f finalUp = rot.Transform(Vector3f(0, 1, 0));
76 | // Vector3f finalForward = rot.Transform(Vector3f(0, 0, -1));
77 | // Matrix4f view = Matrix4f::LookAtRH(pos, pos + finalForward, finalUp);
78 | //QMatrix4x4 viewLeft;
79 | //viewLeft.lookAt(leftPos, leftPos + leftOrient.rotatedVector(QVector3D(0.0,0.0,1.0)), leftOrient.rotatedVector(QVector3D(0.0,1.0,0.0)));
80 | QMatrix4x4 l(viewLeft);
81 | QMatrix4x4 r(viewRight);
82 | l.translate(-m_offset);
83 | r.translate(-m_offset);
84 | m_leftTransform->setMatrix(l);
85 | //QMatrix4x4 viewRight;
86 | //viewRight.lookAt(rightPos, rightPos + rightOrient.rotatedVector(QVector3D(0.0,0.0,1.0)), rightOrient.rotatedVector(QVector3D(0.0,1.0,0.0)));
87 | m_rightTransform->setMatrix(r);
88 |
89 |
90 | // Matrix4f view = Matrix4f(orientation.Inverted()) * Matrix4f::Translation(-WorldEyePos);
91 | // QMatrix4x4 matL1, matL2;
92 | // matL1.rotate(leftOrient.inverted());
93 | // matL2.translate(-leftPos);
94 | // QMatrix4x4 matR1, matR2;
95 | // matR1.rotate(rightOrient.inverted());
96 | // matR2.translate(-rightPos);
97 | // m_leftTransform->setMatrix(matL1*matL2);
98 | // m_rightTransform->setMatrix(matR1*matR2);
99 |
100 | // m_leftTransform->setMatrix(leftOrient.inverted()*-leftPos);
101 | // m_leftTransform->setMatrix(leftOrient.inverted()*-leftPos);
102 | // m_leftTransform->setRotation(leftOrient.inverted());
103 | // m_leftTransform->setTranslation(-leftPos);
104 | // m_rightTransform->setRotation(rightOrient.inverted());
105 | // m_rightTransform->setTranslation(-rightPos);
106 | }
107 |
108 | float QVirtualrealityCamera::disparity() const
109 | {
110 | return m_disparity;
111 | }
112 |
113 | //QMatrix4x4 QVirtualrealityCamera::headPosPredicted() const
114 | //{
115 | // return m_headPosPredicted;
116 | //}
117 |
118 | //QMatrix4x4 QVirtualrealityCamera::headOrientationPredicted() const
119 | //{
120 | // return m_headOrientationPredicted;
121 | //}
122 |
123 | QVector3D QVirtualrealityCamera::offset() const
124 | {
125 | return m_offset;
126 | }
127 |
128 | //QMatrix4x4 QVirtualrealityCamera::viewMatrixPredicted() const
129 | //{
130 | // return m_viewMatrixPredicted;
131 | //}
132 |
133 | float QVirtualrealityCamera::playerHeight() const
134 | {
135 | return m_playerHeight;
136 | }
137 |
138 | QRectF QVirtualrealityCamera::leftNormalizedViewportRect() const
139 | {
140 | return m_leftNormalizedViewportRect;
141 | }
142 |
143 | QRectF QVirtualrealityCamera::rightNormalizedViewportRect() const
144 | {
145 | return m_rightNormalizedViewportRect;
146 | }
147 |
148 | QQuaternion QVirtualrealityCamera::offsetOrientation() const
149 | {
150 | return m_offsetOrientation;
151 | }
152 |
153 | QMatrix4x4 QVirtualrealityCamera::trackedObjectMatrixTmp(int trackedObjectId)
154 | {
155 | if(!m_apibackend) return QMatrix4x4();
156 | QMatrix4x4 mat;
157 | m_apibackend->getTrackedObject(trackedObjectId, mat);
158 | QMatrix4x4 off;
159 | off.translate(m_offset);
160 | return off*mat;
161 | }
162 |
163 | QList QVirtualrealityCamera::trackedObjectsTmp()
164 | {
165 | if(!m_apibackend) return QList();
166 | return m_apibackend->currentlyTrackedObjects();
167 | }
168 |
169 | bool Qt3DVirtualReality::QVirtualrealityCamera::isTriggerTmp()
170 | {
171 |
172 | if(!m_apibackend) return false;
173 | QMatrix4x4 mat;
174 | return m_apibackend->isTriggerTmp();
175 | }
176 |
177 | void QVirtualrealityCamera::setVrBackendTmp(QVirtualRealityApiBackend *backend)
178 | {
179 | m_apibackend = backend;
180 | }
181 |
182 | void QVirtualrealityCamera::setOffset(QVector3D offset)
183 | {
184 | if (m_offset == offset)
185 | return;
186 |
187 | m_offset = offset;
188 | Q_EMIT offsetChanged(offset);
189 | }
190 |
191 | void QVirtualrealityCamera::setLeftNormalizedViewportRect(QRectF leftNormalizedViewportRect)
192 | {
193 | if (m_leftNormalizedViewportRect == leftNormalizedViewportRect)
194 | return;
195 |
196 | m_leftNormalizedViewportRect = leftNormalizedViewportRect;
197 | Q_EMIT leftNormalizedViewportRectChanged(leftNormalizedViewportRect);
198 | }
199 |
200 | void QVirtualrealityCamera::setRightNormalizedViewportRect(QRectF rightNormalizedViewportRect)
201 | {
202 | if (m_rightNormalizedViewportRect == rightNormalizedViewportRect)
203 | return;
204 |
205 | m_rightNormalizedViewportRect = rightNormalizedViewportRect;
206 | Q_EMIT rightNormalizedViewportRectChanged(rightNormalizedViewportRect);
207 | }
208 |
209 | void QVirtualrealityCamera::setOffsetOrientation(QQuaternion offsetOrientation)
210 | {
211 | if (m_offsetOrientation == offsetOrientation)
212 | return;
213 |
214 | m_offsetOrientation = offsetOrientation;
215 | Q_EMIT offsetOrientationChanged(offsetOrientation);
216 | }
217 |
218 | } // namespace Qt3DVirtualReality
219 |
220 | QT_END_NAMESPACE
221 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/virtualreality/vrbackends/ovr/virtualrealityapiovr.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #if(QT3DVR_COMPILE_WITH_OCULUSVR)
16 | #include "virtualrealityapiovr.h"
17 | #include "framebufferovr.h"
18 |
19 | #include "Extras/OVR_Math.h"
20 | #include "OVR_CAPI_GL.h"
21 |
22 | using namespace OVR;
23 |
24 | #if defined(_WIN32)
25 | #include // for GetDefaultAdapterLuid
26 | //#pragma comment(lib, "dxgi.lib")
27 | #endif
28 |
29 |
30 | static ovrGraphicsLuid GetDefaultAdapterLuid()
31 | {
32 | ovrGraphicsLuid luid = ovrGraphicsLuid();
33 |
34 | #if defined(_WIN32)
35 | IDXGIFactory* factory = nullptr;
36 |
37 | if (SUCCEEDED(CreateDXGIFactory(IID_PPV_ARGS(&factory))))
38 | {
39 | IDXGIAdapter* adapter = nullptr;
40 |
41 | if (SUCCEEDED(factory->EnumAdapters(0, &adapter)))
42 | {
43 | DXGI_ADAPTER_DESC desc;
44 |
45 | adapter->GetDesc(&desc);
46 | memcpy(&luid, &desc.AdapterLuid, sizeof(luid));
47 | adapter->Release();
48 | }
49 |
50 | factory->Release();
51 | }
52 | #endif
53 |
54 | return luid;
55 | }
56 |
57 | bool VirtualRealityApiOvr::isRuntimeInstalled()
58 | {
59 | ovrResult result = ovr_Initialize(nullptr);
60 | return OVR_SUCCESS(result);
61 | }
62 |
63 | VirtualRealityApiOvr::VirtualRealityApiOvr()
64 | : m_sessionStarted(false)
65 | , m_sensorSampleTime(0.0)
66 | , m_frameIndex(0)
67 | , m_swapChain(nullptr)
68 | {
69 | }
70 |
71 | VirtualRealityApiOvr::~VirtualRealityApiOvr()
72 | {
73 | // Don't call shutdown. It has been called already at this point.
74 | Q_ASSERT(m_swapChain);
75 | }
76 |
77 | bool VirtualRealityApiOvr::initializeIfHmdIsPresent()
78 | {
79 | if(!m_sessionStarted) {
80 | ovrResult result = ovr_Initialize(nullptr);
81 | if (!OVR_SUCCESS(result))
82 | {
83 | qDebug() << "Failed to initialize libOVR.";
84 | return false;
85 | }
86 | result = ovr_Create(&m_session, &m_luid);
87 | if (!OVR_SUCCESS(result))
88 | {
89 | qDebug() << "Failed to create session libOVR.";
90 | return false;
91 | }
92 | m_sessionStarted = true;
93 | }
94 | if (memcmp(&m_luid, &GetDefaultAdapterLuid(), sizeof(m_luid))) // If luid that the Rift is on is not the default adapter LUID...
95 | {
96 | qDebug() << "OpenGL supports only the default graphics adapter.";
97 | return false;
98 | }
99 | return true;
100 | }
101 |
102 | bool VirtualRealityApiOvr::isHmdPresent()
103 | {
104 | return initializeIfHmdIsPresent();
105 | }
106 |
107 | void VirtualRealityApiOvr::initialize()
108 | {
109 | bool hmdPresent = initializeIfHmdIsPresent();
110 | if(!hmdPresent)
111 | return;
112 | m_hmdDesc = ovr_GetHmdDesc(m_session);
113 | ovr_SetTrackingOriginType(m_session, ovrTrackingOrigin_FloorLevel);
114 | m_swapChain = new OvrSwapChain(m_session, getRenderTargetSize());
115 | }
116 |
117 | void VirtualRealityApiOvr::shutdown()
118 | {
119 | if(m_swapChain != nullptr)
120 | delete m_swapChain;
121 | }
122 |
123 | bool VirtualRealityApiOvr::bindFrambufferObject(int hmdId)
124 | {
125 | m_swapChain->bindCurrentChainIndexFramebuffer();
126 | return true;
127 | }
128 |
129 | void VirtualRealityApiOvr::swapToHeadset()
130 | {
131 | m_swapChain->commit();
132 |
133 | ovrLayerEyeFov ld;
134 | ld.Header.Type = ovrLayerType_EyeFov;
135 | ld.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; // Because OpenGL.
136 |
137 | ld.ColorTexture[ovrEye_Left] = m_swapChain->ovrTextureChain();
138 | int halfWidth = m_swapChain->size().width()/2;
139 | int height = m_swapChain->size().height();
140 | ld.Viewport[ovrEye_Left] = Recti(0, 0, halfWidth, height);
141 | ld.Fov[ovrEye_Left] = m_hmdDesc.DefaultEyeFov[ovrEye_Left];
142 | ld.RenderPose[ovrEye_Left] = m_eyeRenderPose[ovrEye_Left];
143 |
144 | ld.ColorTexture[ovrEye_Right] = m_swapChain->ovrTextureChain();
145 | ld.Viewport[ovrEye_Right] = Recti(halfWidth, 0, halfWidth, height);
146 | ld.Fov[ovrEye_Right] = m_hmdDesc.DefaultEyeFov[ovrEye_Right];
147 | ld.RenderPose[ovrEye_Right] = m_eyeRenderPose[ovrEye_Right];
148 |
149 | ld.SensorSampleTime = m_sensorSampleTime;
150 |
151 | ovrLayerHeader* layers = &ld.Header;
152 | ovrResult result = ovr_SubmitFrame(m_session, m_frameIndex, nullptr, &layers, 1);
153 |
154 | if (!OVR_SUCCESS(result))
155 | {
156 | ovrErrorInfo inf;
157 | ovr_GetLastErrorInfo(&inf);
158 | qDebug() << inf.ErrorString;
159 | return;
160 | }
161 | m_frameIndex++;
162 | }
163 |
164 | void VirtualRealityApiOvr::getEyeMatrices(QMatrix4x4 &leftEye, QMatrix4x4 &rightEye)
165 | {
166 | ovrEyeRenderDesc eyeRenderDesc[ovrEye_Count];
167 | eyeRenderDesc[ovrEye_Left] = ovr_GetRenderDesc(m_session, ovrEye_Left, m_hmdDesc.DefaultEyeFov[ovrEye_Left]);
168 | eyeRenderDesc[ovrEye_Right] = ovr_GetRenderDesc(m_session, ovrEye_Right, m_hmdDesc.DefaultEyeFov[ovrEye_Right]);
169 | // Get eye poses, feeding in correct IPD offset
170 | ovrPosef HmdToEyeOffset[2] = { eyeRenderDesc[ovrEye_Left].HmdToEyePose,
171 | eyeRenderDesc[ovrEye_Right].HmdToEyePose };
172 |
173 |
174 | ovr_GetEyePoses(m_session, m_frameIndex, ovrTrue, HmdToEyeOffset, m_eyeRenderPose, &m_sensorSampleTime);
175 |
176 | ovrVector3f &posLeft = m_eyeRenderPose[ovrEye_Left].Position;
177 | ovrVector3f &posRight = m_eyeRenderPose[ovrEye_Right].Position;
178 | ovrQuatf orientLeft = m_eyeRenderPose[ovrEye_Left].Orientation;
179 | ovrQuatf orientRight = m_eyeRenderPose[ovrEye_Right].Orientation;
180 |
181 | QVector3D zero(0.0f,0.0f,0.0f);
182 | Matrix4f finalRollPitchYaw = Matrix4f(orientLeft).Transposed();
183 | Vector3f finalUp = finalRollPitchYaw.Transform(Vector3f(0, 1, 0));
184 | Vector3f finalForward = finalRollPitchYaw.Transform(Vector3f(0, 0, -1));
185 | leftEye.translate(QVector3D(posLeft.x, posLeft.y, posLeft.z));
186 | leftEye.lookAt(zero, QVector3D(finalForward.x, finalForward.y, finalForward.z), QVector3D(finalUp.x, finalUp.y, finalUp.z));
187 | finalRollPitchYaw = Matrix4f(orientRight).Transposed();
188 | finalUp = finalRollPitchYaw.Transform(Vector3f(0, 1, 0));
189 | finalForward = finalRollPitchYaw.Transform(Vector3f(0, 0, -1));
190 | rightEye.translate(QVector3D(posRight.x, posRight.y, posRight.z));
191 | rightEye.lookAt(zero, QVector3D(finalForward.x, finalForward.y, finalForward.z), QVector3D(finalUp.x, finalUp.y, finalUp.z));
192 | }
193 |
194 | void VirtualRealityApiOvr::getProjectionMatrices(QMatrix4x4 &leftProjection, QMatrix4x4 &rightProjection)
195 | {
196 | Matrix4f projLeft = ovrMatrix4f_Projection(m_hmdDesc.DefaultEyeFov[ovrEye_Left], 0.2f, 1000.0f, ovrProjection_None);
197 | Matrix4f projRight = ovrMatrix4f_Projection(m_hmdDesc.DefaultEyeFov[ovrEye_Right], 0.2f, 1000.0f, ovrProjection_None);
198 | QMatrix4x4 projL(projLeft.M[0][0], projLeft.M[0][1], projLeft.M[0][2], projLeft.M[0][3],
199 | projLeft.M[1][0], projLeft.M[1][1], projLeft.M[1][2], projLeft.M[1][3],
200 | projLeft.M[2][0], projLeft.M[2][1], projLeft.M[2][2], projLeft.M[2][3],
201 | projLeft.M[3][0], projLeft.M[3][1], projLeft.M[3][2], projLeft.M[3][3]);
202 | QMatrix4x4 projR(projRight.M[0][0], projRight.M[0][1], projRight.M[0][2], projRight.M[0][3],
203 | projRight.M[1][0], projRight.M[1][1], projRight.M[1][2], projRight.M[1][3],
204 | projRight.M[2][0], projRight.M[2][1], projRight.M[2][2], projRight.M[2][3],
205 | projRight.M[3][0], projRight.M[3][1], projRight.M[3][2], projRight.M[3][3]);
206 | leftProjection = projL;
207 | rightProjection = projR;
208 | //TODO: don't copy
209 | }
210 |
211 | QList VirtualRealityApiOvr::currentlyTrackedObjects()
212 | {
213 | //TODO: does this work?
214 | //return ovr_GetTrackerCount(m_session);
215 | return QList();
216 | }
217 |
218 | void VirtualRealityApiOvr::getTrackedObject(int id, QMatrix4x4 &transform)
219 | {
220 |
221 | }
222 |
223 | Qt3DVirtualReality::QVirtualRealityApiBackend::TrackedObjectType VirtualRealityApiOvr::getTrackedObjectType(int id)
224 | {
225 | return Qt3DVirtualReality::QVirtualRealityApiBackend::Other;
226 | }
227 |
228 | void VirtualRealityApiOvr::getTrackedObjectModel(int id, QVector &vertices, QVector &indices, QOpenGLTexture *texture)
229 | {
230 |
231 | }
232 |
233 | void VirtualRealityApiOvr::getMirrorTexture(QOpenGLTexture *outMirrorTexture)
234 | {
235 |
236 | }
237 |
238 | bool VirtualRealityApiOvr::isTriggerTmp()
239 | {
240 | //TO DO: check for real trigger
241 | return false;
242 | }
243 |
244 | qreal VirtualRealityApiOvr::refreshRate(int hmdId) const
245 | {
246 | return m_hmdDesc.DisplayRefreshRate;
247 | }
248 |
249 | QMatrix4x4 VirtualRealityApiOvr::headPose(int hmdId)
250 | {
251 | return QMatrix4x4();
252 | }
253 |
254 | QSize VirtualRealityApiOvr::getRenderTargetSize()
255 | {
256 | if(m_swapChain == nullptr)
257 | {
258 | ovrSizei idealTextureSizeLeft = ovr_GetFovTextureSize(m_session, ovrEye_Left, m_hmdDesc.DefaultEyeFov[ovrEye_Left], 1.0f);
259 | ovrSizei idealTextureSizeRight = ovr_GetFovTextureSize(m_session, ovrEye_Right, m_hmdDesc.DefaultEyeFov[ovrEye_Right], 1.0f);
260 | return QSize(idealTextureSizeLeft.w+idealTextureSizeRight.w, idealTextureSizeLeft.h);
261 | }
262 | return m_swapChain->size();
263 | }
264 |
265 | int VirtualRealityApiOvr::timeUntilNextFrame()
266 | {
267 | // TO DO what happens if m_frame has not yet been incremented?
268 | double absolutFrameTime = ovr_GetPredictedDisplayTime(m_session, m_frameIndex-1);
269 | double now = ovr_GetTimeInSeconds();
270 | return static_cast(std::floor(1000.0*(absolutFrameTime-now)));
271 | }
272 | #endif
273 |
--------------------------------------------------------------------------------
/virtualreality/qvirtualrealitygeometry.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | /*!
16 | * \class Qt3DExtras::QVirtualRealityGeometry
17 | * \inheaderfile Qt3DExtras/QVirtualRealityGeometry
18 | * \inmodule Qt3DExtras
19 | * \brief The QVirtualRealityGeometry class allows creation of a virtual reality representation of objects like controllers, hands, tracking cameras, lighthouses or tracking pucks in scenes.
20 | * \since 5.7
21 | * \ingroup geometries
22 | * \inherits Qt3DRender::QGeometry
23 | *
24 | * The QVirtualRealityGeometry class is most commonly used internally by the QVirtualrealityMesh
25 | * but can also be used in custom Qt3DRender::QGeometryRenderer subclasses.
26 | */
27 |
28 | // TO DO: Refactor from Cone
29 |
30 | #ifndef _USE_MATH_DEFINES
31 | # define _USE_MATH_DEFINES // For MSVC
32 | #endif
33 |
34 | #include "qvirtualrealitygeometry.h"
35 | #include "qvirtualrealitygeometry_p.h"
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 |
44 | QT_BEGIN_NAMESPACE
45 |
46 | using namespace Qt3DRender;
47 |
48 | namespace Qt3DVirtualReality {
49 |
50 | class VirtualrealityVertexDataFunctor : public QBufferDataGenerator
51 | {
52 | public:
53 | VirtualrealityVertexDataFunctor(QVirtualRealityApiBackend *apibackend, int trackedObjectIndex)
54 | : m_apibackend(apibackend)
55 | , m_trackedObjectIndex(trackedObjectIndex)
56 | {}
57 |
58 | QByteArray operator ()() Q_DECL_OVERRIDE
59 | {
60 | QVector vertices;
61 | QVector indices;
62 | QOpenGLTexture tex(QOpenGLTexture::Target2D);
63 | m_apibackend->getTrackedObjectModel(m_trackedObjectIndex, vertices, indices, &tex);
64 | return QByteArray::fromRawData( reinterpret_cast(vertices.constData()), sizeof(float) * vertices.size());
65 | }
66 |
67 | bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE
68 | {
69 | const VirtualrealityVertexDataFunctor *otherFunctor = functor_cast(&other);
70 | if (otherFunctor != nullptr)
71 | return (otherFunctor->m_trackedObjectIndex == m_trackedObjectIndex
72 | && otherFunctor->m_apibackend == m_apibackend);
73 | return false;
74 | }
75 |
76 | QT3D_FUNCTOR(VirtualrealityVertexDataFunctor)
77 |
78 | private:
79 | QVirtualRealityApiBackend *m_apibackend;
80 | int m_trackedObjectIndex;
81 | };
82 |
83 | class VirtualrealityIndexDataFunctor : public QBufferDataGenerator
84 | {
85 | public:
86 | VirtualrealityIndexDataFunctor(QVirtualRealityApiBackend *apibackend, int trackedObjectIndex)
87 | : m_apibackend(apibackend)
88 | , m_trackedObjectIndex(trackedObjectIndex)
89 | {}
90 |
91 | QByteArray operator ()() Q_DECL_OVERRIDE
92 | {
93 | QVector vertices;
94 | QVector indices;
95 | QOpenGLTexture tex(QOpenGLTexture::Target2D);
96 | m_apibackend->getTrackedObjectModel(m_trackedObjectIndex, vertices, indices, &tex);
97 | return QByteArray::fromRawData( reinterpret_cast(indices.constData()), sizeof(float) * indices.size());
98 | }
99 |
100 | bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE
101 | {
102 | const VirtualrealityIndexDataFunctor *otherFunctor = functor_cast(&other);
103 | if (otherFunctor != nullptr)
104 | return (otherFunctor->m_trackedObjectIndex == m_trackedObjectIndex
105 | && otherFunctor->m_apibackend == m_apibackend);
106 | return false;
107 | }
108 |
109 | QT3D_FUNCTOR(VirtualrealityIndexDataFunctor)
110 |
111 | private:
112 | QVirtualRealityApiBackend *m_apibackend;
113 | int m_trackedObjectIndex;
114 | };
115 |
116 |
117 | QVirtualRealityGeometryPrivate::QVirtualRealityGeometryPrivate()
118 | : QGeometryPrivate()
119 | , m_trackedObjectIndex(-1)
120 | , m_positionAttribute(nullptr)
121 | , m_normalAttribute(nullptr)
122 | , m_texCoordAttribute(nullptr)
123 | , m_indexAttribute(nullptr)
124 | , m_positionBuffer(nullptr)
125 | , m_vertexBuffer(nullptr)
126 | , m_indexBuffer(nullptr)
127 | , m_apibackend(nullptr)
128 | {
129 | }
130 |
131 | void QVirtualRealityGeometryPrivate::init()
132 | {
133 | Q_Q(QVirtualRealityGeometry);
134 | m_positionAttribute = new QAttribute(q);
135 | m_normalAttribute = new QAttribute(q);
136 | m_texCoordAttribute = new QAttribute(q);
137 | m_indexAttribute = new QAttribute(q);
138 | m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q);
139 | m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q);
140 |
141 | //TO DO: Vertx count and index count lazy. do not retrieve object for this.
142 | // vec3 pos, vec2 tex, vec3 normal
143 | const quint32 elementSize = 3 + 2 + 3;
144 | const quint32 stride = elementSize * sizeof(float);
145 | // QVector vertices;
146 | // QVector indices;
147 | // QOpenGLTexture tex(QOpenGLTexture::Target2D);
148 | // m_apibackend->getTrackedObjectModel(m_trackedObjectIndex, vertices, indices, &tex);
149 | const int faces = 1;//indices.count()/3;
150 | const int nVerts = 3;//vertices.count()/elementSize;
151 |
152 | m_positionAttribute->setName(QAttribute::defaultPositionAttributeName());
153 | m_positionAttribute->setVertexBaseType(QAttribute::Float);
154 | m_positionAttribute->setVertexSize(3);
155 | m_positionAttribute->setAttributeType(QAttribute::VertexAttribute);
156 | m_positionAttribute->setBuffer(m_vertexBuffer);
157 | m_positionAttribute->setByteStride(stride);
158 | m_positionAttribute->setCount(nVerts);
159 |
160 | m_normalAttribute->setName(QAttribute::defaultNormalAttributeName());
161 | m_normalAttribute->setVertexBaseType(QAttribute::Float);
162 | m_normalAttribute->setVertexSize(3);
163 | m_normalAttribute->setAttributeType(QAttribute::VertexAttribute);
164 | m_normalAttribute->setBuffer(m_vertexBuffer);
165 | m_normalAttribute->setByteStride(stride);
166 | m_normalAttribute->setByteOffset(3 * sizeof(float));
167 | m_normalAttribute->setCount(nVerts);
168 |
169 | m_texCoordAttribute->setName(QAttribute::defaultTextureCoordinateAttributeName());
170 | m_texCoordAttribute->setVertexBaseType(QAttribute::Float);
171 | m_texCoordAttribute->setVertexSize(2);
172 | m_texCoordAttribute->setAttributeType(QAttribute::VertexAttribute);
173 | m_texCoordAttribute->setBuffer(m_vertexBuffer);
174 | m_texCoordAttribute->setByteStride(stride);
175 | m_texCoordAttribute->setByteOffset(6 * sizeof(float));
176 | m_texCoordAttribute->setCount(nVerts);
177 |
178 | m_indexAttribute->setAttributeType(QAttribute::IndexAttribute);
179 | m_indexAttribute->setVertexBaseType(QAttribute::UnsignedInt);
180 | m_indexAttribute->setBuffer(m_indexBuffer);
181 |
182 | m_indexAttribute->setCount(faces * 3);
183 |
184 | //m_vertexBuffer->setDataGenerator(QSharedPointer::create(m_apibackend, m_trackedObjectIndex));
185 | //m_indexBuffer->setDataGenerator(QSharedPointer::create(m_apibackend, m_trackedObjectIndex));
186 |
187 | q->addAttribute(m_positionAttribute);
188 | q->addAttribute(m_normalAttribute);
189 | q->addAttribute(m_texCoordAttribute);
190 | q->addAttribute(m_indexAttribute);
191 | }
192 |
193 | /*!
194 | * \qmltype VirtualrealityGeometry
195 | * \instantiates Qt3DExtras::QVirtualRealityGeometry
196 | * \inqmlmodule Qt3D.Extras
197 | * \brief VirtualrealityGeometry allows creation of a virtualreality in 3D space.
198 | *
199 | * The VirtualrealityGeometry type is most commonly used internally by the VirtualrealityMesh type
200 | * but can also be used in custom GeometryRenderer types..
201 | */
202 |
203 | /*!
204 | * \qmlproperty Attribute VirtualrealityGeometry::positionAttribute
205 | *
206 | * Holds the geometry position attribute.
207 | */
208 |
209 | /*!
210 | * \qmlproperty Attribute VirtualrealityGeometry::normalAttribute
211 | *
212 | * Holds the geometry normal attribute.
213 | */
214 |
215 | /*!
216 | * \qmlproperty Attribute VirtualrealityGeometry::texCoordAttribute
217 | *
218 | * Holds the geometry texture coordinate attribute.
219 | */
220 |
221 | /*!
222 | * \qmlproperty Attribute VirtualrealityGeometry::indexAttribute
223 | *
224 | * Holds the geometry index attribute.
225 | */
226 |
227 | QVirtualRealityGeometry::QVirtualRealityGeometry(QNode *parent)
228 | : QGeometry(*new QVirtualRealityGeometryPrivate, parent)
229 | {
230 | Q_D(QVirtualRealityGeometry);
231 | d->init();
232 | }
233 |
234 | QVirtualRealityGeometry::QVirtualRealityGeometry(QVirtualRealityGeometryPrivate &dd, QNode *parent)
235 | :QGeometry(dd, parent)
236 | {
237 | Q_D(QVirtualRealityGeometry);
238 | d->init();
239 | }
240 |
241 |
242 | /*! \internal */
243 | QVirtualRealityGeometry::~QVirtualRealityGeometry()
244 | {
245 | }
246 |
247 | /*!
248 | * Updates vertices based on geometry properties.
249 | */
250 | void QVirtualRealityGeometry::updateVertices()
251 | {
252 | Q_D(QVirtualRealityGeometry);
253 |
254 | if(!d->m_apibackend) return;
255 | //TO DO: do not query whole object here. lazy loading of vertex count
256 | QVector vertices;
257 | QVector indices;
258 | QOpenGLTexture tex(QOpenGLTexture::Target2D);
259 | d->m_apibackend->getTrackedObjectModel(d->m_trackedObjectIndex, vertices, indices, &tex);
260 |
261 | d->m_positionAttribute->setCount(vertices.count()/8);
262 | d->m_texCoordAttribute->setCount(vertices.count()/8);
263 | d->m_normalAttribute->setCount(vertices.count()/8);
264 | d->m_vertexBuffer->setDataGenerator(QSharedPointer::create(d->m_apibackend, d->m_trackedObjectIndex));
265 | }
266 |
267 | /*!
268 | * Updates indices based on geometry properties.
269 | */
270 | void QVirtualRealityGeometry::updateIndices()
271 | {
272 | Q_D(QVirtualRealityGeometry);
273 |
274 | if(!d->m_apibackend) return;
275 | //TO DO: do not query whole object here. lazy loading of vertex count
276 | QVector vertices;
277 | QVector indices;
278 | QOpenGLTexture tex(QOpenGLTexture::Target2D);
279 | d->m_apibackend->getTrackedObjectModel(d->m_trackedObjectIndex, vertices, indices, &tex);
280 |
281 | d->m_indexAttribute->setCount(indices.count());
282 | d->m_indexBuffer->setDataGenerator(QSharedPointer::create(d->m_apibackend, d->m_trackedObjectIndex));
283 | }
284 |
285 | void QVirtualRealityGeometry::setVrApiBackendTmp(QVirtualRealityApiBackend *apibackend)
286 | {
287 | Q_D(QVirtualRealityGeometry);
288 | d->m_apibackend = apibackend;
289 | updateVertices();
290 | updateIndices();
291 | }
292 |
293 | int QVirtualRealityGeometry::trackedObjectIndex() const
294 | {
295 | const Q_D(QVirtualRealityGeometry);
296 | return d->m_trackedObjectIndex;
297 | }
298 |
299 | /*!
300 | * \property QVirtualRealityGeometry::positionAttribute
301 | *
302 | * Holds the geometry position attribute.
303 | */
304 |
305 | /*!
306 | * \property QVirtualRealityGeometry::normalAttribute
307 | *
308 | * Holds the geometry normal attribute.
309 | */
310 |
311 | /*!
312 | * \property QVirtualRealityGeometry::texCoordAttribute
313 | *
314 | * Holds the geometry texture coordinate attribute.
315 | */
316 |
317 | /*!
318 | * \property QVirtualRealityGeometry::indexAttribute
319 | *
320 | * Holds the geometry index attribute.
321 | */
322 |
323 |
324 | QAttribute *QVirtualRealityGeometry::positionAttribute() const
325 | {
326 | Q_D(const QVirtualRealityGeometry);
327 | return d->m_positionAttribute;
328 | }
329 |
330 | QAttribute *QVirtualRealityGeometry::normalAttribute() const
331 | {
332 | Q_D(const QVirtualRealityGeometry);
333 | return d->m_normalAttribute;
334 | }
335 |
336 | QAttribute *QVirtualRealityGeometry::texCoordAttribute() const
337 | {
338 | Q_D(const QVirtualRealityGeometry);
339 | return d->m_texCoordAttribute;
340 | }
341 |
342 | QAttribute *QVirtualRealityGeometry::indexAttribute() const
343 | {
344 | Q_D(const QVirtualRealityGeometry);
345 | return d->m_indexAttribute;
346 | }
347 |
348 | void QVirtualRealityGeometry::setTrackedObjectIndex(int trackedObjectIndex)
349 | {
350 | Q_D(QVirtualRealityGeometry);
351 | if (trackedObjectIndex != d->m_trackedObjectIndex) {
352 | d->m_trackedObjectIndex = trackedObjectIndex;
353 | updateVertices();
354 | updateIndices();
355 | Q_EMIT trackedObjectIndexChanged(trackedObjectIndex);
356 | }
357 | }
358 |
359 | } // namespace Qt3DVirtualReality
360 |
361 | QT_END_NAMESPACE
362 |
--------------------------------------------------------------------------------
/virtualreality/qheadmounteddisplay.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #include "qheadmounteddisplay.h"
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include
31 | #include
32 | #include "qvirtualrealityapibackend.h"
33 | #include
34 | #include
35 | #include
36 | #include "frontend/qvirtualrealitycamera.h"
37 | #include "frontend/qvirtualrealitymesh.h"
38 | #include
39 |
40 | QT_BEGIN_NAMESPACE
41 |
42 | namespace Qt3DVirtualReality {
43 |
44 | namespace {
45 |
46 | class Qt3DQuickVirtualRealityIncubationController : public QObject, public QQmlIncubationController
47 | {
48 | Q_OBJECT
49 | public:
50 | explicit Qt3DQuickVirtualRealityIncubationController(QHeadMountedDisplay *hmd)
51 | : QObject(hmd)
52 | , m_hmd(hmd)
53 | //, m_incubationTime(std::max(1, int(1000 / hmd->refreshRate()) / 3)) // Allow incubation for 1/3 of a frame.
54 | {
55 | startTimer(hmd->refreshRate());
56 | }
57 |
58 | void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE
59 | {
60 | int incubationTime = qMax(0, m_hmd->timeUntilNextFrame()-6); // present ~6ms before scanout
61 | qDebug() << "Incubating for" << incubationTime;
62 | if(incubationTime > 0)
63 | incubateFor(incubationTime);
64 | }
65 |
66 | private:
67 | //const int m_incubationTime;
68 | QHeadMountedDisplay *m_hmd;
69 | };
70 |
71 | } // anonymous
72 |
73 | QHeadMountedDisplay::QHeadMountedDisplay(int hmdId, const QHeadMountedDisplayFormat &formathmd, QVirtualRealityApi *api, QVirtualRealityApiBackend *apibackend)
74 | : QObject()
75 | , m_engine(nullptr)
76 | , m_renderAspect(nullptr)
77 | , m_inputAspect(nullptr)
78 | , m_logicAspect(nullptr)
79 | , m_virtualRealityAspect(nullptr)
80 | , m_initialized(false)
81 | , m_incubationController(nullptr)
82 | , m_api(api)
83 | , m_apibackend(apibackend)
84 | , m_hmdId(hmdId)
85 | , m_fbo(nullptr)
86 | , m_context(nullptr)
87 | , m_surface(new QOffscreenSurface)
88 | , m_rootItem(nullptr)
89 | {
90 | //Note: m_apibackend is not yet initialized here. Wait for openGLContext creation
91 |
92 | QSurfaceFormat format;
93 | // Qt Quick may need a depth and stencil buffer. Always make sure these are available.
94 | format.setDepthBufferSize(16);
95 | format.setStencilBufferSize(8);
96 | format.setProfile(QSurfaceFormat::CoreProfile);
97 | format.setOption(QSurfaceFormat::DebugContext);
98 |
99 | m_context = new QOpenGLContext;
100 | m_context->setFormat(format);
101 | m_context->create();
102 |
103 |
104 | m_surface = new QOffscreenSurface;
105 | // Pass m_context->format(), not format. Format does not specify and color buffer
106 | // sizes, while the context, that has just been created, reports a format that has
107 | // these values filled in. Pass this to the offscreen surface to make sure it will be
108 | // compatible with the context's configuration.
109 | m_surface->setFormat(m_context->format());
110 | m_surface->create();
111 | m_context->makeCurrent(m_surface);
112 |
113 | QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
114 |
115 | logger->initialize();
116 | connect(logger, &QOpenGLDebugLogger::messageLogged, this, [](const QOpenGLDebugMessage &debugMessage){
117 | qDebug() << debugMessage;
118 | }, Qt::DirectConnection);
119 | logger->enableMessages();
120 | logger->startLogging(QOpenGLDebugLogger::SynchronousLogging);
121 | emit surfaceChanged(m_surface);
122 |
123 | m_engine.reset(new Qt3DCore::Quick::QQmlAspectEngine);
124 | m_renderAspect = new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous);
125 | m_inputAspect = new Qt3DInput::QInputAspect;
126 | m_logicAspect = new Qt3DLogic::QLogicAspect;
127 | m_virtualRealityAspect = new Qt3DVirtualReality::QVirtualRealityAspect;
128 | m_virtualRealityAspect->setHeadmountedDisplay(this);
129 | //m_virtualRealityAspect->setVirtualRealityApi(m_api);
130 | m_virtualRealityAspect->setVirtualRealityApiBackend(m_apibackend);
131 |
132 | m_engine->aspectEngine()->registerAspect(m_renderAspect);
133 | m_engine->aspectEngine()->registerAspect(m_inputAspect);
134 | m_engine->aspectEngine()->registerAspect(m_logicAspect);
135 | m_engine->aspectEngine()->registerAspect(m_virtualRealityAspect);
136 | connect(this, &QHeadMountedDisplay::requestRun, this, &QHeadMountedDisplay::run, Qt::QueuedConnection);
137 | }
138 |
139 | QHeadMountedDisplay::~QHeadMountedDisplay()
140 | {
141 | if(m_surface)
142 | delete m_surface;
143 | }
144 |
145 | void QHeadMountedDisplay::registerAspect(Qt3DCore::QAbstractAspect *aspect)
146 | {
147 | m_engine->aspectEngine()->registerAspect(aspect);
148 | }
149 |
150 | void QHeadMountedDisplay::registerAspect(const QString &name)
151 | {
152 | m_engine->aspectEngine()->registerAspect(name);
153 | }
154 |
155 | void QHeadMountedDisplay::setSource(const QUrl &source)
156 | {
157 | m_source = source;
158 | if(!m_initialized)
159 | {
160 | // Connect to the QQmlAspectEngine's statusChanged signal so that when the QML is loaded
161 | // and th eobjects hav ebeen instantiated, but before we set them on the QAspectEngine we
162 | // can swoop in and set the window surface and camera on the framegraph and ensure the camera
163 | // respects the window's aspect ratio
164 | connect(m_engine.data(), &Qt3DCore::Quick::QQmlAspectEngine::sceneCreated,
165 | this, &QHeadMountedDisplay::onSceneCreated);
166 |
167 |
168 | qmlRegisterType("vr", 2, 0, "VrCamera");
169 | qmlRegisterType("vr", 2, 0, "TrackedObjectMesh");
170 | m_engine->setSource(m_source);
171 |
172 | // Set the QQmlIncubationController on the window
173 | // to benefit from asynchronous incubation
174 | if (!m_incubationController)
175 | m_incubationController = new Qt3DQuickVirtualRealityIncubationController(this);
176 |
177 | m_engine->qmlEngine()->setIncubationController(m_incubationController);
178 |
179 | m_initialized = true;
180 | }
181 | else
182 | {
183 | qDebug() << "source already set, not yet implemented."; // TO DO
184 | }
185 | }
186 |
187 | Qt3DCore::Quick::QQmlAspectEngine *QHeadMountedDisplay::engine() const
188 | {
189 | return m_engine.data();
190 | }
191 |
192 | qreal QHeadMountedDisplay::refreshRate()
193 | {
194 | Q_ASSERT(m_apibackend);
195 | return m_apibackend->refreshRate(m_hmdId);
196 | }
197 |
198 | QObject *QHeadMountedDisplay::surface() const
199 | {
200 | return qobject_cast(m_surface);
201 | }
202 |
203 | QSize QHeadMountedDisplay::renderTargetSize() const
204 | {
205 | return m_apibackend->getRenderTargetSize();
206 | }
207 |
208 | int QHeadMountedDisplay::timeUntilNextFrame()
209 | {
210 | return m_apibackend->timeUntilNextFrame();
211 | }
212 |
213 | QOpenGLContext *QHeadMountedDisplay::context()
214 | {
215 | return m_context;
216 | }
217 |
218 | void QHeadMountedDisplay::onSceneCreated(QObject *rootObject)
219 | {
220 | Q_ASSERT(rootObject);
221 |
222 | setWindowSurface(rootObject);
223 |
224 | m_rootItem = rootObject;//qobject_cast(rootObject);
225 | // if (m_cameraAspectRatioMode == AutomaticAspectRatio) {
226 | // // Set aspect ratio of first camera to match the window
227 | // QList cameras
228 | // = rootObject->findChildren();
229 | // if (cameras.isEmpty()) {
230 | // qWarning() << "No camera found";
231 | // } else {
232 | // m_camera = cameras.first();
233 | // setCameraAspectModeHelper();
234 | // }
235 | // }
236 |
237 | if(m_rootItem) {
238 | QVirtualrealityCamera *vrCamera = m_rootItem->findChild();
239 | if(vrCamera) {
240 | QMatrix4x4 projL;
241 | QMatrix4x4 projR;
242 | m_apibackend->getProjectionMatrices(projL, projR);
243 | vrCamera->setProjections(projL, projR);
244 | vrCamera->setLeftNormalizedViewportRect(QRectF(0.0f, 0.0f, 0.5f, 1.0f));
245 | vrCamera->setRightNormalizedViewportRect(QRectF(0.5f, 0.0f, 0.5f, 1.0f));
246 | } else {
247 | Q_ASSERT(vrCamera); //TO DO logging
248 | }
249 | } else {
250 | Q_ASSERT(m_rootItem); //TO DO logging
251 | }
252 |
253 | // Set ourselves up as a source of input events for the input aspect
254 | Qt3DInput::QInputSettings *inputSettings = rootObject->findChild();
255 | if (inputSettings) {
256 | inputSettings->setEventSource(this);
257 | } else {
258 | qWarning() << "No Input Settings found, keyboard and mouse events won't be handled";
259 | }
260 | Q_EMIT sceneCreated(m_rootItem);
261 | }
262 |
263 | void QHeadMountedDisplay::run() {
264 |
265 | m_context->makeCurrent(m_surface);
266 |
267 |
268 | // QOpenGLFramebufferObjectFormat format;
269 | // format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
270 | // format.setTextureTarget(GL_TEXTURE_2D);
271 | // format.setSamples(0);
272 | // format.setMipmap(false);
273 |
274 | // QSize renderTargetSize = m_apibackend->getRenderSurfaceSize();
275 | // if(m_fbo)
276 | // delete m_fbo;
277 | // m_fbo = new QOpenGLFramebufferObject(renderTargetSize, format, m_apibackend->currentTextureId() );
278 | // m_fbo->bind();
279 |
280 | //glViewport(0, 0, renderTargetSize.width(), renderTargetSize.height());
281 |
282 | // Q_ASSERT(false);//TO DO: wrong thread for m_fbo->bind(). need QSGNode. What about createTextureFromId?
283 | // if (m_aspectEngine->rootEntity() != m_item->entity())
284 | // scheduleRootEntityChange();
285 | //TODO: QVrSelector. This is the object with all parameters then
286 | QVirtualrealityCamera *vrCamera(nullptr);
287 | QList vrGeometries;
288 | if(m_rootItem) {
289 | vrCamera = m_rootItem->findChild();
290 | vrGeometries = m_rootItem->findChildren();
291 | }
292 | m_apibackend->bindFrambufferObject(m_hmdId);
293 | for(QList::iterator iter(vrGeometries.begin()); iter != vrGeometries.end(); ++iter) {
294 | (*iter)->setVrApiBackendTmp(m_apibackend);
295 | }
296 | //static_cast(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect))->jobManager()->waitForAllJobs();
297 | static_cast(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous();
298 | QMatrix4x4 leftEye;
299 | QMatrix4x4 rightEye;
300 | m_apibackend->getEyeMatrices(leftEye, rightEye);
301 | if(vrCamera != nullptr) {
302 | vrCamera->update(leftEye, rightEye);
303 | vrCamera->setVrBackendTmp(m_apibackend); // only for transforms
304 | }
305 | m_fbo->bindDefault();
306 | m_apibackend->swapToHeadset();
307 | emit requestRun();
308 | }
309 |
310 | void QHeadMountedDisplay::setWindowSurface(QObject *rootObject)
311 | {
312 | // if(!(m_context = QOpenGLContext::currentContext()))
313 | // {
314 | // m_context = new QOpenGLContext();
315 | // m_context->create();
316 | // m_context->makeCurrent(m_surface);
317 | // Q_ASSERT(QOpenGLContext::currentContext() != nullptr);
318 | // }
319 | m_context->makeCurrent(m_surface);
320 | static_cast(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect))->renderInitialize(m_context);
321 | Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(rootObject);
322 | if (surfaceSelector)
323 | surfaceSelector->setSurface(m_surface);
324 | if (m_fbo) {
325 | delete m_fbo;
326 | m_fbo = nullptr;
327 | }
328 | const QSize texSize(m_apibackend->getRenderTargetSize());
329 |
330 | //TODO: At the moment FBO is recreated each frame
331 | //if (!m_fbo) {
332 | QOpenGLFramebufferObjectFormat format;
333 | format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
334 | format.setTextureTarget(GL_TEXTURE_2D);
335 | format.setSamples(0);
336 | format.setMipmap(false);
337 |
338 | // QSurfaceFormat notUsedTodo;
339 | // m_apibackend->createSurface(m_hmdId, texSize, notUsedTodo);
340 | emit renderTargetSizeChanged(texSize);
341 | //m_fbo = new QOpenGLFramebufferObject(texSize, format, texId );
342 | //m_quickWindow->setRenderTarget(m_fbo);
343 | //}
344 | // if(!sizeOkay)
345 | // {
346 | // // Size of m_window can differ from m_quickWindow and rendertarget size
347 | // m_quickWindow->resize(texSize);
348 | // m_quickWindow->contentItem()->setWidth(texSize.width());
349 | // m_quickWindow->contentItem()->setHeight(texSize.height());
350 | // m_quickWindow->setGeometry(0, 0, texSize.width(), texSize.height());
351 | // }
352 | }
353 |
354 | } // Qt3DVirtualReality
355 |
356 | QT_END_NAMESPACE
357 |
358 | #include "qheadmounteddisplay.moc"
359 |
--------------------------------------------------------------------------------
/virtualreality/vrbackends/openvr/virtualrealityapiopenvr.cpp:
--------------------------------------------------------------------------------
1 | //****************************************************************************
2 | //**
3 | //** Author: Daniel Bulla
4 | //** Contact: qt3d-vr@danielbulla.de
5 | //**
6 | //** GNU Lesser General Public License Usage
7 | //** General Public License version 3 as published by the Free Software
8 | //** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 | //** packaging of this file. Please review the following information to
10 | //** ensure the GNU Lesser General Public License version 3 requirements
11 | //** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 | //**
13 | //****************************************************************************/
14 |
15 | #if(QT3DVR_COMPILE_WITH_OPENVR)
16 | #include "virtualrealityapiopenvr.h"
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | //// Process SteamVR controller state
23 | //for( vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; unDevice++ )
24 | //{
25 | // vr::VRControllerState_t state;
26 | // if( m_pHMD->GetControllerState( unDevice, &state, sizeof(state) ) )
27 | // {
28 | // m_rbShowTrackedDevice[ unDevice ] = state.ulButtonPressed == 0;
29 | // }
30 | //}
31 |
32 | //-----------------------------------------------------------------------------
33 | // Purpose: Helper to get a string from a tracked device property and turn it
34 | // into a std::string
35 | //-----------------------------------------------------------------------------
36 | std::string getTrackedDeviceString( vr::IVRSystem *hmd, vr::TrackedDeviceIndex_t device, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *error = NULL )
37 | {
38 | uint32_t requiredBufferLen = hmd->GetStringTrackedDeviceProperty( device, prop, NULL, 0, error );
39 | if( requiredBufferLen == 0 )
40 | return "";
41 |
42 | char *buffer = new char[ requiredBufferLen ];
43 | requiredBufferLen = hmd->GetStringTrackedDeviceProperty( device, prop, buffer, requiredBufferLen, error );
44 | std::string result = buffer;
45 | delete [] buffer;
46 | return result;
47 | }
48 |
49 | //-----------------------------------------------------------------------------
50 | // Purpose: Gets a Matrix Projection Eye with respect to nEye.
51 | //-----------------------------------------------------------------------------
52 | QMatrix4x4 VirtualRealityApiOpenVR::getHmdMatrixProjectionEye( vr::Hmd_Eye nEye )
53 | {
54 | if ( !m_hmd )
55 | return QMatrix4x4();
56 | float nearClip = 0.2f;
57 | float farClip = 1000.0f;
58 | vr::HmdMatrix44_t mat = m_hmd->GetProjectionMatrix( nEye, nearClip, farClip );
59 |
60 | return convertSteamVrMatrixToQMatrix4x4(mat);
61 | // return QMatrix4x4(
62 | // mat.m[0][0], mat.m[0][1], -mat.m[0][2], mat.m[0][3],
63 | // mat.m[1][0], mat.m[1][1], -mat.m[1][2], mat.m[1][3],
64 | // mat.m[2][0], mat.m[2][1], -mat.m[2][2], mat.m[2][3],
65 | // mat.m[3][0], mat.m[3][1], -mat.m[3][2], mat.m[3][3]
66 | // );
67 | }
68 |
69 | //-----------------------------------------------------------------------------
70 | // Purpose: Gets an HMDMatrixPoseEye with respect to nEye.
71 | //-----------------------------------------------------------------------------
72 | QMatrix4x4 VirtualRealityApiOpenVR::getHmdMatrixPoseEye( vr::Hmd_Eye nEye )
73 | {
74 | if ( !m_hmd )
75 | return QMatrix4x4();
76 |
77 | vr::HmdMatrix34_t mat = m_hmd->GetEyeToHeadTransform( nEye );
78 | return convertSteamVrMatrixToQMatrix4x4(mat);//.inverted();
79 | }
80 |
81 | //-----------------------------------------------------------------------------
82 | // Purpose: Gets a Current View Projection Matrix with respect to nEye,
83 | // which may be an Eye_Left or an Eye_Right.
84 | //-----------------------------------------------------------------------------
85 | QMatrix4x4 VirtualRealityApiOpenVR::getCurrentViewMatrix( vr::Hmd_Eye nEye )
86 | {
87 | QMatrix4x4 matMVP;
88 | if( nEye == vr::Eye_Left )
89 | {
90 | matMVP = m_eyePosLeft * m_hmdPose;
91 | }
92 | else if( nEye == vr::Eye_Right )
93 | {
94 | matMVP = m_eyePosRight * m_hmdPose;
95 | }
96 |
97 | return matMVP;
98 | }
99 |
100 | //-----------------------------------------------------------------------------
101 | // Purpose:
102 | //-----------------------------------------------------------------------------
103 | void VirtualRealityApiOpenVR::updateHmdMatrixPose()
104 | {
105 | // This queries the pose for user. User gets a good estimation of the HMD pose that will be used.
106 | // However, the engine is free to use a newer estimation for the head pose for rendering, than returned here.
107 | // Only one estimation will be made on the first request of poses per frame.
108 | // This way e.g. not every qml binding will query the vr sdk on its own.
109 | if(m_poseNewEnough)
110 | return;
111 | m_poseNewEnough = true;
112 | if ( !m_hmd )
113 | return;
114 |
115 | vr::VRCompositor()->WaitGetPoses(m_trackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0 );
116 |
117 | m_validPoseCount = 0;
118 | m_poseClasses = "";
119 | for ( int deviceIndex = 0; deviceIndex < vr::k_unMaxTrackedDeviceCount; ++deviceIndex )
120 | {
121 | if ( m_trackedDevicePose[deviceIndex].bPoseIsValid )
122 | {
123 | m_validPoseCount++;
124 | m_devicePose[deviceIndex] = convertSteamVrMatrixToQMatrix4x4( m_trackedDevicePose[deviceIndex].mDeviceToAbsoluteTracking );
125 | if (m_devClassChar[deviceIndex]==0)
126 | {
127 | switch (m_hmd->GetTrackedDeviceClass(deviceIndex))
128 | {
129 | case vr::TrackedDeviceClass_Controller: m_devClassChar[deviceIndex] = 'C'; break;
130 | case vr::TrackedDeviceClass_HMD: m_devClassChar[deviceIndex] = 'H'; break;
131 | case vr::TrackedDeviceClass_Invalid: m_devClassChar[deviceIndex] = 'I'; break;
132 | case vr::TrackedDeviceClass_GenericTracker: m_devClassChar[deviceIndex] = 'G'; break;
133 | case vr::TrackedDeviceClass_TrackingReference: m_devClassChar[deviceIndex] = 'T'; break;
134 | default: m_devClassChar[deviceIndex] = '?'; break;
135 | }
136 | }
137 | m_poseClasses += m_devClassChar[deviceIndex];
138 | }
139 | }
140 |
141 | if ( m_trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid )
142 | {
143 | m_hmdPose = m_devicePose[vr::k_unTrackedDeviceIndex_Hmd];
144 | //m_hmdPose = m_hmdPose.inverted();
145 | }
146 |
147 | m_isTrigger = false;
148 | for( vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; unDevice++ )
149 | {
150 | vr::VRControllerState_t state;
151 | if( m_hmd->GetControllerState( unDevice, &state, sizeof(state) ) )
152 | {
153 | m_isTrigger |= state.ulButtonPressed != 0;
154 | }
155 | }
156 | }
157 |
158 | void VirtualRealityApiOpenVR::setupCameras()
159 | {
160 | m_eyePosLeft = getHmdMatrixPoseEye( vr::Eye_Left );
161 | m_eyePosRight = getHmdMatrixPoseEye( vr::Eye_Right );
162 | qDebug() << "Left eye " << m_eyePosLeft.column(3);
163 | qDebug() << "Right eye" << m_eyePosRight.column(3);
164 | }
165 |
166 | //-----------------------------------------------------------------------------
167 | // Purpose: Converts a SteamVR matrix to our local matrix class
168 | //-----------------------------------------------------------------------------
169 | QMatrix4x4 VirtualRealityApiOpenVR::convertSteamVrMatrixToQMatrix4x4( const vr::HmdMatrix34_t matPose )
170 | {
171 | return QMatrix4x4(matPose.m[0][0], matPose.m[0][1], matPose.m[0][2], matPose.m[0][3],
172 | matPose.m[1][0], matPose.m[1][1], matPose.m[1][2], matPose.m[1][3],
173 | matPose.m[2][0], matPose.m[2][1], matPose.m[2][2], matPose.m[2][3],
174 | 0.0f, 0.0f, 0.0f, 1.0f);
175 | }
176 |
177 | QMatrix4x4 VirtualRealityApiOpenVR::convertSteamVrMatrixToQMatrix4x4( const vr::HmdMatrix44_t matPose )
178 | {
179 | return QMatrix4x4(matPose.m[0][0], matPose.m[0][1], matPose.m[0][2], matPose.m[0][3],
180 | matPose.m[1][0], matPose.m[1][1], matPose.m[1][2], matPose.m[1][3],
181 | matPose.m[2][0], matPose.m[2][1], matPose.m[2][2], matPose.m[2][3],
182 | matPose.m[3][0], matPose.m[3][1], matPose.m[3][2], matPose.m[3][3]);
183 | }
184 |
185 | //QMatrix4x4 VirtualRealityApiOpenVR::convertSteamVrMatrixToQMatrix4x4( const vr::HmdMatrix44_t matPose )
186 | //{
187 | // return QMatrix4x4(matPose.m[0][0], matPose.m[1][0], matPose.m[2][0], matPose.m[3][0],
188 | // matPose.m[0][1], matPose.m[1][1], matPose.m[2][1], matPose.m[3][1],
189 | // matPose.m[0][2], matPose.m[1][2], matPose.m[2][2], matPose.m[3][2],
190 | // matPose.m[0][3], matPose.m[1][3], matPose.m[2][3], matPose.m[3][3]);
191 | //}
192 |
193 | bool VirtualRealityApiOpenVR::isRuntimeInstalled()
194 | {
195 | return vr::VR_IsRuntimeInstalled();
196 | }
197 |
198 | VirtualRealityApiOpenVR::VirtualRealityApiOpenVR()
199 | : m_fbo(nullptr)
200 | , m_poseNewEnough(false)
201 | , m_isTrigger(false)
202 | {
203 |
204 | }
205 |
206 | bool VirtualRealityApiOpenVR::isHmdPresent()
207 | {
208 | return vr::VR_IsHmdPresent();
209 | }
210 |
211 | void VirtualRealityApiOpenVR::initialize()
212 | {
213 | vr::EVRInitError error = vr::VRInitError_None;
214 | m_hmd = vr::VR_Init( &error, vr::VRApplication_Scene );
215 |
216 | if ( error != vr::VRInitError_None )
217 | {
218 | m_hmd = NULL;
219 | qDebug() << "Unable to init VR runtime:" << vr::VR_GetVRInitErrorAsEnglishDescription( error );
220 | return;
221 | }
222 |
223 | m_driver = getTrackedDeviceString( m_hmd, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String );
224 | m_display = getTrackedDeviceString( m_hmd, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String );
225 |
226 | vr::EVRInitError peError = vr::VRInitError_None;
227 |
228 | if ( !vr::VRCompositor() )
229 | {
230 | qDebug() << "Compositor initialization failed. See log file for details";
231 | return;
232 | }
233 | setupCameras();
234 |
235 | m_fbo = new QOpenGLFramebufferObject(getRenderTargetSize(), QOpenGLFramebufferObject::Depth);
236 | m_fbo->addColorAttachment(m_fbo->size(), GL_RGBA8);
237 | }
238 |
239 | void VirtualRealityApiOpenVR::shutdown()
240 | {
241 | if( m_hmd ) {
242 | vr::VR_Shutdown();
243 | m_hmd = NULL;
244 | }
245 | if(m_fbo) {
246 | delete m_fbo;
247 | m_fbo = nullptr;
248 | }
249 | }
250 |
251 |
252 | void VirtualRealityApiOpenVR::processVrEvent( const vr::VREvent_t & event )
253 | {
254 | switch( event.eventType )
255 | {
256 | case vr::VREvent_TrackedDeviceActivated:
257 | {
258 | // SetupRenderModelForTrackedDevice( event.trackedDeviceIndex );
259 | qDebug() << "Device" << event.trackedDeviceIndex << "attached. Setting up render model.";
260 | }
261 | break;
262 | case vr::VREvent_TrackedDeviceDeactivated:
263 | {
264 | qDebug() << "Device" << event.trackedDeviceIndex << "detached.";
265 | }
266 | break;
267 | case vr::VREvent_TrackedDeviceUpdated:
268 | {
269 | qDebug() << "Device" << event.trackedDeviceIndex << "updated.";
270 | }
271 | break;
272 | }
273 | }
274 |
275 | bool VirtualRealityApiOpenVR::bindFrambufferObject(int hmdId)
276 | {
277 | return m_fbo->bind();
278 | }
279 |
280 | qreal VirtualRealityApiOpenVR::refreshRate(int hmdId) const
281 | {
282 | return 90.f;
283 | }
284 |
285 | QMatrix4x4 VirtualRealityApiOpenVR::headPose(int hmdId)
286 | {
287 | updateHmdMatrixPose();
288 | return m_hmdPose;
289 | }
290 |
291 | QSize VirtualRealityApiOpenVR::getRenderTargetSize()
292 | {
293 | if ( !m_hmd ) return QSize(0, 0);
294 | uint32_t width, height;
295 | m_hmd->GetRecommendedRenderTargetSize( &width, &height );
296 | return QSize(width*2, height);
297 | //return QSize(width, height);
298 | }
299 |
300 | int VirtualRealityApiOpenVR::timeUntilNextFrame()
301 | {
302 | return 1000/90;
303 | }
304 |
305 | void VirtualRealityApiOpenVR::swapToHeadset()
306 | {
307 | vr::Texture_t leftEyeTexture = {(void*)m_fbo->handle(), vr::TextureType_OpenGL, vr::ColorSpace_Gamma };
308 | vr::VRTextureBounds_t leftViewport = {0.0f, 0.0f, 0.5f, 1.0f};
309 | vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture, &leftViewport );
310 | vr::Texture_t rightEyeTexture = {(void*)m_fbo->handle(), vr::TextureType_OpenGL, vr::ColorSpace_Gamma };
311 | vr::VRTextureBounds_t rightViewport = {0.5f, 0.0f, 1.0f, 1.0f};
312 | vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTexture, &rightViewport );
313 | m_poseNewEnough = false;
314 | // QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
315 | // f->glFlush();
316 | // f->glFinish();
317 | }
318 |
319 | void VirtualRealityApiOpenVR::getEyeMatrices(QMatrix4x4 &leftEye, QMatrix4x4 &rightEye)
320 | {
321 | updateHmdMatrixPose();
322 | leftEye = getCurrentViewMatrix(vr::Eye_Left);
323 | rightEye = getCurrentViewMatrix(vr::Eye_Right);
324 | }
325 |
326 | void VirtualRealityApiOpenVR::getProjectionMatrices(QMatrix4x4 &leftProjection, QMatrix4x4 &rightProjection)
327 | {
328 | leftProjection = getHmdMatrixProjectionEye( vr::Eye_Left );
329 | rightProjection = getHmdMatrixProjectionEye( vr::Eye_Right );
330 | }
331 |
332 | QList VirtualRealityApiOpenVR::currentlyTrackedObjects()
333 | {
334 | QList tracked;
335 | for( uint32_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++ ) {
336 | if( m_hmd->IsTrackedDeviceConnected( unTrackedDevice ) )
337 | tracked.push_back(unTrackedDevice);
338 | }
339 | return tracked;
340 | }
341 |
342 | void VirtualRealityApiOpenVR::getTrackedObject(int id, QMatrix4x4 &transform)
343 | {
344 | if( id >= vr::k_unMaxTrackedDeviceCount) {
345 | qWarning("Requested tracked object: Index out of bounds.");
346 | return;
347 | }
348 | if( !m_hmd->IsTrackedDeviceConnected( id ) ) {
349 | qWarning((QString("Requested VR Device was not connected. (id: ") + QString::number(id) + ")").toLatin1());
350 | return;
351 | }
352 | transform = m_devicePose[ id ];
353 | }
354 |
355 | Qt3DVirtualReality::QVirtualRealityApiBackend::TrackedObjectType VirtualRealityApiOpenVR::getTrackedObjectType(int id)
356 | {
357 | return Qt3DVirtualReality::QVirtualRealityApiBackend::Other;
358 | }
359 | bool VirtualRealityApiOpenVR::isTriggerTmp()
360 | {
361 | return m_isTrigger;
362 | }
363 |
364 | void VirtualRealityApiOpenVR::getTrackedObjectModel(int id, QVector &vertices, QVector &indices, QOpenGLTexture *texture)
365 | {
366 | if( id >= vr::k_unMaxTrackedDeviceCount) {
367 | qWarning("Requested tracked object vertices: Index out of bounds.");
368 | return;
369 | }
370 |
371 | if (m_models.contains(id)){
372 | vertices = m_models[id]->vertices;
373 | indices = m_models[id]->indices;
374 | texture = m_models[id]->texture;
375 | return;
376 | }
377 |
378 | std::string sRenderModelName = getTrackedDeviceString( m_hmd, id, vr::Prop_RenderModelName_String );
379 |
380 | //TODO: load renderModels only once
381 |
382 | vr::RenderModel_t *pModel;
383 | vr::EVRRenderModelError error;
384 | while ( 1 ) {
385 | error = vr::VRRenderModels()->LoadRenderModel_Async( sRenderModelName.c_str(), &pModel );
386 | if ( error != vr::VRRenderModelError_Loading )
387 | break;
388 | QThread::currentThread()->sleep( 1 );
389 | }
390 |
391 | if ( error != vr::VRRenderModelError_None ) {
392 | qWarning( "Unable to load render model %s - %s\n", sRenderModelName.c_str(), vr::VRRenderModels()->GetRenderModelErrorNameFromEnum( error ) );
393 | return;
394 | }
395 |
396 | vr::RenderModel_TextureMap_t *pTexture;
397 | while ( 1 ) {
398 | error = vr::VRRenderModels()->LoadTexture_Async( pModel->diffuseTextureId, &pTexture );
399 | if ( error != vr::VRRenderModelError_Loading )
400 | break;
401 | QThread::currentThread()->sleep( 1 );
402 | }
403 |
404 | if ( error != vr::VRRenderModelError_None ) {
405 | qWarning( "Unable to load render texture id:%d for render model %s\n", pModel->diffuseTextureId, sRenderModelName.c_str() );
406 | vr::VRRenderModels()->FreeRenderModel( pModel );
407 | return;
408 | }
409 |
410 | //Position, Normal, Texture
411 | vertices.resize(pModel->unVertexCount * (3 + 3 + 2));
412 | memcpy(vertices.data(), pModel->rVertexData, sizeof(float) * vertices.size());
413 | indices.resize(pModel->unTriangleCount * 3);
414 | for(int i=0; iunTriangleCount; i++) {
415 | indices[i*3 ] = pModel->rIndexData[i*3 ];
416 | indices[i*3+1] = pModel->rIndexData[i*3+1];
417 | indices[i*3+2] = pModel->rIndexData[i*3+2];
418 | }
419 |
420 | //texture = new QOpenGLTexture(QOpenGLTexture::BindingTarget2D);
421 | texture->setSize(pTexture->unWidth, pTexture->unHeight);
422 | texture->setData( QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, pTexture->rubTextureMapData );
423 |
424 | m_models.insert(id,new TrackedObjectModel(vertices, indices, texture));
425 |
426 | vr::VRRenderModels()->FreeRenderModel( pModel );
427 | vr::VRRenderModels()->FreeTexture( pTexture );
428 | }
429 |
430 | void VirtualRealityApiOpenVR::getMirrorTexture(QOpenGLTexture *outMirrorTexture)
431 | {
432 |
433 | }
434 | #endif
435 |
--------------------------------------------------------------------------------