├── .github └── workflows │ ├── ci-linux.yml │ └── ci-windows.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── examples ├── CMakeLists.txt ├── features │ ├── common │ │ ├── example_functions.cpp │ │ └── example_main_desktop.cpp │ ├── composition_layers │ │ ├── CMakeLists.txt │ │ ├── android-quest │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── app │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── build.gradle │ │ │ │ ├── cpp │ │ │ │ │ ├── CMakeLists.txt │ │ │ │ │ └── main.cpp │ │ │ │ └── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ └── values │ │ │ │ │ └── strings.xml │ │ │ ├── build.gradle │ │ │ ├── gradle.properties │ │ │ ├── gradle │ │ │ │ └── wrapper │ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ └── settings.gradle │ │ ├── game.cpp │ │ ├── game.h │ │ ├── interaction.cpp │ │ ├── interaction.h │ │ ├── interactions │ │ │ ├── interaction_teleport.cpp │ │ │ └── interaction_teleport.h │ │ └── main.cpp │ └── interaction_locomotion │ │ ├── CMakeLists.txt │ │ ├── android-quest │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app │ │ │ ├── AndroidManifest.xml │ │ │ ├── build.gradle │ │ │ ├── cpp │ │ │ │ ├── CMakeLists.txt │ │ │ │ └── main.cpp │ │ │ └── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── strings.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ │ ├── game.cpp │ │ ├── game.h │ │ ├── interaction.cpp │ │ ├── interaction.h │ │ ├── interactions │ │ ├── interaction_slide.cpp │ │ ├── interaction_slide.h │ │ ├── interaction_teleport.cpp │ │ └── interaction_teleport.h │ │ └── main.cpp └── platform │ ├── android-monado │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── cpp │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── debug │ │ │ ├── app-debug.apk │ │ │ └── output-metadata.json │ │ ├── release │ │ │ ├── app-release.apk │ │ │ └── output-metadata.json │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ └── strings.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ ├── android-quest │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── cpp │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ └── strings.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ └── generic │ ├── CMakeLists.txt │ └── main.cpp ├── models ├── assets │ └── teleport_marker │ │ ├── teleport_marker.blend │ │ ├── teleport_marker.cpp │ │ └── teleport_marker.glb ├── controller │ ├── controller.blend │ ├── controller.cpp │ ├── controller.glb │ ├── controller.vsgt │ ├── controller2.blend │ ├── controller2.cpp │ ├── controller2.glb │ └── controller2.vsgt └── world │ ├── world.blend │ ├── world.cpp │ ├── world.glb │ └── world.vsgt ├── readme.md ├── vsgvr ├── CMakeLists.txt ├── include │ └── vsgvr │ │ ├── actions │ │ ├── Action.h │ │ ├── ActionPoseBinding.h │ │ ├── ActionSet.h │ │ └── SpaceBinding.h │ │ ├── app │ │ ├── CompositionLayer.h │ │ ├── CompositionLayer.h.bak │ │ ├── CompositionLayerProjection.h │ │ ├── CompositionLayerQuad.h │ │ ├── UserOrigin.h │ │ └── Viewer.h │ │ ├── extensions │ │ ├── KHRCompositionLayerEquirect.h │ │ └── KHRCompositionLayerEquirect2.h │ │ └── xr │ │ ├── AndroidTraits.h │ │ ├── Common.h │ │ ├── EventHandler.h │ │ ├── Exception.h │ │ ├── GraphicsBindingVulkan.h │ │ ├── Instance.h │ │ ├── Pose.h │ │ ├── ProjectionMatrix.h │ │ ├── ReferenceSpace.h │ │ ├── Session.h │ │ ├── Swapchain.h │ │ ├── Traits.h │ │ └── ViewMatrix.h └── src │ └── vsgvr │ ├── actions │ ├── Action.cpp │ ├── ActionPoseBinding.cpp │ ├── ActionSet.cpp │ └── SpaceBinding.cpp │ ├── app │ ├── CompositionLayer.cpp │ ├── CompositionLayerProjection.cpp │ ├── CompositionLayerQuad.cpp │ ├── UserOrigin.cpp │ └── Viewer.cpp │ ├── extensions │ ├── KHRCompositionLayerEquirect.cpp │ └── KHRCompositionLayerEquirect2.cpp │ └── xr │ ├── AndroidTraits.cpp │ ├── EventHandler.cpp │ ├── GraphicsBindingVulkan.cpp │ ├── Instance.cpp │ ├── Macros.cpp │ ├── Pose.cpp │ ├── ReferenceSpace.cpp │ ├── Session.cpp │ ├── Swapchain.cpp │ └── Traits.cpp └── vsgvrConfig.cmake.in /.github/workflows/ci-linux.yml: -------------------------------------------------------------------------------- 1 | name: Compile Check (Linux) 2 | on: 3 | push: 4 | pull_request: 5 | env: 6 | CMakeVersion: 3.14.x 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | vsg-tag: [master, VulkanSceneGraph-1.0] 13 | build-shared: [ON] 14 | vulkan-version: [1.3.224.1] 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | with: 19 | submodules: true 20 | 21 | - name: Setup cmake 22 | uses: jwlawson/actions-setup-cmake@v1.13 23 | with: 24 | cmake-version: ${{ env.CMakeVersion }} 25 | 26 | - name: Install Vulkan SDK 27 | uses: humbletim/install-vulkan-sdk@v1.1.1 28 | with: 29 | version: ${{ matrix.vulkan-version }} 30 | cache: true 31 | 32 | - name: Checkout vsg 33 | uses: actions/checkout@v3 34 | with: 35 | repository: vsg-dev/VulkanSceneGraph 36 | ref: ${{matrix.vsg-tag}} 37 | path: vsg 38 | submodules: true 39 | 40 | - name: Build and Install VSG 41 | shell: bash 42 | run: | 43 | cd vsg 44 | cmake . -DBUILD_SHARED_LIBS=${{matrix.build-shared}} -DCMAKE_INSTALL_PREFIX=../install 45 | cmake --build . --target install --config Release --parallel 4 46 | 47 | - name: Build and Install VSGVR 48 | shell: bash 49 | run: | 50 | cmake . -DBUILD_SHARED_LIBS=${{matrix.build-shared}} -DCMAKE_INSTALL_PREFIX=./install 51 | cmake --build . --target install --config Release --parallel 4 52 | -------------------------------------------------------------------------------- /.github/workflows/ci-windows.yml: -------------------------------------------------------------------------------- 1 | name: Compile Check (Windows) 2 | on: 3 | push: 4 | pull_request: 5 | env: 6 | CMakeVersion: 3.21.x 7 | jobs: 8 | build: 9 | runs-on: windows-latest 10 | strategy: 11 | matrix: 12 | vsg-tag: [master, VulkanSceneGraph-1.0] 13 | build-shared: [ON] 14 | vulkan-version: [1.3.224.1] 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | with: 19 | submodules: true 20 | - name: Setup cmake 21 | uses: jwlawson/actions-setup-cmake@v1.13 22 | with: 23 | cmake-version: ${{ env.CMakeVersion }} 24 | - name: Install Vulkan SDK 25 | uses: humbletim/install-vulkan-sdk@v1.1.1 26 | with: 27 | version: ${{ matrix.vulkan-version }} 28 | cache: true 29 | - name: Add MSBuild to PATH 30 | uses: microsoft/setup-msbuild@v1.1 31 | - name: Checkout vsg 32 | uses: actions/checkout@v3 33 | with: 34 | repository: vsg-dev/VulkanSceneGraph 35 | ref: ${{matrix.vsg-tag}} 36 | path: vsg 37 | submodules: true 38 | - name: Build and Install VSG 39 | shell: bash 40 | run: | 41 | cd vsg 42 | cmake --help 43 | cmake . -DBUILD_SHARED_LIBS=${{matrix.build-shared}} -A x64 -DCMAKE_INSTALL_PREFIX=../../install 44 | MSBuild.exe INSTALL.vcxproj -p:Configuration=Release 45 | - name: Build and Install VSGVR 46 | shell: bash 47 | run: | 48 | cmake . -DBUILD_SHARED_LIBS=${{matrix.build-shared}} -A x64 -DCMAKE_INSTALL_PREFIX=../install 49 | MSBuild.exe INSTALL.vcxproj -p:Configuration=Release 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | build 3 | 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/openxr"] 2 | path = deps/openxr 3 | url = https://github.com/KhronosGroup/OpenXR-SDK 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(vsgvr 4 | VERSION 0.4.0 5 | DESCRIPTION "VulkanSceneGraph based virtual reality viewer" 6 | LANGUAGES CXX 7 | ) 8 | set(VSGVR_SOVERSION 0) 9 | 10 | 11 | option( BUILD_SHARED_LIBS "Build shared libraries" OFF ) 12 | option( VSGVR_BUILD_EXAMPLES "Whether to build VSGVR examples" ON ) 13 | 14 | if( NOT VSGVR_XR_PLATFORM ) 15 | # OPENXR_GENERIC - The standard openxr_loader.so, built from deps/openxr 16 | # OPENXR_SYSTEM - Whatever OpenXR is available via find_package 17 | # OPENXR_OCULUS_MODULE - Oculus specific runtime from their Mobile OpenXR SDK 18 | set( VSGVR_XR_PLATFORM "OPENXR_GENERIC" CACHE STRING "The OpenXR loader / platform combination to build" ) 19 | set_property( CACHE VSGVR_XR_PLATFORM PROPERTY STRINGS "OPENXR_GENERIC" "OPENXR_SYSTEM" "OPENXR_OCULUS_MOBILE" ) 20 | endif() 21 | 22 | # Compiler/Tool requirements 23 | set( CMAKE_CXX_STANDARD 17 ) 24 | set( OpenGL_GL_PREFERENCE GLVND ) 25 | 26 | # Package/System requirements 27 | if(ANDROID) 28 | # On Android, allow vsg to be located outside the Android sysroot 29 | find_package(vsg 1.0.0 NO_CMAKE_FIND_ROOT_PATH) 30 | else() 31 | find_package(vsg 1.0.0) 32 | endif() 33 | 34 | # Other Dependencies 35 | find_package(Vulkan REQUIRED) 36 | 37 | set(OpenXR_LIBRARY openxr_loader) 38 | if( VSGVR_XR_PLATFORM STREQUAL "OPENXR_GENERIC" ) 39 | add_subdirectory( deps/openxr ) 40 | elseif( VSGVR_XR_PLATFORM STREQUAL "OPENXR_SYSTEM" ) 41 | find_package(OpenXR REQUIRED) 42 | set(OpenXR_LIBRARY OpenXR::openxr_loader) 43 | elseif( VSGVR_XR_PLATFORM STREQUAL "OPENXR_OCULUS_MOBILE" ) 44 | if(NOT ANDROID) 45 | message(FATAL_ERROR "Oculus Mobile SDK is only supported when building for Android") 46 | endif() 47 | set( VSGVR_OCULUS_OPENXR_MOBILE_SDK "${CMAKE_CURRENT_SOURCE_DIR}/../ovr_openxr_mobile_sdk") 48 | if(NOT EXISTS ${VSGVR_OCULUS_OPENXR_MOBILE_SDK}) 49 | message(FATAL_ERROR "Failed to find Oculus Mobile SDK, please download from https://developer.oculus.com/downloads/package/oculus-openxr-mobile-sdk/ and set VSGVR_OCULUS_OPENXR_MOBILE_SDK") 50 | endif() 51 | 52 | add_library(openxr_loader SHARED IMPORTED) 53 | set_property(TARGET openxr_loader PROPERTY IMPORTED_LOCATION 54 | "${VSGVR_OCULUS_OPENXR_MOBILE_SDK}/OpenXR/Libs/Android/${ANDROID_ABI}/${CMAKE_BUILD_TYPE}/libopenxr_loader.so") 55 | target_include_directories(openxr_loader INTERFACE 56 | "${VSGVR_OCULUS_OPENXR_MOBILE_SDK}/OpenXR/Include" 57 | "${VSGVR_OCULUS_OPENXR_MOBILE_SDK}/3rdParty/khronos/openxr/OpenXR-SDK/include") 58 | endif() 59 | 60 | 61 | # vsgMacros.cmake - Follow vsg conventions for the most part, 62 | # for all vsgvr libraries and executables 63 | vsg_setup_dir_vars() 64 | vsg_setup_build_vars() 65 | set_property( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Release" "Debug" "MinSizeRel" "RelWithDebInfo" ) 66 | get_property( generator_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG ) 67 | if( generator_is_multi_config ) 68 | set( CMAKE_CONFIGURATION_TYPES "Release;Debug;MinSizeRel;RelWithDebInfo" CACHE STRING "Build configuration types") 69 | endif() 70 | 71 | # TODO: Will re-visit these, and fix when vsgvr is more mature 72 | # (Dev primarily on Windows/Visual Studio, or in Android Studio) 73 | # 74 | # vsg_add_target_clang_format( 75 | # FILES 76 | # ${PROJECT_SOURCE_DIR}/vsgvr/include/vsgvr/*.h 77 | # ${PROJECT_SOURCE_DIR}/vsgvr/srv/vsgvr/*.cpp 78 | # ) 79 | # vsg_add_target_cppcheck( 80 | # FILES 81 | # ${PROJECT_SOURCE_DIR}/vsgvr/include/vsgvr/*.h 82 | # ${PROJECT_SOURCE_DIR}/vsgvr/srv/vsgvr/*.cpp 83 | # ) 84 | # vsg_add_target_docs( 85 | # FILES 86 | # ${PROJECT_SOURCE_DIR}/vsgvr/include 87 | # ) 88 | # vsg_add_target_clobber() 89 | 90 | vsg_add_target_uninstall() 91 | set_target_properties(uninstall-vsgvr PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) 92 | 93 | vsg_add_feature_summary() 94 | vsg_add_cmake_support_files( 95 | CONFIG_TEMPLATE vsgvrConfig.cmake.in 96 | ) 97 | 98 | # VSGVR 99 | add_subdirectory( vsgvr ) 100 | 101 | if( VSGVR_BUILD_EXAMPLES ) 102 | add_subdirectory( examples ) 103 | endif() 104 | 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Gareth Francis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if(ANDROID) 3 | # Android applications are loaded backwards 4 | # The android studio project is opened, which will include 5 | # VSGVR, VSG, and other dependencies from parent directories 6 | # See Android example README.md files for the required directory 7 | # layouts and setup instructions. 8 | else() 9 | add_subdirectory( platform/generic ) 10 | add_subdirectory( features/interaction_locomotion ) 11 | add_subdirectory( features/composition_layers ) 12 | endif() 13 | -------------------------------------------------------------------------------- /examples/features/composition_layers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( SOURCES 3 | main.cpp 4 | game.h 5 | game.cpp 6 | interaction.h 7 | interaction.cpp 8 | 9 | interactions/interaction_teleport.h 10 | interactions/interaction_teleport.cpp 11 | ) 12 | 13 | add_executable( vsgvr_example_composition_layers ${SOURCES} ) 14 | target_include_directories( vsgvr_example_composition_layers PRIVATE . ) 15 | target_link_libraries( vsgvr_example_composition_layers vsg::vsg vsgvr ) 16 | 17 | install(TARGETS vsgvr_example_composition_layers) 18 | 19 | set_target_properties( vsgvr_example_composition_layers PROPERTIES FOLDER "examples" ) 20 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | app/build 4 | app/.cxx 5 | local.properties 6 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/README.md: -------------------------------------------------------------------------------- 1 | # VSGVR Example for Oculus Quest 2 | 3 | This example demonstrates basic VSG and VSGVR usage, in a quest-native executable. 4 | 5 | Due to the use of the Oculus OpenXR loader, this sample is not suitable for other platforms. 6 | 7 | Build Requirements: 8 | * Android Studio 9 | * Android SDK API Level 24 10 | * Android NDK 25 11 | * [Oculus Mobile OpenXR SDK](https://developer.oculus.com/downloads/package/oculus-openxr-mobile-sdk/) 12 | 13 | ## Build Configuration 14 | 15 | The Android Studio project assumes the following folder structure: 16 | * vsg 17 | * ovr\_openxr\_mobile\_sdk 18 | * vsgvr 19 | * examples 20 | * questnative 21 | 22 | If this structure is modified, or your vsg is located in another location, modify app/build.gradle and app/cpp/CMakeLists.txt accordingly, to specify different locations for VSG and the Oculus OpenXR SDK. 23 | 24 | For simplicity this sample includes VSG directly into the CMake project, but with modifications may load from a prebuilt copy as well. 25 | 26 | 27 | ## Building with Android Studio 28 | 29 | 1. Open Android Studio and select 'Open Project' 30 | 2. Select the `questnative` folder 31 | 3. Build the application 32 | 33 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdk 31 5 | 6 | defaultConfig { 7 | applicationId = 'com.vsgvr.vsgvrquestcompositionlayers' 8 | minSdkVersion 24 9 | targetSdkVersion 24 10 | externalNativeBuild { 11 | cmake { 12 | arguments '-DANDROID_STL=c++_static', '-DVSGVR_XR_PLATFORM=OPENXR_OCULUS_MOBILE' 13 | } 14 | } 15 | } 16 | sourceSets { 17 | main { 18 | manifest.srcFile 'AndroidManifest.xml' 19 | java.srcDirs = ['src'] 20 | res.srcDirs = ['res'] 21 | assets.srcDirs = ['assets'] 22 | } 23 | } 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 28 | 'proguard-rules.pro' 29 | ndk { 30 | abiFilters "arm64-v8a", "armeabi-v7a" 31 | } 32 | } 33 | debug { 34 | debuggable true 35 | ndk { 36 | abiFilters "arm64-v8a", "armeabi-v7a" 37 | } 38 | } 39 | } 40 | externalNativeBuild { 41 | cmake { 42 | path 'cpp/CMakeLists.txt' 43 | } 44 | } 45 | ndkVersion '25.1.8937393' 46 | } 47 | 48 | dependencies { 49 | implementation fileTree(dir: 'libs', include: ['*.jar']) 50 | implementation 'com.android.support:appcompat-v7:28.0.0' 51 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 52 | } 53 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13.0) 2 | 3 | project(vsgvrquestnative) 4 | 5 | # build native_app_glue as a static lib 6 | set(${CMAKE_C_FLAGS}, "${CMAKE_C_FLAGS}") 7 | add_library(native_app_glue STATIC 8 | ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) 9 | 10 | # set the use of C++17 11 | set(CMAKE_CXX_STANDARD 17) 12 | set(CMAKE_CXX_VISIBILITY_PRESET default) 13 | 14 | # To prevent errors when loading the native activity, ensure library name is the same in all builds 15 | set(CMAKE_DEBUG_POSTFIX "") 16 | set(CMAKE_RELWITHDEBINFO_POSTFIX "") 17 | 18 | # find vsg 19 | set(VSG_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../") 20 | add_subdirectory("${VSG_ROOT}/VulkanSceneGraph" vsg) 21 | add_subdirectory("${VSG_ROOT}/vsgvr" vsgvr) 22 | 23 | # Export ANativeActivity_onCreate(), 24 | # Refer to: https://github.com/android-ndk/ndk/issues/381. 25 | set(CMAKE_SHARED_LINKER_FLAGS 26 | "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") 27 | 28 | # add vsgnative target 29 | set( SAMP "${CMAKE_CURRENT_SOURCE_DIR}/../../../" ) 30 | add_library(vsgvrquestnative SHARED 31 | ${SAMP}/game.h 32 | ${SAMP}/game.cpp 33 | ${SAMP}/interaction.h 34 | ${SAMP}/interaction.cpp 35 | 36 | ${SAMP}/interactions/interaction_teleport.h 37 | ${SAMP}/interactions/interaction_teleport.cpp 38 | main.cpp 39 | ) 40 | 41 | # add the app glue include directory 42 | target_include_directories(vsgvrquestnative PRIVATE 43 | ${ANDROID_NDK}/sources/android/native_app_glue 44 | ${CMAKE_CURRENT_SOURCE_DIR}/../../vsgvr/include 45 | ${SAMP} 46 | ) 47 | 48 | # add lib dependencies 49 | target_link_libraries(vsgvrquestnative 50 | vsg::vsg vsgvr 51 | android 52 | native_app_glue 53 | log 54 | ) 55 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/composition_layers/android-quest/app/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/composition_layers/android-quest/app/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/composition_layers/android-quest/app/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/composition_layers/android-quest/app/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/app/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | VSGVR Composition Layer Example 4 | 5 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:7.3.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | task clean(type: Delete) { 20 | delete rootProject.buildDir 21 | } 22 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/composition_layers/android-quest/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 17 20:42:48 GMT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /examples/features/composition_layers/android-quest/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | -------------------------------------------------------------------------------- /examples/features/composition_layers/game.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "interaction.h" 14 | 15 | #include 16 | 17 | class Game { 18 | public: 19 | Game(vsg::ref_ptr xrInstance, vsg::ref_ptr vr, vsg::ref_ptr desktopViewer, bool displayDesktopWindow); 20 | ~Game(); 21 | 22 | static std::vector requiredInstanceExtensions(); 23 | 24 | bool shouldExit = false; 25 | 26 | void frame(); 27 | 28 | vsg::ref_ptr userOrigin() const { return _userOrigin; } 29 | 30 | private: 31 | void loadScene(); 32 | void initVR(); 33 | void initActions(); 34 | 35 | void createCompositionLayerEquirect(); 36 | void createCompositionLayerProjection(); 37 | void createCompositionLayerQuadInWorld(); 38 | void createCompositionLayerQuadInView(); 39 | 40 | vsg::ref_ptr _xrInstance; 41 | vsg::ref_ptr _vr; 42 | vsg::ref_ptr _desktopViewer; 43 | bool _desktopWindowEnabled = false; 44 | 45 | // The user / OpenXR root space - Contains elements such as controllers 46 | vsg::ref_ptr _sceneRoot; 47 | vsg::ref_ptr _controllerLeft; 48 | vsg::ref_ptr _controllerRight; 49 | vsg::ref_ptr _teleportMarker; 50 | 51 | // A transform allowing the player to move within the normal vsg scene 52 | vsg::ref_ptr _userOrigin; 53 | vsg::ref_ptr _ground; 54 | 55 | std::vector> _xrCameras; 56 | vsg::ref_ptr _desktopCamera; 57 | 58 | // Actions and behaviours 59 | vsg::ref_ptr _baseActionSet; 60 | vsg::ref_ptr _leftHandPose; 61 | vsg::ref_ptr _rightHandPose; 62 | vsg::ref_ptr _headPose; 63 | 64 | std::map> _interactions; 65 | 66 | vsg::time_point _lastFrameTime; 67 | 68 | vsg::ref_ptr _skyboxLayer; 69 | }; 70 | -------------------------------------------------------------------------------- /examples/features/composition_layers/interaction.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "interaction.h" 3 | 4 | Interaction::Interaction() {} 5 | 6 | Interaction::~Interaction() {} 7 | -------------------------------------------------------------------------------- /examples/features/composition_layers/interaction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class Game; 13 | 14 | class Interaction 15 | { 16 | public: 17 | vsg::ref_ptr actionSet() const { return _actionSet; } 18 | std::map> actionsToSuggest() const { return _actionsToSuggest; } 19 | 20 | virtual void frame(vsg::ref_ptr scene, Game& game, double deltaT) = 0; 21 | virtual ~Interaction(); 22 | protected: 23 | Interaction(); 24 | vsg::ref_ptr _actionSet; 25 | std::map> _actionsToSuggest; 26 | }; 27 | -------------------------------------------------------------------------------- /examples/features/composition_layers/interactions/interaction_teleport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "interaction.h" 4 | 5 | /// Basic user-teleport navigation, on left controller 6 | /// * A button, Trackpad click, or trigger pull on controller -> Teleport to aimed target 7 | /// * Thumstick on controller -> rotate in place 8 | class Interaction_teleport : public Interaction 9 | { 10 | public: 11 | Interaction_teleport() = delete; 12 | Interaction_teleport(vsg::ref_ptr xrInstance, 13 | vsg::ref_ptr headPose, 14 | vsg::ref_ptr leftHandPose, 15 | vsg::ref_ptr teleportTarget, 16 | vsg::ref_ptr ground); 17 | 18 | void frame(vsg::ref_ptr scene, Game& game, double deltaT) final override; 19 | virtual ~Interaction_teleport(); 20 | protected: 21 | 22 | vsg::ref_ptr _teleportAction; 23 | vsg::ref_ptr _rotateAction; 24 | 25 | vsg::dvec3 _teleportPosition = {0.0, 0.0, 0.0}; 26 | vsg::ref_ptr _teleportTarget; 27 | vsg::ref_ptr _headPose; 28 | vsg::ref_ptr _leftHandPose; 29 | 30 | bool _teleportButtonDown = false; 31 | bool _teleportTargetValid = false; 32 | int _rotateActionState = 0; // -1 is rot left, 1 is rot right 33 | 34 | double _playerRotation = 0.0; 35 | 36 | vsg::ref_ptr _ground; 37 | }; 38 | -------------------------------------------------------------------------------- /examples/features/composition_layers/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "game.h" 6 | 7 | #include "../common/example_functions.cpp" 8 | #include "../common/example_main_desktop.cpp" 9 | 10 | int main(int argc, char** argv) { 11 | exampleMain(argc, argv); 12 | } 13 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( SOURCES 3 | main.cpp 4 | game.h 5 | game.cpp 6 | interaction.h 7 | interaction.cpp 8 | 9 | interactions/interaction_teleport.h 10 | interactions/interaction_teleport.cpp 11 | interactions/interaction_slide.h 12 | interactions/interaction_slide.cpp 13 | ) 14 | 15 | add_executable( vsgvr_example_locomotion ${SOURCES} ) 16 | target_include_directories( vsgvr_example_locomotion PRIVATE . ) 17 | target_link_libraries( vsgvr_example_locomotion vsg::vsg vsgvr ) 18 | 19 | install(TARGETS vsgvr_example_locomotion) 20 | 21 | set_target_properties( vsgvr_example_locomotion PROPERTIES FOLDER "examples" ) 22 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | app/build 4 | app/.cxx 5 | local.properties 6 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/README.md: -------------------------------------------------------------------------------- 1 | # VSGVR Example for Oculus Quest 2 | 3 | This example demonstrates basic VSG and VSGVR usage, in a quest-native executable. 4 | 5 | Due to the use of the Oculus OpenXR loader, this sample is not suitable for other platforms. 6 | 7 | Build Requirements: 8 | * Android Studio 9 | * Android SDK API Level 24 10 | * Android NDK 25 11 | * [Oculus Mobile OpenXR SDK](https://developer.oculus.com/downloads/package/oculus-openxr-mobile-sdk/) 12 | 13 | ## Build Configuration 14 | 15 | The Android Studio project assumes the following folder structure: 16 | * vsg 17 | * ovr\_openxr\_mobile\_sdk 18 | * vsgvr 19 | * examples 20 | * questnative 21 | 22 | If this structure is modified, or your vsg is located in another location, modify app/build.gradle and app/cpp/CMakeLists.txt accordingly, to specify different locations for VSG and the Oculus OpenXR SDK. 23 | 24 | For simplicity this sample includes VSG directly into the CMake project, but with modifications may load from a prebuilt copy as well. 25 | 26 | 27 | ## Building with Android Studio 28 | 29 | 1. Open Android Studio and select 'Open Project' 30 | 2. Select the `questnative` folder 31 | 3. Build the application 32 | 33 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdk 31 5 | 6 | defaultConfig { 7 | applicationId = 'com.vsgvr.vsgvrlocomotion' 8 | minSdkVersion 24 9 | targetSdkVersion 24 10 | externalNativeBuild { 11 | cmake { 12 | arguments '-DANDROID_STL=c++_static', '-DVSGVR_XR_PLATFORM=OPENXR_OCULUS_MOBILE' 13 | } 14 | } 15 | } 16 | sourceSets { 17 | main { 18 | manifest.srcFile 'AndroidManifest.xml' 19 | java.srcDirs = ['src'] 20 | res.srcDirs = ['res'] 21 | assets.srcDirs = ['assets'] 22 | } 23 | } 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 28 | 'proguard-rules.pro' 29 | ndk { 30 | abiFilters "arm64-v8a", "armeabi-v7a" 31 | } 32 | } 33 | debug { 34 | debuggable true 35 | ndk { 36 | abiFilters "arm64-v8a", "armeabi-v7a" 37 | } 38 | } 39 | } 40 | externalNativeBuild { 41 | cmake { 42 | path 'cpp/CMakeLists.txt' 43 | } 44 | } 45 | ndkVersion '25.1.8937393' 46 | } 47 | 48 | dependencies { 49 | implementation fileTree(dir: 'libs', include: ['*.jar']) 50 | implementation 'com.android.support:appcompat-v7:28.0.0' 51 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 52 | } 53 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13.0) 2 | 3 | project(vsgvrquestnative) 4 | 5 | # build native_app_glue as a static lib 6 | set(${CMAKE_C_FLAGS}, "${CMAKE_C_FLAGS}") 7 | add_library(native_app_glue STATIC 8 | ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) 9 | 10 | # set the use of C++17 11 | set(CMAKE_CXX_STANDARD 17) 12 | set(CMAKE_CXX_VISIBILITY_PRESET default) 13 | 14 | # To prevent errors when loading the native activity, ensure library name is the same in all builds 15 | set(CMAKE_DEBUG_POSTFIX "") 16 | set(CMAKE_RELWITHDEBINFO_POSTFIX "") 17 | 18 | # find vsg 19 | set(VSG_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../") 20 | add_subdirectory("${VSG_ROOT}/VulkanSceneGraph" vsg) 21 | add_subdirectory("${VSG_ROOT}/vsgvr" vsgvr) 22 | 23 | # Export ANativeActivity_onCreate(), 24 | # Refer to: https://github.com/android-ndk/ndk/issues/381. 25 | set(CMAKE_SHARED_LINKER_FLAGS 26 | "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") 27 | 28 | # add vsgnative target 29 | set( SAMP "${CMAKE_CURRENT_SOURCE_DIR}/../../../" ) 30 | add_library(vsgvrquestnative SHARED 31 | ${SAMP}/game.h 32 | ${SAMP}/game.cpp 33 | ${SAMP}/interaction.h 34 | ${SAMP}/interaction.cpp 35 | 36 | ${SAMP}/interactions/interaction_teleport.h 37 | ${SAMP}/interactions/interaction_teleport.cpp 38 | ${SAMP}/interactions/interaction_slide.h 39 | ${SAMP}/interactions/interaction_slide.cpp 40 | main.cpp 41 | ) 42 | 43 | # add the app glue include directory 44 | target_include_directories(vsgvrquestnative PRIVATE 45 | ${ANDROID_NDK}/sources/android/native_app_glue 46 | ${CMAKE_CURRENT_SOURCE_DIR}/../../vsgvr/include 47 | ${SAMP} 48 | ) 49 | 50 | # add lib dependencies 51 | target_link_libraries(vsgvrquestnative 52 | vsg::vsg vsgvr 53 | android 54 | native_app_glue 55 | log 56 | ) 57 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/interaction_locomotion/android-quest/app/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/interaction_locomotion/android-quest/app/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/interaction_locomotion/android-quest/app/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/interaction_locomotion/android-quest/app/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/app/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | VSGVR Locomotion Example 4 | 5 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:7.3.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | task clean(type: Delete) { 20 | delete rootProject.buildDir 21 | } 22 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/features/interaction_locomotion/android-quest/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 17 20:42:48 GMT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/android-quest/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/game.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "interaction.h" 12 | 13 | #include 14 | 15 | class Game { 16 | public: 17 | Game( 18 | vsg::ref_ptr xrInstance, 19 | vsg::ref_ptr vr, 20 | vsg::ref_ptr desktopViewer, bool displayDesktopWindow); 21 | ~Game(); 22 | 23 | static std::vector requiredInstanceExtensions(); 24 | 25 | bool shouldExit = false; 26 | 27 | void frame(); 28 | 29 | vsg::ref_ptr userOrigin() const { return _userOrigin; } 30 | 31 | private: 32 | void loadScene(); 33 | void initVR(); 34 | void initActions(); 35 | 36 | vsg::ref_ptr _xrInstance; 37 | vsg::ref_ptr _vr; 38 | vsg::ref_ptr _desktopViewer; 39 | bool _desktopWindowEnabled = false; 40 | 41 | // The user / OpenXR root space - Contains elements such as controllers 42 | vsg::ref_ptr _sceneRoot; 43 | vsg::ref_ptr _controllerLeft; 44 | vsg::ref_ptr _controllerRight; 45 | vsg::ref_ptr _teleportMarker; 46 | 47 | // A transform allowing the player to move within the normal vsg scene 48 | vsg::ref_ptr _userOrigin; 49 | vsg::ref_ptr _ground; 50 | 51 | std::vector> _xrCameras; 52 | vsg::ref_ptr _desktopCamera; 53 | 54 | // Actions and behaviours 55 | vsg::ref_ptr _baseActionSet; 56 | vsg::ref_ptr _leftHandPose; 57 | vsg::ref_ptr _rightHandPose; 58 | vsg::ref_ptr _headPose; 59 | vsg::ref_ptr _switchInteractionAction; 60 | 61 | enum InteractionMethod { 62 | InteractionMethod_Min, 63 | Teleport, 64 | Slide, 65 | InteractionMethod_Max 66 | }; 67 | std::map> _interactions; 68 | InteractionMethod _currentInteractionMethod = InteractionMethod::Teleport; 69 | void updateActiveInteraction(InteractionMethod method); 70 | 71 | vsg::time_point _lastFrameTime; 72 | }; 73 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/interaction.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "interaction.h" 3 | 4 | Interaction::Interaction() {} 5 | 6 | Interaction::~Interaction() {} 7 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/interaction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | class Game; 13 | 14 | class Interaction 15 | { 16 | public: 17 | vsg::ref_ptr actionSet() const { return _actionSet; } 18 | std::map> actionsToSuggest() const { return _actionsToSuggest; } 19 | 20 | virtual void frame(vsg::ref_ptr scene, Game& game, double deltaT) = 0; 21 | virtual ~Interaction(); 22 | protected: 23 | Interaction(); 24 | vsg::ref_ptr _actionSet; 25 | std::map> _actionsToSuggest; 26 | }; 27 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/interactions/interaction_slide.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "interaction_slide.h" 3 | #include "game.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | Interaction_slide::Interaction_slide( 10 | vsg::ref_ptr xrInstance, 11 | vsg::ref_ptr headPose, 12 | vsg::ref_ptr leftHandPose, 13 | vsg::ref_ptr ground) 14 | : _headPose(headPose) 15 | , _leftHandPose(leftHandPose) 16 | , _ground(ground) 17 | { 18 | _actionSet = vsgvr::ActionSet::create(xrInstance, "slide", "Slide"); 19 | 20 | // Pose bindings - One for each hand 21 | _strafeXAction = vsgvr::Action::create(xrInstance, _actionSet, XrActionType::XR_ACTION_TYPE_FLOAT_INPUT, "strafe_x", "Strafe X"); 22 | _strafeYAction = vsgvr::Action::create(xrInstance, _actionSet, XrActionType::XR_ACTION_TYPE_FLOAT_INPUT, "strafe_y", "Strafe Y"); 23 | _rotateAction = vsgvr::Action::create(xrInstance, _actionSet, XrActionType::XR_ACTION_TYPE_FLOAT_INPUT, "rotate", "Rotate"); 24 | 25 | _actionSet->actions = { 26 | _strafeXAction, 27 | _strafeYAction, 28 | _rotateAction, 29 | }; 30 | 31 | // Doesn't have a thumstick, nothing we can do (except map to controller aim + trigger) 32 | // _actionsToSuggest["/interaction_profiles/khr/simple_controller"] = {}; 33 | 34 | _actionsToSuggest["/interaction_profiles/htc/vive_controller"] = { 35 | {_strafeXAction, "/user/hand/left/input/trackpad/x"}, 36 | {_strafeYAction, "/user/hand/left/input/trackpad/y"}, 37 | {_rotateAction, "/user/hand/right/input/trackpad/x"} 38 | }; 39 | _actionsToSuggest["/interaction_profiles/oculus/touch_controller"] = { 40 | {_strafeXAction, "/user/hand/left/input/thumbstick/x"}, 41 | {_strafeYAction, "/user/hand/left/input/thumbstick/y"}, 42 | {_rotateAction, "/user/hand/right/input/thumbstick/x"} 43 | }; 44 | } 45 | 46 | Interaction_slide::~Interaction_slide() {} 47 | 48 | void Interaction_slide::frame(vsg::ref_ptr scene, Game& game, double deltaT) 49 | { 50 | bool updateOrigin = false; 51 | 52 | // The player's position in vr space, at 'ground' level 53 | // In most cases this will simply be playerPosOrigin.z = 0, 54 | // though an intersection to the scene would be more appropriate in many cases 55 | auto playerPosUser = _headPose->getTransform() * vsg::dvec3{ 0.0, 0.0, 0.0 }; 56 | playerPosUser.z = 0.0; 57 | 58 | // Player's position in the scene - Strafing is performed in scene space 59 | auto newPositionScene = game.userOrigin()->userToScene() * playerPosUser; 60 | 61 | if (_rotateAction->getStateValid()) 62 | { 63 | auto state = _rotateAction->getStateFloat(); 64 | if (state.isActive && fabs(state.currentState) > deadZone) 65 | { 66 | _rotation += state.currentState * rotateSensitivity * deltaT * -1.0; 67 | updateOrigin = true; 68 | } 69 | } 70 | 71 | if (_leftHandPose->getTransformValid() && _strafeXAction->getStateValid() && _strafeYAction->getStateValid()) 72 | { 73 | // Direction vectors in scene space, based on left controller 74 | // (User may point controller to modify strafe direction) 75 | // Alternatively the head's pose could be used to determine forward, 76 | // but that would prevent strafing sideways while looking sideways 77 | // 78 | // Here all strafing is performed in the xy plane, ignoring height differences 79 | // of the ground. 80 | auto lt = game.userOrigin()->userToScene() * _leftHandPose->getTransform(); 81 | auto lForward = (lt * vsg::dvec3{0.0, 0.0, -1.0}) - (lt * vsg::dvec3{0.0, 0.0, 0.0}); 82 | lForward.z = 0; 83 | lForward = vsg::normalize(lForward); 84 | auto lRight = (lt * vsg::dvec3{ 1.0, 0.0, 0.0 }) - (lt * vsg::dvec3{ 0.0, 0.0, 0.0 }); 85 | lRight.z = 0; 86 | lRight = vsg::normalize(lRight); 87 | 88 | auto xState = _strafeXAction->getStateFloat(); 89 | auto yState = _strafeYAction->getStateFloat(); 90 | if (xState.isActive && yState.isActive) 91 | { 92 | vsg::dvec3 d = (lRight * static_cast(xState.currentState) ) + (lForward * static_cast(yState.currentState) ); 93 | if (vsg::length(d) > deadZone) 94 | { 95 | d *= strafeSensitivity * deltaT; 96 | newPositionScene += d; 97 | updateOrigin = true; 98 | } 99 | } 100 | } 101 | 102 | if( updateOrigin ) 103 | { 104 | // Update the vsg scene's transform to strafe player as needed 105 | game.userOrigin()->setUserInScene( 106 | playerPosUser, 107 | newPositionScene, 108 | vsg::dquat(_rotation, { 0.0, 0.0, 1.0 }), 109 | { 1.0, 1.0, 1.0 } 110 | ); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/interactions/interaction_slide.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "interaction.h" 4 | 5 | /// Basic user-slide navigation 6 | /// * Thumstick on left controller -> strafe, relative to controller aim 7 | /// * Thumbstick on right controller -> rotate 8 | class Interaction_slide : public Interaction 9 | { 10 | public: 11 | Interaction_slide() = delete; 12 | Interaction_slide(vsg::ref_ptr xrInstance, 13 | vsg::ref_ptr headPose, 14 | vsg::ref_ptr leftHandPose, 15 | vsg::ref_ptr ground); 16 | 17 | void frame(vsg::ref_ptr scene, Game& game, double deltaT) final override; 18 | virtual ~Interaction_slide(); 19 | 20 | double strafeSensitivity = 1.8; // m/s 21 | double rotateSensitivity = 1.4; // rad/s 22 | double deadZone = 0.1; 23 | protected: 24 | 25 | vsg::ref_ptr _strafeXAction; 26 | vsg::ref_ptr _strafeYAction; 27 | vsg::ref_ptr _rotateAction; 28 | vsg::ref_ptr _headPose; 29 | vsg::ref_ptr _leftHandPose; 30 | 31 | vsg::ref_ptr _ground; 32 | double _rotation = 0.0; 33 | }; 34 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/interactions/interaction_teleport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "interaction.h" 4 | 5 | /// Basic user-teleport navigation, on left controller 6 | /// * A button, Trackpad click, or trigger pull on controller -> Teleport to aimed target 7 | /// * Thumstick on controller -> rotate in place 8 | class Interaction_teleport : public Interaction 9 | { 10 | public: 11 | Interaction_teleport() = delete; 12 | Interaction_teleport(vsg::ref_ptr xrInstance, 13 | vsg::ref_ptr headPose, 14 | vsg::ref_ptr leftHandPose, 15 | vsg::ref_ptr teleportTarget, 16 | vsg::ref_ptr ground); 17 | 18 | void frame(vsg::ref_ptr scene, Game& game, double deltaT) final override; 19 | 20 | virtual ~Interaction_teleport(); 21 | protected: 22 | 23 | vsg::ref_ptr _teleportAction; 24 | vsg::ref_ptr _rotateAction; 25 | 26 | vsg::dvec3 _teleportPosition = {0.0, 0.0, 0.0}; 27 | vsg::ref_ptr _teleportTarget; 28 | vsg::ref_ptr _headPose; 29 | vsg::ref_ptr _leftHandPose; 30 | 31 | bool _teleportButtonDown = false; 32 | bool _teleportTargetValid = false; 33 | int _rotateActionState = 0; // -1 is rot left, 1 is rot right 34 | 35 | double _playerRotation = 0.0; 36 | 37 | vsg::ref_ptr _ground; 38 | }; 39 | -------------------------------------------------------------------------------- /examples/features/interaction_locomotion/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "game.h" 6 | 7 | #include "../common/example_functions.cpp" 8 | #include "../common/example_main_desktop.cpp" 9 | 10 | int main(int argc, char** argv) { 11 | exampleMain(argc, argv); 12 | } 13 | -------------------------------------------------------------------------------- /examples/platform/android-monado/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | app/build 4 | app/.cxx 5 | local.properties 6 | -------------------------------------------------------------------------------- /examples/platform/android-monado/README.md: -------------------------------------------------------------------------------- 1 | # VSGVR Example for Android - Monado runtime 2 | 3 | This example demonstrates basic VSG and VSGVR usage on any Android device, running the Monado OpenXR runtime. 4 | 5 | Build Requirements: 6 | * Android Studio 7 | * Android SDK API Level 27 8 | * Android NDK 25 9 | * Android device with Monado OpenXR runtime installed 10 | 11 | Quirks / Issues: 12 | * If ANDROID_STL=C++_static the OpenXR runtime will not load correctly. The runtime could be rebuilt with a static STL, but the simpler option is to use c++_shared in the vsgvr application 13 | * Monado on Android seems to be targeted at cardboard-like HMDs - Configuring as XR_FORM_FACTOR_HANDHELD_DISPLAY is not currently possible 14 | * When starting the application, ensure phone is held horizontally - Tracking is relative to the starting position 15 | * Performance may be quite low 16 | 17 | ## Installing Monado 18 | 19 | Firstly, build and install the monado runtime from https://gitlab.freedesktop.org/monado/monado 20 | * Clone the repo 21 | * Open the repo in Android Studio 22 | * Build and install the runtime APK 23 | 24 | Also build and install the monado broker application from https://gitlab.freedesktop.org/monado/utilities/openxr-android-broker 25 | * Clone the repo 26 | * Open the repo in Android Studio 27 | * Build and install the APK for `installable_runtime_broker` 28 | 29 | On the phone, configure the runtime 30 | * Open the app `OpenXR Runtime Broker` 31 | * Ensure the Monado runtime is selected 32 | 33 | ## Build Configuration 34 | 35 | The Android Studio project assumes the following folder structure: 36 | * VulkanSceneGraph 37 | * vsgvr 38 | * examples 39 | * android-monado 40 | 41 | Project / Gradle requirements 42 | * VSGVR_XR_PLATFORM=OPENXR_GENERIC 43 | * ANDROID_STL=c++_shared 44 | * `implementation 'org.khronos.openxr:openxr_loader_for_android:1.0.23'` 45 | 46 | If this structure is modified, or your vsg is located in another location, modify app/build.gradle and app/cpp/CMakeLists.txt accordingly, to specify different locations for VSG and the Oculus OpenXR SDK. 47 | 48 | For simplicity this sample includes VSG directly into the CMake project, but with modifications may load from a prebuilt copy as well. 49 | 50 | ## Building 51 | 52 | * Open project in Android Studio 53 | * Build / Run 54 | -------------------------------------------------------------------------------- /examples/platform/android-monado/app/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 22 | 23 | 25 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/platform/android-monado/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdk 31 5 | 6 | defaultConfig { 7 | applicationId = 'com.vsgvr.vsgvrandroidmonado' 8 | minSdkVersion 27 9 | targetSdkVersion 31 10 | externalNativeBuild { 11 | cmake { 12 | arguments '-DANDROID_STL=c++_shared', '-DVSGVR_XR_PLATFORM=OPENXR_GENERIC' 13 | } 14 | } 15 | } 16 | sourceSets { 17 | main { 18 | manifest.srcFile 'AndroidManifest.xml' 19 | java.srcDirs = ['src'] 20 | res.srcDirs = ['res'] 21 | assets.srcDirs = ['assets'] 22 | } 23 | } 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 28 | 'proguard-rules.pro' 29 | ndk { 30 | abiFilters "arm64-v8a" 31 | } 32 | } 33 | debug { 34 | debuggable true 35 | ndk { 36 | abiFilters "arm64-v8a" 37 | } 38 | } 39 | } 40 | externalNativeBuild { 41 | cmake { 42 | path 'cpp/CMakeLists.txt' 43 | } 44 | } 45 | ndkVersion '25.1.8937393' 46 | } 47 | 48 | dependencies { 49 | implementation fileTree(dir: 'libs', include: ['*.jar']) 50 | implementation 'androidx.appcompat:appcompat:1.0.0' 51 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 52 | implementation 'org.khronos.openxr:openxr_loader_for_android:1.0.23' 53 | } 54 | -------------------------------------------------------------------------------- /examples/platform/android-monado/app/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13.0) 2 | 3 | project(vsgvrnative) 4 | 5 | # build native_app_glue as a static lib 6 | set(${CMAKE_C_FLAGS}, "${CMAKE_C_FLAGS}") 7 | add_library(native_app_glue STATIC 8 | ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) 9 | 10 | # set the use of C++17 11 | set(CMAKE_CXX_STANDARD 17) 12 | set(CMAKE_CXX_VISIBILITY_PRESET default) 13 | 14 | # To prevent errors when loading the native activity, ensure library name is the same in all builds 15 | set(CMAKE_DEBUG_POSTFIX "") 16 | set(CMAKE_RELWITHDEBINFO_POSTFIX "") 17 | 18 | # find vsg 19 | set(VSG_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../") 20 | add_subdirectory("${VSG_ROOT}/VulkanSceneGraph" vsg) 21 | add_subdirectory("${VSG_ROOT}/vsgvr" vsgvr) 22 | 23 | # Export ANativeActivity_onCreate(), 24 | # Refer to: https://github.com/android-ndk/ndk/issues/381. 25 | set(CMAKE_SHARED_LINKER_FLAGS 26 | "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") 27 | 28 | # add vsgnative target 29 | add_library(vsgvrnative SHARED main.cpp) 30 | 31 | # add the app glue include directory 32 | target_include_directories(vsgvrnative PRIVATE 33 | ${ANDROID_NDK}/sources/android/native_app_glue 34 | ${CMAKE_CURRENT_SOURCE_DIR}/../../vsgvr/include 35 | ${VSG_ROOT}/vsgvr/models 36 | ) 37 | 38 | # add lib dependencies 39 | target_link_libraries(vsgvrnative 40 | vsg::vsg vsgvr 41 | android 42 | native_app_glue 43 | log 44 | ) 45 | -------------------------------------------------------------------------------- /examples/platform/android-monado/app/debug/app-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-monado/app/debug/app-debug.apk -------------------------------------------------------------------------------- /examples/platform/android-monado/app/debug/output-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "artifactType": { 4 | "type": "APK", 5 | "kind": "Directory" 6 | }, 7 | "applicationId": "com.vsgvr.vsgvrandroidmonado", 8 | "variantName": "debug", 9 | "elements": [ 10 | { 11 | "type": "SINGLE", 12 | "filters": [], 13 | "attributes": [], 14 | "versionCode": 1, 15 | "versionName": "1.0", 16 | "outputFile": "app-debug.apk" 17 | } 18 | ], 19 | "elementType": "File" 20 | } -------------------------------------------------------------------------------- /examples/platform/android-monado/app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-monado/app/release/app-release.apk -------------------------------------------------------------------------------- /examples/platform/android-monado/app/release/output-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "artifactType": { 4 | "type": "APK", 5 | "kind": "Directory" 6 | }, 7 | "applicationId": "com.vsgvr.vsgvrandroidmonado", 8 | "variantName": "release", 9 | "elements": [ 10 | { 11 | "type": "SINGLE", 12 | "filters": [], 13 | "attributes": [], 14 | "versionCode": 1, 15 | "versionName": "1.0", 16 | "outputFile": "app-release.apk" 17 | } 18 | ], 19 | "elementType": "File" 20 | } -------------------------------------------------------------------------------- /examples/platform/android-monado/app/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-monado/app/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-monado/app/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-monado/app/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-monado/app/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-monado/app/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-monado/app/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-monado/app/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-monado/app/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | VSGVR Android Monado Example 4 | 5 | -------------------------------------------------------------------------------- /examples/platform/android-monado/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:7.3.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | task clean(type: Delete) { 20 | delete rootProject.buildDir 21 | } 22 | -------------------------------------------------------------------------------- /examples/platform/android-monado/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | android.enableJetifier=true 13 | android.useAndroidX=true 14 | org.gradle.jvmargs=-Xmx1536m 15 | 16 | # When configured, Gradle will run in incubating parallel mode. 17 | # This option should only be used with decoupled projects. More details, visit 18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 19 | # org.gradle.parallel=true 20 | 21 | -------------------------------------------------------------------------------- /examples/platform/android-monado/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-monado/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/platform/android-monado/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 17 20:42:48 GMT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /examples/platform/android-monado/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /examples/platform/android-monado/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /examples/platform/android-monado/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | -------------------------------------------------------------------------------- /examples/platform/android-quest/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | app/build 4 | app/.cxx 5 | local.properties 6 | -------------------------------------------------------------------------------- /examples/platform/android-quest/README.md: -------------------------------------------------------------------------------- 1 | # VSGVR Example for Oculus Quest 2 | 3 | This example demonstrates basic VSG and VSGVR usage, in a quest-native executable. 4 | 5 | Due to the use of the Oculus OpenXR loader, this sample is not suitable for other platforms. 6 | 7 | Build Requirements: 8 | * Android Studio 9 | * Android SDK API Level 24 10 | * Android NDK 25 11 | * [Oculus Mobile OpenXR SDK](https://developer.oculus.com/downloads/package/oculus-openxr-mobile-sdk/) 12 | 13 | ## Build Configuration 14 | 15 | The Android Studio project assumes the following folder structure: 16 | * vsg 17 | * ovr\_openxr\_mobile\_sdk 18 | * vsgvr 19 | * examples 20 | * questnative 21 | 22 | If this structure is modified, or your vsg is located in another location, modify app/build.gradle and app/cpp/CMakeLists.txt accordingly, to specify different locations for VSG and the Oculus OpenXR SDK. 23 | 24 | For simplicity this sample includes VSG directly into the CMake project, but with modifications may load from a prebuilt copy as well. 25 | 26 | 27 | ## Building with Android Studio 28 | 29 | 1. Open Android Studio and select 'Open Project' 30 | 2. Select the `questnative` folder 31 | 3. Build the application 32 | 33 | -------------------------------------------------------------------------------- /examples/platform/android-quest/app/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/platform/android-quest/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdk 31 5 | 6 | defaultConfig { 7 | applicationId = 'com.vsgvr.vsgvrquestnative' 8 | minSdkVersion 24 9 | targetSdkVersion 24 10 | externalNativeBuild { 11 | cmake { 12 | arguments '-DANDROID_STL=c++_static', '-DVSGVR_XR_PLATFORM=OPENXR_OCULUS_MOBILE' 13 | } 14 | } 15 | } 16 | sourceSets { 17 | main { 18 | manifest.srcFile 'AndroidManifest.xml' 19 | java.srcDirs = ['src'] 20 | res.srcDirs = ['res'] 21 | assets.srcDirs = ['assets'] 22 | } 23 | } 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 28 | 'proguard-rules.pro' 29 | ndk { 30 | abiFilters "arm64-v8a", "armeabi-v7a" 31 | } 32 | } 33 | debug { 34 | debuggable true 35 | ndk { 36 | abiFilters "arm64-v8a", "armeabi-v7a" 37 | } 38 | } 39 | } 40 | externalNativeBuild { 41 | cmake { 42 | path 'cpp/CMakeLists.txt' 43 | } 44 | } 45 | ndkVersion '25.1.8937393' 46 | } 47 | 48 | dependencies { 49 | implementation fileTree(dir: 'libs', include: ['*.jar']) 50 | implementation 'com.android.support:appcompat-v7:28.0.0' 51 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 52 | } 53 | -------------------------------------------------------------------------------- /examples/platform/android-quest/app/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13.0) 2 | 3 | project(vsgvrquestnative) 4 | 5 | # build native_app_glue as a static lib 6 | set(${CMAKE_C_FLAGS}, "${CMAKE_C_FLAGS}") 7 | add_library(native_app_glue STATIC 8 | ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) 9 | 10 | # set the use of C++17 11 | set(CMAKE_CXX_STANDARD 17) 12 | set(CMAKE_CXX_VISIBILITY_PRESET default) 13 | 14 | # To prevent errors when loading the native activity, ensure library name is the same in all builds 15 | set(CMAKE_DEBUG_POSTFIX "") 16 | set(CMAKE_RELWITHDEBINFO_POSTFIX "") 17 | 18 | # find vsg 19 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../../VulkanSceneGraph" vsg) 20 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../" vsgvr) 21 | 22 | # Export ANativeActivity_onCreate(), 23 | # Refer to: https://github.com/android-ndk/ndk/issues/381. 24 | set(CMAKE_SHARED_LINKER_FLAGS 25 | "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") 26 | 27 | # add vsgnative target 28 | add_library(vsgvrquestnative SHARED main.cpp) 29 | 30 | # add the app glue include directory 31 | target_include_directories(vsgvrquestnative PRIVATE 32 | ${ANDROID_NDK}/sources/android/native_app_glue 33 | ${CMAKE_CURRENT_SOURCE_DIR}/../../vsgvr/include 34 | ) 35 | 36 | # add lib dependencies 37 | target_link_libraries(vsgvrquestnative 38 | vsg::vsg vsgvr 39 | android 40 | native_app_glue 41 | log 42 | ) 43 | -------------------------------------------------------------------------------- /examples/platform/android-quest/app/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-quest/app/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-quest/app/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-quest/app/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-quest/app/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-quest/app/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-quest/app/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-quest/app/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/platform/android-quest/app/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | VSGVR Quest Native Example 4 | 5 | -------------------------------------------------------------------------------- /examples/platform/android-quest/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:7.3.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | task clean(type: Delete) { 20 | delete rootProject.buildDir 21 | } 22 | -------------------------------------------------------------------------------- /examples/platform/android-quest/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | -------------------------------------------------------------------------------- /examples/platform/android-quest/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/examples/platform/android-quest/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/platform/android-quest/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 17 20:42:48 GMT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /examples/platform/android-quest/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /examples/platform/android-quest/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /examples/platform/android-quest/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | -------------------------------------------------------------------------------- /examples/platform/generic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable( vsgvr_example_generic main.cpp ) 3 | 4 | target_link_libraries( vsgvr_example_generic vsg::vsg vsgvr ) 5 | 6 | install(TARGETS vsgvr_example_generic) 7 | 8 | set_target_properties( vsgvr_example_generic PROPERTIES FOLDER "examples" ) 9 | -------------------------------------------------------------------------------- /models/assets/teleport_marker/teleport_marker.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/assets/teleport_marker/teleport_marker.blend -------------------------------------------------------------------------------- /models/assets/teleport_marker/teleport_marker.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/assets/teleport_marker/teleport_marker.glb -------------------------------------------------------------------------------- /models/controller/controller.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/controller/controller.blend -------------------------------------------------------------------------------- /models/controller/controller.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/controller/controller.glb -------------------------------------------------------------------------------- /models/controller/controller2.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/controller/controller2.blend -------------------------------------------------------------------------------- /models/controller/controller2.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/controller/controller2.glb -------------------------------------------------------------------------------- /models/world/world.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/world/world.blend -------------------------------------------------------------------------------- /models/world/world.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geefr/vsgvr/8a4f9871b3de91504c979ba82b61d0e144c5a6dd/models/world/world.glb -------------------------------------------------------------------------------- /vsgvr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( HEADERS_ACTIONS 3 | include/vsgvr/actions/Action.h 4 | include/vsgvr/actions/ActionPoseBinding.h 5 | include/vsgvr/actions/SpaceBinding.h 6 | include/vsgvr/actions/ActionSet.h 7 | ) 8 | 9 | set( HEADERS_APP 10 | include/vsgvr/app/Viewer.h 11 | include/vsgvr/app/UserOrigin.h 12 | include/vsgvr/app/CompositionLayer.h 13 | include/vsgvr/app/CompositionLayerProjection.h 14 | include/vsgvr/app/CompositionLayerQuad.h 15 | ) 16 | 17 | set( HEADERS_XR 18 | include/vsgvr/xr/Common.h 19 | include/vsgvr/xr/EventHandler.h 20 | include/vsgvr/xr/GraphicsBindingVulkan.h 21 | include/vsgvr/xr/Instance.h 22 | include/vsgvr/xr/ProjectionMatrix.h 23 | include/vsgvr/xr/ReferenceSpace.h 24 | include/vsgvr/xr/Session.h 25 | include/vsgvr/xr/Swapchain.h 26 | include/vsgvr/xr/Traits.h 27 | include/vsgvr/xr/ViewMatrix.h 28 | include/vsgvr/xr/Pose.h 29 | ) 30 | 31 | set( HEADERS_EXT 32 | include/vsgvr/extensions/KHRCompositionLayerEquirect.h 33 | include/vsgvr/extensions/KHRCompositionLayerEquirect2.h 34 | ) 35 | 36 | set( SOURCES 37 | src/vsgvr/actions/Action.cpp 38 | src/vsgvr/actions/ActionPoseBinding.cpp 39 | src/vsgvr/actions/SpaceBinding.cpp 40 | src/vsgvr/actions/ActionSet.cpp 41 | 42 | src/vsgvr/app/Viewer.cpp 43 | src/vsgvr/app/UserOrigin.cpp 44 | src/vsgvr/app/CompositionLayer.cpp 45 | src/vsgvr/app/CompositionLayerProjection.cpp 46 | src/vsgvr/app/CompositionLayerQuad.cpp 47 | 48 | src/vsgvr/xr/EventHandler.cpp 49 | src/vsgvr/xr/GraphicsBindingVulkan.cpp 50 | src/vsgvr/xr/Instance.cpp 51 | src/vsgvr/xr/ReferenceSpace.cpp 52 | src/vsgvr/xr/Session.cpp 53 | src/vsgvr/xr/Swapchain.cpp 54 | src/vsgvr/xr/Traits.cpp 55 | src/vsgvr/xr/Pose.cpp 56 | 57 | src/vsgvr/extensions/KHRCompositionLayerEquirect.cpp 58 | src/vsgvr/extensions/KHRCompositionLayerEquirect2.cpp 59 | ) 60 | 61 | if( ANDROID ) 62 | list(APPEND HEADERS_XR 63 | include/vsgvr/xr/AndroidTraits.h 64 | ) 65 | list(APPEND SOURCES 66 | src/vsgvr/xr/AndroidTraits.cpp 67 | ) 68 | endif() 69 | 70 | add_library( vsgvr ${HEADERS_ACTIONS} ${HEADERS_APP} ${HEADERS_XR} ${HEADERS_EXT} ${SOURCES} ) 71 | 72 | target_include_directories(vsgvr PUBLIC 73 | $ 74 | $ 75 | ) 76 | 77 | target_link_libraries( vsgvr PUBLIC vsg::vsg ${OpenXR_LIBRARY} ) 78 | 79 | set_target_properties( vsgvr PROPERTIES FOLDER "vsgvr" ) 80 | 81 | # TODO: This needs to be in a header - Otherwise anyone linking to vsgvr without 82 | # going through CMake will have to define it themselves 83 | if(WIN32 AND BUILD_SHARED_LIBS) 84 | target_compile_definitions(vsgvr PRIVATE "VSGVR_DECLSPEC=__declspec(dllexport)") 85 | target_compile_definitions(vsgvr INTERFACE "VSGVR_DECLSPEC=__declspec(dllimport)") 86 | else() 87 | target_compile_definitions(vsgvr PUBLIC "VSGVR_DECLSPEC=") 88 | endif() 89 | 90 | set_target_properties(vsgvr PROPERTIES 91 | VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} 92 | SOVERSION ${VSGVR_SOVERSION} 93 | ) 94 | 95 | install(TARGETS vsgvr ${INSTALL_TARGETS_DEFAULT_FLAGS}) 96 | install(FILES ${HEADERS_ACTIONS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/vsgvr/actions) 97 | install(FILES ${HEADERS_APP} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/vsgvr/app) 98 | install(FILES ${HEADERS_XR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/vsgvr/xr) 99 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/actions/Action.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace vsgvr { 29 | class Instance; 30 | class ActionSet; 31 | class Session; 32 | 33 | class VSGVR_DECLSPEC Action : public vsg::Inherit 34 | { 35 | public: 36 | Action(vsg::ref_ptr instance, ActionSet* actionSet, XrActionType actionType, std::string name, std::string localisedName, std::vector subPaths = {} ); 37 | virtual ~Action(); 38 | 39 | XrActionType getActionType() const { return _actionType; } 40 | std::string getName() const { return _name; } 41 | std::string getLocalisedName() const { return _localisedName; } 42 | const std::vector& getSubPaths() const { return _subPaths; } 43 | XrAction getAction() const { return _action; } 44 | 45 | void syncInputState(vsg::ref_ptr instance, vsg::ref_ptr session, std::string subPath = {}); 46 | 47 | // TODO: Writing lots of wrappers on openxr api isn't great, 48 | // but this is worse. Rework to subclasses for each type, 49 | // perhaps allow custom actions by the app providing a 50 | // lambda that makes the appropriate OpenXR state update? 51 | XrActionStateBoolean getStateBool( std::string subPath = {} ) const; 52 | XrActionStateFloat getStateFloat( std::string subPath = {} ) const; 53 | XrActionStateVector2f getStateVec2f( std::string subPath = {} ) const; 54 | bool getStateValid( std::string subPath = {} ) const; 55 | 56 | private: 57 | void createAction(vsg::ref_ptr instance, ActionSet* actionSet); 58 | void destroyAction(); 59 | 60 | protected: 61 | XrActionType _actionType; 62 | std::string _name; 63 | std::string _localisedName; 64 | std::vector _subPaths; 65 | XrAction _action; 66 | 67 | struct ActionState { 68 | XrActionStateBoolean _stateBool = {}; 69 | XrActionStateFloat _stateFloat = {}; 70 | XrActionStateVector2f _stateVec2f = {}; 71 | bool _stateValid = false; 72 | }; 73 | // 74 | std::map _state; 75 | }; 76 | } 77 | 78 | EVSG_type_name(vsgvr::Action); 79 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/actions/ActionPoseBinding.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | namespace vsgvr { 30 | class Session; 31 | 32 | /** 33 | * An action of type XR_INPUT_ACTION_TYPE_POSE, and an associated action space 34 | * The space will only be valid while a session is running 35 | */ 36 | class VSGVR_DECLSPEC ActionPoseBinding : public vsg::Inherit 37 | { 38 | public: 39 | ActionPoseBinding(vsg::ref_ptr instance, ActionSet* actionSet, std::string name, std::string localisedName); 40 | virtual ~ActionPoseBinding(); 41 | 42 | XrSpace getActionSpace() const { return _space; } 43 | bool getTransformValid() const { return _transformValid; } 44 | vsg::dmat4 getTransform() const { return _transform; } 45 | 46 | void createActionSpace(Session* session); 47 | void destroyActionSpace(); 48 | 49 | void setTransform(XrSpaceLocation location); 50 | private: 51 | XrSpace _space = 0; 52 | 53 | bool _transformValid = false; 54 | vsg::dmat4 _transform; 55 | }; 56 | } 57 | 58 | EVSG_type_name(vsgvr::ActionPoseBinding); 59 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/actions/ActionSet.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | namespace vsgvr { 31 | class Instance; 32 | class VSGVR_DECLSPEC ActionSet : public vsg::Inherit 33 | { 34 | public: 35 | ActionSet(Instance* instance, std::string name, std::string localisedName, uint32_t priority = 0); 36 | ~ActionSet(); 37 | 38 | XrActionSet getActionSet() const { return _actionSet; } 39 | std::string getName() const { return _name; } 40 | std::string getLocalisedName() const { return _localisedName; } 41 | uint32_t getPriority() const { return _priority; } 42 | 43 | // Storage for actions in the set. 44 | // Any actions within the set will be synchronised by the viewer 45 | // each frame. 46 | std::vector> actions; 47 | 48 | struct SuggestedInteractionBinding 49 | { 50 | Action* action; 51 | std::string path; 52 | }; 53 | static bool suggestInteractionBindings(Instance* instance, std::string interactionProfile, std::list bindings); 54 | 55 | private: 56 | void createActionSet(Instance* instance); 57 | void destroyActionSet(); 58 | 59 | std::string _name; 60 | std::string _localisedName; 61 | uint32_t _priority; 62 | 63 | XrActionSet _actionSet; 64 | 65 | static std::set suggestInteractionBindingsCalledFor; 66 | }; 67 | } 68 | 69 | EVSG_type_name(vsgvr::ActionSet); 70 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/actions/SpaceBinding.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace vsgvr { 31 | class Session; 32 | /** 33 | * A binding class allowing an XrSpace to be tracked by the Viewer. 34 | * 35 | * The specified reference space will be kept updated during rendering (along with any ActionPoseBindings) 36 | * in order to track elements such as the position of the headset (view) space, or user's local space. 37 | * 38 | * SpaceBindings managed by the Viewer will be located in relation to the Session's reference space. 39 | * They may be located relative to a different base space by the application if required 40 | * 41 | * ```c++ 42 | * // After calling Viewer::advanceToNextFrame, and before Viewer::releaseFrame 43 | * auto t = viewer->getFrameState()->predictedDisplayTime; 44 | * auto located = spaceBinding->getSpace()->locate( someBaseReferenceSpace->getSpace(), t ); 45 | * spaceBinding->setTransform(located); 46 | * ``` 47 | */ 48 | class VSGVR_DECLSPEC SpaceBinding : public vsg::Inherit 49 | { 50 | public: 51 | SpaceBinding(vsg::ref_ptr space); 52 | virtual ~SpaceBinding(); 53 | 54 | vsg::ref_ptr getSpace() const { return _space; } 55 | 56 | bool getTransformValid() const { return _transformValid; } 57 | vsg::dmat4 getTransform() const { return _transform; } 58 | 59 | void setTransform(XrSpaceLocation location); 60 | private: 61 | vsg::ref_ptr _space; 62 | 63 | bool _transformValid = false; 64 | vsg::dmat4 _transform; 65 | }; 66 | } 67 | 68 | EVSG_type_name(vsgvr::SpaceBinding); 69 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/app/CompositionLayerProjection.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace vsgvr { 27 | /// XrCompositionLayerProjection - Planar projected images rendered for each eye, displaying the required view within the scene 28 | /// 29 | /// When this layer is used cameras do not need to be provided when calling createCommandGraphsForView. 30 | /// If a camera is provided it will be used, but any cameras used by this layer will be modified each frame, in order to 31 | /// render the scene to the headset. 32 | /// 33 | /// Cameras used with this layer should not be directly shared for any other use - Doing so can cause deadlocks when running 34 | /// under SteamVR (Instead a separate camera should be constructed and synced to the user's head position). 35 | class VSGVR_DECLSPEC CompositionLayerProjection final : public vsg::Inherit 36 | { 37 | public: 38 | CompositionLayerProjection() = delete; 39 | CompositionLayerProjection(vsg::ref_ptr referenceSpace); 40 | CompositionLayerProjection(vsg::ref_ptr referenceSpace, XrCompositionLayerFlags inFlags); 41 | virtual ~CompositionLayerProjection(); 42 | XrCompositionLayerBaseHeader* getCompositionLayerBaseHeaderPtr() override { return reinterpret_cast(&_compositionLayer); } 43 | 44 | XrCompositionLayerFlags flags; 45 | 46 | std::vector getSwapchainImageRequirements(vsg::ref_ptr instance) override; 47 | void render(vsg::ref_ptr instance, vsg::ref_ptr session, XrFrameState frameState, vsg::ref_ptr frameStamp) override; 48 | 49 | double nearPlane = 0.05; 50 | double farPlane = 100.0; 51 | 52 | protected: 53 | XrCompositionLayerProjection _compositionLayer; 54 | std::vector _layerProjectionViews; 55 | // Details of chosen _xrTraits->viewConfigurationType 56 | // Details of individual views - recommended size / sampling 57 | XrViewConfigurationProperties _viewConfigurationProperties; 58 | std::vector _viewConfigurationViews; 59 | }; 60 | } 61 | 62 | EVSG_type_name(vsgvr::CompositionLayerProjection); 63 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/app/CompositionLayerQuad.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace vsgvr { 27 | /// XrCompositionLayerQuad - Rendered elements on a 2D quad, positioned in world space. 28 | /// 29 | /// This composition layer is typically used for rendering UI panels or other content, 30 | /// as a plane within the world. Note that this plane will obscure the world, ignoring 31 | /// depth. 32 | class VSGVR_DECLSPEC CompositionLayerQuad final : public vsg::Inherit 33 | { 34 | public: 35 | CompositionLayerQuad() = delete; 36 | CompositionLayerQuad(vsg::ref_ptr referenceSpace); 37 | CompositionLayerQuad(vsg::ref_ptr referenceSpace, uint32_t inWidthPixels, uint32_t inHeightPixels, uint32_t inNumSamples); 38 | CompositionLayerQuad(vsg::ref_ptr referenceSpace, uint32_t inWidthPixels, uint32_t inHeightPixels, uint32_t inNumSamples, vsg::dvec3 position, vsg::dquat orientation, XrExtent2Df inSizeMeters, XrCompositionLayerFlags inFlags, XrEyeVisibility inEyeVisibility); 39 | CompositionLayerQuad(vsg::ref_ptr referenceSpace, uint32_t inWidthPixels, uint32_t inHeightPixels, uint32_t inNumSamples, XrPosef inPose, XrExtent2Df inSizeMeters, XrCompositionLayerFlags inFlags, XrEyeVisibility inEyeVisibility); 40 | virtual ~CompositionLayerQuad(); 41 | XrCompositionLayerBaseHeader* getCompositionLayerBaseHeaderPtr() override { return reinterpret_cast(&_compositionLayer); } 42 | 43 | std::vector getSwapchainImageRequirements(vsg::ref_ptr instance) override; 44 | void render(vsg::ref_ptr instance, vsg::ref_ptr session, XrFrameState frameState, vsg::ref_ptr frameStamp) override; 45 | 46 | void setPose(vsg::dvec3 position, vsg::dquat orientation); 47 | 48 | /// Image properties for the rendered quad 49 | uint32_t widthPixels = 1920; 50 | uint32_t heightPixels = 1080; 51 | uint32_t numSamples = 1; 52 | 53 | /// Positioning properties 54 | /// Note: XrPosef is in the OpenXR coordinate system - X-right, Y-up, Z-back 55 | XrPosef pose = { 56 | {0.0f, 0.0f, 0.0f, 1.0f}, 57 | {0.0f, 0.0f, 0.0f} 58 | }; 59 | XrExtent2Df sizeMeters = { 1.0, 1.0 }; 60 | XrCompositionLayerFlags flags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT; 61 | XrEyeVisibility eyeVisibility = XrEyeVisibility::XR_EYE_VISIBILITY_BOTH; 62 | protected: 63 | XrCompositionLayerQuad _compositionLayer; 64 | }; 65 | } 66 | 67 | EVSG_type_name(vsgvr::CompositionLayerQuad); 68 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/app/UserOrigin.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | namespace vsgvr { 28 | 29 | /// A transform node which allows the vsgvr::Viewer origin to be set within the 30 | /// scene via position, rotation, and scale. 31 | /// 32 | /// This node functions in the same way as vsg::MatrixTransform, but will 33 | /// transform a child vsg scene to position the user as needed. 34 | /// Note that under vsgvr world space is defined by the OpenXR / vsgvr session, 35 | /// based on the user's physical play area. 36 | /// 37 | /// Actions previously performed in 'world' space may remain if they are performed 38 | /// within the child scene node(s) of this transform - Desktop base interactions 39 | /// should ignore this node, and instead operate directly on the child scene. 40 | /// 41 | /// Likewise vr-specific elements such as SpaceBinding, ActionPoseBinding, and 42 | /// any nodes which represent controllers / trackers should be added to the root 43 | /// of the scene graph, and not as a child of UserOrigin - These elements are 44 | /// tracked within the user's physical play area, rather than within the 45 | /// vsg scene. 46 | class VSGVR_DECLSPEC UserOrigin : public vsg::Inherit 47 | { 48 | public: 49 | UserOrigin(); 50 | 51 | explicit UserOrigin(vsg::dmat4 matrix); 52 | 53 | /// @see setOriginInScene. 54 | explicit UserOrigin(vsg::dvec3 position, vsg::dquat orientation, vsg::dvec3 scale); 55 | 56 | /// @see setUserInScene. 57 | explicit UserOrigin(vsg::dvec3 playerGroundPosition, vsg::dvec3 position, vsg::dquat orientation, vsg::dvec3 scale); 58 | 59 | vsg::dmat4 userToScene() const { return vsg::inverse(matrix); } 60 | vsg::dmat4 sceneToUser() const { return matrix; } 61 | 62 | /// Set the matrix to position the origin within the vsg scene space. 63 | /// 64 | /// Note: The user is not usually at the origin, @see setUserInScene. 65 | /// 66 | /// @param position The position to set the origin to, within the scene's space 67 | /// @param orientation The orientation of the origin, within the scene's space 68 | /// @param scale The scale of the origin, within the scene's space 69 | void setOriginInScene( vsg::dvec3 position, vsg::dquat orientation, vsg::dvec3 scale ); 70 | 71 | /// Set the matrix to position th euser within the vsg scene space. 72 | /// 73 | /// This is similar to setOriginInScene, however accounts for the position of the player 74 | /// within the vr space - The origin will be offset by playerFloorPosition. 75 | /// 76 | /// playerFloorPosition is typically calculated based on the user's head 77 | /// ```c++ 78 | /// // Enable tracking of the headset - View space in OpenXR 79 | /// headPose = vsgvr::SpaceBinding::create( 80 | /// vsgvr::ReferenceSpace::create( 81 | /// _vr->getSession()->getSession(), XrReferenceSpaceType::XR_REFERENCE_SPACE_TYPE_VIEW 82 | /// )); 83 | /// viewer->spaceBindings.push_back(headPose); 84 | /// 85 | /// // The position on the ground, beneath the player 86 | /// // This assumes the user is standing on a flat plane, and that z == 0 in vr space 87 | /// // aligns with z == 0 in scene space (An intersection in scene space may be preferred) 88 | /// auto playerGroundPosition = _headPose->getTransform() * vsg::dvec3{ 0.0, 0.0, 0.0 }; 89 | /// playerPosUser.z = 0.0; 90 | /// ``` 91 | /// 92 | /// @param playerGroundPosition A position on the floor, directly beneath the player, in the vr space 93 | /// @param position The position to set the origin to, within the scene's space 94 | /// @param orientation The orientation of the origin, within the scene's space 95 | /// @param scale The scale of the origin, within the scene's space 96 | void setUserInScene( vsg::dvec3 playerGroundPosition, vsg::dvec3 position, vsg::dquat orientation, vsg::dvec3 scale ); 97 | }; 98 | } 99 | 100 | EVSG_type_name(vsgvr::UserOrigin); 101 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/extensions/KHRCompositionLayerEquirect.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace vsgvr { 27 | /// XrCompositionLayerEquirectKHR - equirectangular image mapped to the inside of a sphere 28 | class VSGVR_DECLSPEC KHRCompositionLayerEquirect final : public vsg::Inherit 29 | { 30 | public: 31 | static const char* instanceExtension() { return "XR_KHR_composition_layer_equirect"; } 32 | 33 | KHRCompositionLayerEquirect() = delete; 34 | KHRCompositionLayerEquirect(vsg::ref_ptr referenceSpace); 35 | KHRCompositionLayerEquirect(vsg::ref_ptr referenceSpace, uint32_t inWidthPixels, uint32_t inHeightPixels); 36 | 37 | virtual ~KHRCompositionLayerEquirect(); 38 | 39 | XrCompositionLayerBaseHeader* getCompositionLayerBaseHeaderPtr() override { return reinterpret_cast(&_compositionLayer); } 40 | std::vector getSwapchainImageRequirements(vsg::ref_ptr instance) override; 41 | void render(vsg::ref_ptr instance, vsg::ref_ptr session, XrFrameState frameState, vsg::ref_ptr frameStamp) override; 42 | 43 | void setPose(vsg::dvec3 position, vsg::dquat orientation); 44 | 45 | /// Image properties for the rendered quad 46 | uint32_t widthPixels = 3600; 47 | uint32_t heightPixels = 1800; 48 | uint32_t numSamples = 1; 49 | 50 | /// Positioning properties 51 | XrPosef pose = { 52 | {0.0f, 0.0f, 0.0f, 1.0f}, 53 | {0.0f, 0.0f, 0.0f} 54 | }; 55 | float radius = 0.0f; 56 | XrVector2f scale = { 1.0f, 1.0f }; 57 | XrVector2f bias = { 0.0f, 0.0f }; 58 | 59 | // Composition propertiesw 60 | XrCompositionLayerFlags flags = 0x00; 61 | XrEyeVisibility eyeVisibility = XrEyeVisibility::XR_EYE_VISIBILITY_BOTH; 62 | protected: 63 | XrCompositionLayerEquirectKHR _compositionLayer; 64 | }; 65 | } 66 | 67 | EVSG_type_name(vsgvr::KHRCompositionLayerEquirect); 68 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/extensions/KHRCompositionLayerEquirect2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | namespace vsgvr { 28 | /// XrCompositionLayerEquirect2KHR - equirectangular image mapped to the inside of a sphere 29 | class VSGVR_DECLSPEC KHRCompositionLayerEquirect2 final : public vsg::Inherit 30 | { 31 | public: 32 | static const char* instanceExtension() { return "XR_KHR_composition_layer_equirect2"; } 33 | 34 | KHRCompositionLayerEquirect2() = delete; 35 | KHRCompositionLayerEquirect2(vsg::ref_ptr referenceSpace); 36 | KHRCompositionLayerEquirect2(vsg::ref_ptr referenceSpace, uint32_t inWidthPixels, uint32_t inHeightPixels); 37 | 38 | virtual ~KHRCompositionLayerEquirect2(); 39 | 40 | XrCompositionLayerBaseHeader* getCompositionLayerBaseHeaderPtr() override { return reinterpret_cast(&_compositionLayer); } 41 | std::vector getSwapchainImageRequirements(vsg::ref_ptr instance) override; 42 | void render(vsg::ref_ptr instance, vsg::ref_ptr session, XrFrameState frameState, vsg::ref_ptr frameStamp) override; 43 | 44 | void setPose(vsg::dvec3 position, vsg::dquat orientation); 45 | 46 | /// Image properties for the rendered quad 47 | uint32_t widthPixels = 3600; 48 | uint32_t heightPixels = 1800; 49 | uint32_t numSamples = 1; 50 | 51 | /// Positioning properties 52 | XrPosef pose = { 53 | {0.0f, 0.0f, 0.0f, 1.0f}, 54 | {0.0f, 0.0f, 0.0f} 55 | }; 56 | float radius = 0.0f; // 0 == Infinite sphere 57 | float centralHorizontalAngle = static_cast(vsg::PI * 2.0); 58 | float upperVerticalAngle = static_cast(vsg::PI / 2.0); 59 | float lowerVerticalAngle = static_cast(- vsg::PI / 2.0); 60 | 61 | // Composition properties 62 | XrCompositionLayerFlags flags = 0x00; 63 | XrEyeVisibility eyeVisibility = XrEyeVisibility::XR_EYE_VISIBILITY_BOTH; 64 | protected: 65 | XrCompositionLayerEquirect2KHR _compositionLayer; 66 | }; 67 | } 68 | 69 | EVSG_type_name(vsgvr::KHRCompositionLayerEquirect2); 70 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/AndroidTraits.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace vsgvr { 29 | class VSGVR_DECLSPEC AndroidTraits : public vsg::Inherit { 30 | public: 31 | AndroidTraits(); 32 | 33 | JavaVM* vm = nullptr; 34 | jobject activity = nullptr; 35 | protected: 36 | virtual ~AndroidTraits(); 37 | }; 38 | } 39 | 40 | EVSG_type_name(vsgvr::AndroidTraits); 41 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/Common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #define XR_USE_GRAPHICS_API_VULKAN 30 | #ifdef ANDROID 31 | # define XR_USE_PLATFORM_ANDROID 32 | # define XR_USE_PLATFORM_ANDROID_KHR 33 | # include 34 | #endif 35 | #include 36 | 37 | #include 38 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/EventHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace vsgvr { 29 | class Instance; 30 | class Session; 31 | class VSGVR_DECLSPEC EventHandler : public vsg::Inherit 32 | { 33 | public: 34 | EventHandler(); 35 | ~EventHandler(); 36 | 37 | void pollEvents(Instance* instance, Session* session); 38 | }; 39 | } 40 | 41 | EVSG_type_name(vsgvr::EventHandler); 42 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/Exception.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | namespace vsgvr 28 | { 29 | /// A general error within vsgvr 30 | struct Exception 31 | { 32 | std::string message; 33 | }; 34 | 35 | /// An OpenXR API error 36 | struct XrException : public Exception 37 | { 38 | XrResult result = XR_SUCCESS; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/GraphicsBindingVulkan.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | namespace vsgvr { 37 | struct VSGVR_DECLSPEC VulkanRequirements 38 | { 39 | uint32_t minVersion; 40 | uint32_t maxVersion; 41 | std::string minVersionStr; 42 | std::string maxVersionStr; 43 | std::set instanceExtensions; 44 | std::set deviceExtensions; 45 | }; 46 | 47 | struct VSGVR_DECLSPEC VulkanGraphicsRequirements 48 | { 49 | VkPhysicalDevice* physicalDevice; 50 | }; 51 | 52 | class VSGVR_DECLSPEC GraphicsBindingVulkan : public vsg::Inherit 53 | { 54 | public: 55 | static VulkanRequirements getVulkanRequirements(vsg::ref_ptr xrInstance); 56 | static VkPhysicalDevice getVulkanDeviceRequirements(vsg::ref_ptr xrInstance, vsg::ref_ptr vsgInstance, const VulkanRequirements& versionReqs); 57 | 58 | GraphicsBindingVulkan() = delete; 59 | GraphicsBindingVulkan(vsg::ref_ptr vsgInstance, vsg::ref_ptr vsgPhysicalDevice, vsg::ref_ptr vsgDevice, uint32_t queueFamilyIndex, uint32_t queueIndex); 60 | ~GraphicsBindingVulkan(); 61 | 62 | vsg::ref_ptr getVsgInstance() const { return _vsgInstance; } 63 | vsg::ref_ptr getVsgPhysicalDevice() const { return _vsgPhysicalDevice; } 64 | vsg::ref_ptr getVsgDevice() const { return _vsgDevice; } 65 | 66 | const XrGraphicsBindingVulkanKHR& getBinding() const { return _binding; } 67 | 68 | private: 69 | vsg::ref_ptr _vsgInstance; 70 | vsg::ref_ptr _vsgPhysicalDevice; 71 | vsg::ref_ptr _vsgDevice; 72 | 73 | XrGraphicsBindingVulkanKHR _binding; 74 | }; 75 | } 76 | 77 | EVSG_type_name(vsgvr::GraphicsBindingVulkan); 78 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/Instance.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace vsgvr { 32 | class VSGVR_DECLSPEC Instance : public vsg::Inherit 33 | { 34 | public: 35 | static std::vector getSupportedApiLayers(); 36 | static std::vector getSupportedInstanceExtensions(const char* apiLayerName = nullptr); 37 | 38 | // Check if a named OpenXR api layer is available 39 | static bool checkApiLayerSupported(const char* apiLayerName); 40 | // Check if a named OpenXR extension is supported 41 | static bool checkInstanceExtensionSupported(const char* extensionName, const char* apiLayerName = nullptr); 42 | 43 | Instance() = delete; 44 | /// Create an OpenXR instance, and configure the overall XrSystem 45 | /// Once initialised applications should configure Instance::traits 46 | /// as needed, in order to continue to initialisation of a Viewer / Session 47 | /// 48 | /// An exception will be thrown if the formFactor is unsupported. In this case applications 49 | /// may attempt to re-create the Instance with an alternate form factor. 50 | Instance(XrFormFactor formFactor, vsg::ref_ptr xrTraits); 51 | ~Instance(); 52 | 53 | std::vector getSupportedViewConfigurationTypes(); 54 | std::vector getSupportedEnvironmentBlendModes(XrViewConfigurationType viewConfiguration); 55 | 56 | /// Check whether instance-level features are supported by the OpenXR runtime 57 | bool checkViewConfigurationSupported(XrViewConfigurationType viewConfiguration); 58 | bool checkEnvironmentBlendModeSupported(XrViewConfigurationType viewConfiguration, XrEnvironmentBlendMode environmentBlendMode); 59 | 60 | vsg::ref_ptr traits; 61 | 62 | XrInstance getInstance() const { return _instance; } 63 | XrInstanceProperties getInstanceProperties() const { return _instanceProperties; } 64 | XrSystemId getSystem() const { return _system; } 65 | XrSystemProperties getSystemProperties() const { return _systemProperties; } 66 | 67 | void onEventInstanceLossPending(const XrEventDataInstanceLossPending& event); 68 | 69 | private: 70 | void createInstance(); 71 | void destroyInstance(); 72 | void createSystem(); 73 | 74 | XrFormFactor _formFactor; 75 | 76 | XrInstance _instance = XR_NULL_HANDLE; 77 | XrInstanceProperties _instanceProperties; 78 | 79 | XrSystemId _system = XR_NULL_SYSTEM_ID; 80 | XrSystemProperties _systemProperties; 81 | }; 82 | } 83 | 84 | EVSG_type_name(vsgvr::Instance); 85 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/Pose.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | namespace vsgvr { 28 | class VSGVR_DECLSPEC Pose : public vsg::Inherit 29 | { 30 | public: 31 | Pose(XrPosef pose); 32 | Pose(vsg::dvec3 position, vsg::dquat orientation); 33 | Pose(vsg::vec3 position, vsg::quat orientation); 34 | virtual ~Pose(); 35 | 36 | void setPose(XrPosef pose); 37 | void setPose(vsg::dvec3 position, vsg::dquat orientation); 38 | void setPose(vsg::vec3 position, vsg::quat orientation); 39 | 40 | XrPosef getPose() const { return _pose; } 41 | 42 | // TODO 43 | // vsg::dmat4 getTransform() const; 44 | // vsg::dvec3 getPosition() const; 45 | // vsg::dquat getOrientation() const; 46 | private: 47 | XrPosef _pose; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/ProjectionMatrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | namespace vsgvr 34 | { 35 | class VSGVR_DECLSPEC ProjectionMatrix : public vsg::Inherit 36 | { 37 | public: 38 | ProjectionMatrix(vsg::dmat4 matrix) 39 | : mat(matrix) 40 | {} 41 | 42 | ProjectionMatrix(const XrFovf& pose, double near, double far) 43 | { 44 | // https://gitlab.freedesktop.org/monado/demos/xrgears/-/blob/master/src/main.cpp _create_projection_from_fov 45 | // See also https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/main/src/common/xr_linear.h 46 | 47 | // TODO: Added to resolve inside-out objects, should be reviewed properly 48 | // TODO: Pretty sure this is related to vsg being reverse-depth by default. Should be fixed to work for both. 49 | std::swap(near, far); 50 | 51 | auto tanL = std::tan(pose.angleLeft); 52 | auto tanD = std::tan(pose.angleDown); 53 | auto tanU = std::tan(pose.angleUp); 54 | auto tanR = std::tan(pose.angleRight); 55 | 56 | auto tanX = tanR - tanL; 57 | auto tanY = tanU - tanD; 58 | 59 | mat = vsg::dmat4( 60 | 2 / tanX, 0, 0, 0, 61 | 0, 2 / tanY, 0, 0, 62 | (tanR + tanL) / tanX, (tanU + tanD) / tanY, -far / (far - near), -1, 63 | 0, 0, -(far * near) / (far - near), 0 64 | ); 65 | } 66 | 67 | vsg::dmat4 transform() const override { return mat; } 68 | vsg::dmat4 mat; 69 | }; 70 | } 71 | 72 | EVSG_type_name(vsgvr::ProjectionMatrix); 73 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/ReferenceSpace.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | namespace vsgvr { 28 | class Session; 29 | 30 | /// A XrSpace handle representing a pose and orientation within one of the base reference space types 31 | /// 32 | /// Reference spaces are used primarily by the Session and CompositionLayers in order to position content. 33 | class VSGVR_DECLSPEC ReferenceSpace : public vsg::Inherit 34 | { 35 | public: 36 | ReferenceSpace() = delete; 37 | ReferenceSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType); 38 | ReferenceSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType, vsg::dvec3 position, vsg::dquat orientation); 39 | ReferenceSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType, XrPosef poseInReferenceSpace); 40 | virtual ~ReferenceSpace(); 41 | 42 | XrSpace getSpace() const { return _space; } 43 | XrSpaceLocation locate(XrSpace baseSpace, XrTime time); 44 | 45 | private: 46 | void createSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType, XrPosef poseInReferenceSpace); 47 | void destroySpace(); 48 | 49 | XrSpace _space = XR_NULL_HANDLE; 50 | }; 51 | } 52 | 53 | EVSG_type_name(vsgvr::ReferenceSpace); 54 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/Session.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | namespace vsgvr { 35 | class VSGVR_DECLSPEC Session : public vsg::Inherit 36 | { 37 | public: 38 | Session() = delete; 39 | Session(vsg::ref_ptr instance, vsg::ref_ptr graphicsBinding); 40 | 41 | vsg::ref_ptr getGraphicsBinding() { return _graphicsBinding; } 42 | 43 | XrSession getSession() const { return _session; } 44 | XrSessionState getSessionState() const { return _sessionState; } 45 | bool getSessionRunning() const { return _sessionRunning; } 46 | 47 | /// The session's reference space 48 | vsg::ref_ptr space; 49 | 50 | XrViewConfigurationProperties getViewConfigurationProperties(); 51 | std::vector getViewConfigurationViews(); 52 | 53 | std::vector getSupportedSwapchainFormats(); 54 | std::vector getSupportedSwapchainSamples(); 55 | std::vector getSupportedReferenceSpaceTypes(); 56 | 57 | bool checkSwapchainFormatSupported(VkFormat format); 58 | bool checkSwapchainSampleCountSupported(uint32_t numSamples); 59 | bool checkReferenceSpaceTypeSupported(XrReferenceSpaceType referenceSpaceType); 60 | 61 | void onEventStateChanged(const XrEventDataSessionStateChanged& event); 62 | 63 | void beginSession(XrViewConfigurationType viewConfigurationType); 64 | void endSession(); 65 | 66 | protected: 67 | virtual ~Session(); 68 | private: 69 | void createSession(); 70 | void destroySession(); 71 | 72 | vsg::ref_ptr _instance; 73 | vsg::ref_ptr _graphicsBinding; 74 | 75 | XrSession _session = XR_NULL_HANDLE; 76 | XrSessionState _sessionState = XrSessionState::XR_SESSION_STATE_UNKNOWN; 77 | bool _sessionRunning = false; 78 | }; 79 | } 80 | 81 | EVSG_type_name(vsgvr::Session); 82 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/Swapchain.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace vsgvr 30 | { 31 | /// Binding between an OpenXR swapchain image and vsg::Image 32 | /// 33 | /// These images are managed by OpenXR itself - When destroyed this class 34 | /// does not call vkDestroyImage, and should otherwise be considered read-only. 35 | class VSGVR_DECLSPEC SwapchainImage : public vsg::Inherit 36 | { 37 | public: 38 | SwapchainImage(VkImage image, vsg::Device *device); 39 | 40 | protected: 41 | virtual ~SwapchainImage(); 42 | }; 43 | using SwapchainImages = std::vector>; 44 | 45 | /// Wrapper around XrSwapchain, mapping images to vsg::Image 46 | /// 47 | /// * Swapchains manage a series of images within OpenXR 48 | /// * Multiple swapchains may be created by the application - Typically one per XrView or composition layer 49 | /// * Swapchains belong to the active session, and are destroyed during session shutdown 50 | /// * Likewise, swapchain images belong to a swapchain, and are destroyed as part of this 51 | /// * Each frame images are acquired from the swapchain, rendered to, and then released to the OpenXR compositor 52 | class VSGVR_DECLSPEC Swapchain : public vsg::Inherit 53 | { 54 | public: 55 | Swapchain() = delete; 56 | Swapchain(XrSession session, VkFormat swapchainFormat, uint32_t width, uint32_t height, uint32_t sampleCount, vsg::ref_ptr graphicsBinding); 57 | 58 | ~Swapchain(); 59 | 60 | VkImage acquireImage(uint32_t &index); 61 | bool waitImage(XrDuration timeout); 62 | void releaseImage(); 63 | 64 | VkFormat getSwapchainFormat() const { return _swapchainFormat; } 65 | XrSwapchain getSwapchain() const { return _swapchain; } 66 | VkExtent2D getExtent() const { return _extent; } 67 | 68 | vsg::ImageViews getImageViews() const { return _imageViews; } 69 | 70 | private: 71 | void createSwapchain(XrSession session, uint32_t width, uint32_t height, uint32_t sampleCount, vsg::ref_ptr graphicsBinding); 72 | 73 | void destroySwapchain(); 74 | 75 | VkFormat _swapchainFormat = VK_FORMAT_UNDEFINED; 76 | XrSwapchain _swapchain = 0; 77 | VkExtent2D _extent; 78 | 79 | std::vector _images; 80 | vsg::ImageViews _imageViews; 81 | }; 82 | } 83 | 84 | EVSG_type_name(vsgvr::SwapchainImage); 85 | EVSG_type_name(vsgvr::Swapchain); 86 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/Traits.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | namespace vsgvr 32 | { 33 | // Application and runtime settings for vsgvr 34 | class VSGVR_DECLSPEC Traits : public vsg::Inherit 35 | { 36 | public: 37 | Traits(); 38 | 39 | // OpenXR extensions required by the application 40 | std::vector xrExtensions = { 41 | // "XR_EXT_debug_utils" 42 | }; 43 | std::vector xrLayers = { 44 | // "XR_APILAYER_LUNARG_core_validation" 45 | }; 46 | 47 | // Application metadata provided to the OpenXR runtime 48 | XrVersion apiVersion = XR_MAKE_VERSION(1, 0, 0); 49 | std::string applicationName = "VSGVR Application"; 50 | std::string engineName = "VSGVR"; 51 | uint32_t engineVersion = 0; 52 | uint32_t applicationVersion = 0; 53 | 54 | void setApplicationVersion(uint32_t maj, uint32_t min, uint32_t patch); 55 | void setEngineVersion(uint32_t maj, uint32_t min, uint32_t patch); 56 | 57 | // The configuration of displays used for the form factor 58 | // May be validated via Instance::checkViewConfigurationSupported 59 | XrViewConfigurationType viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; 60 | 61 | // The mode used to blend rendered data with the environment. This may vary based on the 62 | // capabilities of a headset, such as whether visual or camera-based environment is supported 63 | // May be validated via Instance::checkEnvironmentBlendModeSupported 64 | XrEnvironmentBlendMode environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE; 65 | 66 | // The Vulkan image format used for OpenXR swapchain images (i.e. the render target for vsg content) 67 | // May be validated via Session::checkSwapchainFormatSupported 68 | // Runtimes should support VK_FORMAT_R8G8B8A8_UNORM and VK_FORMAT_R8G8B8A8_SRGB as preferred formats 69 | VkFormat swapchainFormat = VK_FORMAT_R8G8B8A8_UNORM; 70 | 71 | // The number of samples used for swapchain images 72 | // May be validated via Session::checkSwapchainSampleCountSupported 73 | uint32_t swapchainSampleCount = 1; 74 | 75 | protected: 76 | virtual ~Traits(); 77 | }; 78 | } 79 | 80 | EVSG_type_name(vsgvr::Traits); 81 | -------------------------------------------------------------------------------- /vsgvr/include/vsgvr/xr/ViewMatrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace vsgvr { 33 | class VSGVR_DECLSPEC ViewMatrix : public vsg::Inherit 34 | { 35 | public: 36 | ViewMatrix(const vsg::dmat4& m) : 37 | matrix(m) 38 | {} 39 | 40 | ViewMatrix(const XrPosef& pose) 41 | { 42 | // OpenXR space: x-right, y-up, z-back 43 | // VSG/Vulkan space: x-right, y-forward, z-up 44 | // * Invert y -> To flip the handedness (x-right, y-back, z-up) 45 | // * Rotate clockwise around x -> To move into vsg space (x-right, y-up, z-back) 46 | // After this, models are built for vsg space, and default concepts in the api map across 47 | // 48 | // Ref: 49 | // * https://gitlab.freedesktop.org/monado/demos/xrgears/-/blob/master/src/main.cpp _create_view_from_pose 50 | // * https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/main/src/common/xr_linear.h 51 | 52 | // Work out the view matrix for the HMD camera, in the VSG space 53 | auto q = vsg::dquat( 54 | pose.orientation.x, 55 | pose.orientation.y * -1.0, 56 | pose.orientation.z, 57 | pose.orientation.w * -1.0 58 | ); 59 | auto rotateMat = vsg::rotate(q); 60 | 61 | auto p = vsg::dvec3(pose.position.x, pose.position.y * -1, pose.position.z); 62 | auto translateMat = vsg::translate(p); 63 | matrix = vsg::inverse(translateMat * rotateMat ); 64 | 65 | // Also map all rendered content into this space 66 | // Other OpenXR applications don't do this bit, but adding it in 67 | // means we can place content as we would normally in VSG, 68 | // and that this view matrix matches the equivalent vsg::LookAt 69 | // for a desktop camera. 70 | vsg::dmat4 viewAxesMat( 71 | 1, 0, 0, 0, 72 | 0, -1, 0, 0, 73 | 0, 0, 1, 0, 74 | 0, 0, 0, 1 75 | ); 76 | auto worldRotateMat = vsg::rotate(-vsg::PI / 2.0, 1.0, 0.0, 0.0); 77 | matrix = matrix * viewAxesMat * worldRotateMat; 78 | } 79 | 80 | vsg::dmat4 transform() const override { return matrix; } 81 | vsg::dmat4 matrix; 82 | }; 83 | } 84 | 85 | EVSG_type_name(vsgvr::ViewMatrix); 86 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/actions/ActionPoseBinding.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include "../xr/Macros.cpp" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | namespace vsgvr 34 | { 35 | ActionPoseBinding::ActionPoseBinding(vsg::ref_ptr instance, ActionSet* actionSet, std::string name, std::string localisedName ) 36 | : Inherit(instance, actionSet, XR_ACTION_TYPE_POSE_INPUT, name, localisedName ) 37 | {} 38 | 39 | ActionPoseBinding::~ActionPoseBinding() 40 | { 41 | destroyActionSpace(); 42 | } 43 | 44 | void ActionPoseBinding::createActionSpace(Session* session) 45 | { 46 | if( _space ) throw Exception({"Space already created: " + _name}); 47 | 48 | // Create the action space 49 | { 50 | auto info = XrActionSpaceCreateInfo(); 51 | info.type = XR_TYPE_ACTION_SPACE_CREATE_INFO; 52 | info.next = nullptr; 53 | info.action = _action; 54 | info.subactionPath = XR_NULL_PATH; 55 | info.poseInActionSpace.orientation = XrQuaternionf{0.0f, 0.0f, 0.0f, 1.0f}; 56 | info.poseInActionSpace.position = XrVector3f{0.0f, 0.0f, 0.0f}; 57 | xr_check(xrCreateActionSpace(session->getSession(), &info, &_space), "Failed to create action space: " + _name); 58 | } 59 | } 60 | 61 | void ActionPoseBinding::destroyActionSpace() 62 | { 63 | if (_space) { 64 | xr_check(xrDestroySpace(_space)); 65 | _space = 0; 66 | } 67 | } 68 | 69 | void ActionPoseBinding::setTransform(XrSpaceLocation location) 70 | { 71 | if ((location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) && 72 | (location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)) 73 | { 74 | _transformValid = true; 75 | 76 | vsg::dmat4 xrToVsg; 77 | vsg::transform(vsg::CoordinateConvention::Y_UP, vsg::CoordinateConvention::Z_UP, xrToVsg); 78 | auto q = vsg::dquat( 79 | location.pose.orientation.x, 80 | location.pose.orientation.y, 81 | location.pose.orientation.z, 82 | location.pose.orientation.w 83 | ); 84 | auto p = vsg::dvec3(location.pose.position.x, location.pose.position.y, location.pose.position.z); 85 | auto transform = xrToVsg * vsg::translate(p) * vsg::rotate(q); 86 | 87 | _transform = transform; 88 | } 89 | else 90 | { 91 | _transformValid = false; 92 | } 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/actions/ActionSet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include "../xr/Macros.cpp" 26 | 27 | #include 28 | 29 | namespace vsgvr 30 | { 31 | std::set ActionSet::suggestInteractionBindingsCalledFor; 32 | 33 | ActionSet::ActionSet(Instance *instance, std::string name, std::string localisedName, uint32_t priority) 34 | : _name(name), _localisedName(localisedName), _priority(priority) 35 | { 36 | if (_localisedName.empty()) 37 | _localisedName = name; 38 | createActionSet(instance); 39 | } 40 | 41 | ActionSet::~ActionSet() 42 | { 43 | destroyActionSet(); 44 | } 45 | 46 | void ActionSet::createActionSet(Instance *instance) 47 | { 48 | auto info = XrActionSetCreateInfo(); 49 | info.type = XR_TYPE_ACTION_SET_CREATE_INFO; 50 | info.next = nullptr; 51 | strncpy(info.actionSetName, _name.c_str(), std::min(static_cast(_name.size()), static_cast(XR_MAX_ACTION_NAME_SIZE))); 52 | strncpy(info.localizedActionSetName, _localisedName.c_str(), std::min(static_cast(_localisedName.size()), static_cast(XR_MAX_ACTION_NAME_SIZE))); 53 | info.priority = _priority; 54 | xr_check(xrCreateActionSet(instance->getInstance(), &info, &_actionSet), "Failed to create action set: " + _name); 55 | } 56 | 57 | void ActionSet::destroyActionSet() 58 | { 59 | xr_check(xrDestroyActionSet(_actionSet)); 60 | } 61 | 62 | bool ActionSet::suggestInteractionBindings(Instance* instance, std::string interactionProfile, std::list bindings) 63 | { 64 | if (suggestInteractionBindingsCalledFor.find(interactionProfile) != suggestInteractionBindingsCalledFor.end()) 65 | { 66 | throw Exception({"suggestInteractionBindings may only be called once for each interaction profile - Collate your calls together"}); 67 | } 68 | suggestInteractionBindingsCalledFor.insert(interactionProfile); 69 | 70 | XrPath xrProfilePath; 71 | auto res = xrStringToPath(instance->getInstance(), interactionProfile.c_str(), &xrProfilePath); 72 | if (!XR_SUCCEEDED(res)) 73 | { 74 | std::cerr << "ActionSet::suggestInteractionBindings: xrStringToPath(" << interactionProfile << "): " << to_string(res) << std::endl; 75 | return false; 76 | } 77 | 78 | std::vector actionBindings; 79 | for( auto& b : bindings ) 80 | { 81 | XrPath xrPath; 82 | xr_check(xrStringToPath(instance->getInstance(), b.path.c_str(), &xrPath), "suggestInteractionBindings: Invalid path provided"); 83 | actionBindings.push_back(XrActionSuggestedBinding{b.action->getAction(), xrPath}); 84 | } 85 | 86 | auto interactionProfileBinding = XrInteractionProfileSuggestedBinding(); 87 | interactionProfileBinding.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING; 88 | interactionProfileBinding.next = nullptr; 89 | interactionProfileBinding.interactionProfile = xrProfilePath; 90 | interactionProfileBinding.countSuggestedBindings = static_cast(actionBindings.size()); 91 | interactionProfileBinding.suggestedBindings = actionBindings.data(); 92 | auto result = xrSuggestInteractionProfileBindings(instance->getInstance(), &interactionProfileBinding); 93 | if (XR_SUCCEEDED(result)) 94 | { 95 | return true; 96 | } 97 | else 98 | { 99 | std::cerr << "ActionPoseBinding::suggestInteractionBinding: Failed to suggest interaction bindings (" << interactionProfile << "): " << to_string(result) << std::endl; 100 | return false; 101 | } 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/actions/SpaceBinding.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "../xr/Macros.cpp" 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | namespace vsgvr 35 | { 36 | SpaceBinding::SpaceBinding(vsg::ref_ptr space) 37 | : _space(space) 38 | {} 39 | 40 | SpaceBinding::~SpaceBinding() 41 | {} 42 | 43 | void SpaceBinding::setTransform(XrSpaceLocation location) 44 | { 45 | if ((location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) && 46 | (location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)) 47 | { 48 | _transformValid = true; 49 | 50 | vsg::dmat4 xrToVsg; 51 | vsg::transform(vsg::CoordinateConvention::Y_UP, vsg::CoordinateConvention::Z_UP, xrToVsg); 52 | auto q = vsg::dquat( 53 | location.pose.orientation.x, 54 | location.pose.orientation.y, 55 | location.pose.orientation.z, 56 | location.pose.orientation.w 57 | ); 58 | auto p = vsg::dvec3(location.pose.position.x, location.pose.position.y, location.pose.position.z); 59 | auto transform = xrToVsg * vsg::translate(p) * vsg::rotate(q); 60 | 61 | _transform = transform; 62 | } 63 | else 64 | { 65 | _transformValid = false; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/app/UserOrigin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | namespace vsgvr 26 | { 27 | UserOrigin::UserOrigin() {} 28 | 29 | UserOrigin::UserOrigin(vsg::dmat4 matrix) 30 | : Inherit(matrix) 31 | {} 32 | 33 | UserOrigin::UserOrigin(vsg::dvec3 position, vsg::dquat orientation, vsg::dvec3 scale) 34 | { 35 | setOriginInScene(position, orientation, scale); 36 | } 37 | 38 | UserOrigin::UserOrigin(vsg::dvec3 playerGroundPosition, vsg::dvec3 position, vsg::dquat orientation, vsg::dvec3 scale) 39 | { 40 | setUserInScene(playerGroundPosition, position, orientation, scale); 41 | } 42 | 43 | void UserOrigin::setOriginInScene(vsg::dvec3 position, vsg::dquat orientation, vsg::dvec3 scale) 44 | { 45 | matrix = vsg::inverse( 46 | vsg::translate(position) * 47 | vsg::rotate(orientation) * 48 | vsg::scale(scale) 49 | ); 50 | } 51 | 52 | void UserOrigin::setUserInScene(vsg::dvec3 playerGroundPosition, vsg::dvec3 newPosition, vsg::dquat orientation, vsg::dvec3 scale) 53 | { 54 | matrix = vsg::inverse( 55 | vsg::translate(newPosition) * 56 | vsg::rotate(orientation) * 57 | vsg::scale(scale) * 58 | vsg::translate(-playerGroundPosition) 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/extensions/KHRCompositionLayerEquirect.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "../xr/Macros.cpp" 29 | 30 | #include 31 | #include 32 | 33 | namespace vsgvr { 34 | KHRCompositionLayerEquirect::KHRCompositionLayerEquirect(vsg::ref_ptr referenceSpace) 35 | : Inherit(referenceSpace) 36 | {} 37 | KHRCompositionLayerEquirect::KHRCompositionLayerEquirect(vsg::ref_ptr referenceSpace, 38 | uint32_t inWidthPixels, uint32_t inHeightPixels) 39 | : Inherit(referenceSpace) 40 | , widthPixels(inWidthPixels) 41 | , heightPixels(inHeightPixels) 42 | {} 43 | KHRCompositionLayerEquirect::~KHRCompositionLayerEquirect() {} 44 | 45 | std::vector KHRCompositionLayerEquirect::getSwapchainImageRequirements(vsg::ref_ptr instance) 46 | { 47 | std::vector reqs; 48 | reqs.push_back({widthPixels, heightPixels, numSamples}); 49 | return reqs; 50 | } 51 | void KHRCompositionLayerEquirect::render(vsg::ref_ptr instance, vsg::ref_ptr session, XrFrameState frameState, vsg::ref_ptr frameStamp) 52 | { 53 | // Render the scene 54 | auto swapchainI = 0; 55 | auto swapchain = getSwapchain(swapchainI); 56 | uint32_t swapChainImageIndex = 0; 57 | 58 | swapchain->acquireImage(swapChainImageIndex); 59 | XrDuration timeoutNs = 20000000; 60 | auto waitSuccess = swapchain->waitImage(timeoutNs); 61 | 62 | if (waitSuccess) 63 | { 64 | // reset connected ExecuteCommands 65 | for (auto& recordAndSubmitTask : _recordAndSubmitTasks) 66 | { 67 | for (auto& commandGraph : recordAndSubmitTask->commandGraphs) 68 | { 69 | commandGraph->reset(); 70 | if (!commandGraph->children.empty()) 71 | { 72 | // TODO: More reliable way to fetch render graph? Maybe just store a pointer to it if there's no downside? 73 | if (auto renderGraph = commandGraph->children[0].cast()) 74 | { 75 | renderGraph->framebuffer = frames(swapchainI)[swapChainImageIndex].framebuffer; 76 | } 77 | } 78 | } 79 | } 80 | 81 | for (auto& recordAndSubmitTask : _recordAndSubmitTasks) 82 | { 83 | recordAndSubmitTask->submit(frameStamp); 84 | } 85 | 86 | swapchain->releaseImage(); 87 | } 88 | 89 | // Add the composition layer for the frame end info 90 | _compositionLayer.type = XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR; 91 | _compositionLayer.next = nullptr; 92 | _compositionLayer.layerFlags = flags; 93 | _compositionLayer.space = _referenceSpace->getSpace(); 94 | _compositionLayer.eyeVisibility = eyeVisibility; 95 | _compositionLayer.subImage.swapchain = swapchain->getSwapchain(); 96 | auto extent = swapchain->getExtent(); 97 | _compositionLayer.subImage.imageRect = XrRect2Di{ {0, 0}, 98 | {static_cast(extent.width), static_cast(extent.height)} 99 | }; 100 | _compositionLayer.subImage.imageArrayIndex = 0; 101 | _compositionLayer.pose = pose; 102 | _compositionLayer.radius = radius; 103 | _compositionLayer.scale = scale; 104 | _compositionLayer.bias = bias; 105 | } 106 | 107 | void KHRCompositionLayerEquirect::setPose(vsg::dvec3 position, vsg::dquat orientation) 108 | { 109 | pose = Pose(position, orientation).getPose(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/extensions/KHRCompositionLayerEquirect2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "../xr/Macros.cpp" 29 | 30 | #include 31 | #include 32 | 33 | namespace vsgvr { 34 | KHRCompositionLayerEquirect2::KHRCompositionLayerEquirect2(vsg::ref_ptr referenceSpace) 35 | : Inherit(referenceSpace) 36 | {} 37 | KHRCompositionLayerEquirect2::KHRCompositionLayerEquirect2(vsg::ref_ptr referenceSpace, 38 | uint32_t inWidthPixels, uint32_t inHeightPixels) 39 | : Inherit(referenceSpace) 40 | , widthPixels(inWidthPixels) 41 | , heightPixels(inHeightPixels) 42 | {} 43 | KHRCompositionLayerEquirect2::~KHRCompositionLayerEquirect2() {} 44 | 45 | std::vector KHRCompositionLayerEquirect2::getSwapchainImageRequirements(vsg::ref_ptr instance) 46 | { 47 | std::vector reqs; 48 | reqs.push_back({widthPixels, heightPixels, numSamples}); 49 | return reqs; 50 | } 51 | void KHRCompositionLayerEquirect2::render(vsg::ref_ptr instance, vsg::ref_ptr session, XrFrameState frameState, vsg::ref_ptr frameStamp) 52 | { 53 | // Render the scene 54 | auto swapchainI = 0; 55 | auto swapchain = getSwapchain(swapchainI); 56 | uint32_t swapChainImageIndex = 0; 57 | 58 | swapchain->acquireImage(swapChainImageIndex); 59 | XrDuration timeoutNs = 20000000; 60 | auto waitSuccess = swapchain->waitImage(timeoutNs); 61 | 62 | if (waitSuccess) 63 | { 64 | // reset connected ExecuteCommands 65 | for (auto& recordAndSubmitTask : _recordAndSubmitTasks) 66 | { 67 | for (auto& commandGraph : recordAndSubmitTask->commandGraphs) 68 | { 69 | commandGraph->reset(); 70 | if (!commandGraph->children.empty()) 71 | { 72 | // TODO: More reliable way to fetch render graph? Maybe just store a pointer to it if there's no downside? 73 | if (auto renderGraph = commandGraph->children[0].cast()) 74 | { 75 | renderGraph->framebuffer = frames(swapchainI)[swapChainImageIndex].framebuffer; 76 | } 77 | } 78 | } 79 | } 80 | 81 | for (auto& recordAndSubmitTask : _recordAndSubmitTasks) 82 | { 83 | recordAndSubmitTask->submit(frameStamp); 84 | } 85 | 86 | swapchain->releaseImage(); 87 | } 88 | 89 | // Add the composition layer for the frame end info 90 | _compositionLayer.type = XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR; 91 | _compositionLayer.next = nullptr; 92 | _compositionLayer.layerFlags = flags; 93 | _compositionLayer.space = _referenceSpace->getSpace(); 94 | _compositionLayer.eyeVisibility = eyeVisibility; 95 | _compositionLayer.subImage.swapchain = swapchain->getSwapchain(); 96 | auto extent = swapchain->getExtent(); 97 | _compositionLayer.subImage.imageRect = XrRect2Di{ {0, 0}, 98 | {static_cast(extent.width), static_cast(extent.height)} 99 | }; 100 | _compositionLayer.subImage.imageArrayIndex = 0; 101 | _compositionLayer.pose = pose; 102 | _compositionLayer.radius = radius; 103 | 104 | _compositionLayer.centralHorizontalAngle = centralHorizontalAngle; 105 | _compositionLayer.lowerVerticalAngle = lowerVerticalAngle; 106 | _compositionLayer.upperVerticalAngle = upperVerticalAngle; 107 | } 108 | 109 | void KHRCompositionLayerEquirect2::setPose(vsg::dvec3 position, vsg::dquat orientation) 110 | { 111 | pose = Pose(position, orientation).getPose(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/xr/AndroidTraits.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | 24 | namespace vsgvr 25 | { 26 | AndroidTraits::AndroidTraits() {} 27 | 28 | AndroidTraits::~AndroidTraits() {} 29 | } 30 | 31 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/xr/EventHandler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include "Macros.cpp" 28 | 29 | using namespace vsg; 30 | 31 | namespace vsgvr { 32 | 33 | EventHandler::EventHandler() {} 34 | 35 | EventHandler::~EventHandler() {} 36 | 37 | void EventHandler::pollEvents(Instance* instance, Session* session) 38 | { 39 | auto toProcess = 20; 40 | while (toProcess-- > 0) 41 | { 42 | auto event = XrEventDataBuffer(); 43 | event.type = XR_TYPE_EVENT_DATA_BUFFER; 44 | event.next = nullptr; 45 | auto result = xrPollEvent(instance->getInstance(), &event); 46 | 47 | if (result == XR_EVENT_UNAVAILABLE) 48 | { 49 | // Done 50 | break; 51 | } 52 | // TODO: Gracefully handle XR_ERROR_INSTANCE_LOST? 53 | xr_check(result, "xrPollEvent"); 54 | 55 | // https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#events 56 | switch (event.type) 57 | { 58 | case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: 59 | if (instance) instance->onEventInstanceLossPending(*reinterpret_cast(&event)); 60 | break; 61 | case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: 62 | // TODO 63 | break; 64 | case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: 65 | // TODO 66 | break; 67 | case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: 68 | // TODO: event.session - Are multiple sessions possible? Certainly not yet in vsgvr 69 | if (session) session->onEventStateChanged(*reinterpret_cast(&event)); 70 | break; 71 | case XR_TYPE_EVENT_DATA_EVENTS_LOST: 72 | // TODO: Sensible logging? Is this possible if the queue is polled regularly? 73 | // throw Exception({"OpenXR event queue overflow, events lost"}); 74 | break; 75 | default: 76 | break; 77 | } 78 | 79 | } 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/xr/Macros.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | namespace { 23 | [[maybe_unused]] const char* to_string(XrResult result) { 24 | switch (result) { 25 | #define RESULT_CASE(V, _) \ 26 | case V: return #V; 27 | XR_LIST_ENUM_XrResult(RESULT_CASE); 28 | default: return "Unknown"; 29 | } 30 | } 31 | [[maybe_unused]] const char* to_string(XrSessionState result) { 32 | switch (result) { 33 | #define RESULT_CASE(V, _) \ 34 | case V: return #V; 35 | XR_LIST_ENUM_XrSessionState(RESULT_CASE); 36 | default: return "Unknown"; 37 | } 38 | } 39 | [[maybe_unused]] void xr_check(XrResult result, std::string msg = "") { 40 | if (XR_SUCCEEDED(result)) return; 41 | vsgvr::XrException e; 42 | e.message = msg + " (" + to_string(result) + ")"; 43 | e.result = result; 44 | throw e; 45 | } 46 | [[maybe_unused]] PFN_xrVoidFunction xr_pfn(XrInstance instance, std::string name) { 47 | PFN_xrVoidFunction fn = nullptr; 48 | xr_check(xrGetInstanceProcAddr(instance, name.c_str(), &fn), 49 | "Failed to look up function: " + name); 50 | return fn; 51 | } 52 | [[maybe_unused]] PFN_xrVoidFunction xr_pfn_noexcept(XrInstance instance, std::string name) { 53 | PFN_xrVoidFunction fn = nullptr; 54 | auto res = xrGetInstanceProcAddr(instance, name.c_str(), &fn); 55 | if( XR_SUCCEEDED(res) ) return fn; 56 | else return nullptr; 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/xr/Pose.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | namespace vsgvr { 5 | 6 | Pose::Pose(XrPosef pose) 7 | : _pose(pose) 8 | {} 9 | 10 | Pose::Pose(vsg::dvec3 position, vsg::dquat orientation) 11 | { 12 | setPose(position, orientation); 13 | } 14 | 15 | Pose::Pose(vsg::vec3 position, vsg::quat orientation) 16 | { 17 | setPose(position, orientation); 18 | } 19 | 20 | Pose::~Pose() {} 21 | 22 | void Pose::setPose(XrPosef pose) 23 | { 24 | _pose = pose; 25 | } 26 | 27 | void Pose::setPose(vsg::dvec3 position, vsg::dquat orientation) 28 | { 29 | vsg::dmat4 vsgToXr( 30 | 1.0, 0.0, 0.0, 0.0, 31 | 0.0, 0.0, -1.0, 0.0, 32 | 0.0, 1.0, 0.0, 0.0, 33 | 0.0, 0.0, 0.0, 1.0 34 | ); 35 | vsg::vec3 xrp = static_cast(vsgToXr * position); 36 | 37 | // TODO: I'm a little unsure of why w needed to be inverted here - It may be compensating bugs in ViewMatrix or ProjectionMatrix 38 | // IMPORTANT: OpenXR is required to raise an error if quaternion length is >1% away from unit 39 | auto xro = static_cast(vsg::dquat( 40 | orientation.x, 41 | orientation.z, 42 | -orientation.y, 43 | -orientation.w 44 | )); 45 | xro = vsg::normalize(xro); 46 | 47 | _pose = XrPosef{ 48 | XrQuaternionf{xro.x, xro.y, xro.z, xro.w}, 49 | XrVector3f{xrp.x, xrp.y, xrp.z} 50 | }; 51 | } 52 | 53 | void Pose::setPose(vsg::vec3 position, vsg::quat orientation) 54 | { 55 | setPose(static_cast(position), static_cast(orientation)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/xr/ReferenceSpace.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "Macros.cpp" 27 | 28 | #include 29 | 30 | namespace vsgvr { 31 | ReferenceSpace::ReferenceSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType) 32 | { 33 | createSpace(session, referenceSpaceType, XrPosef{ 34 | XrQuaternionf{0.0f, 0.0f, 0.0f, 1.0f}, 35 | XrVector3f{0.0f, 0.0f, 0.0f} 36 | }); 37 | } 38 | ReferenceSpace::ReferenceSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType, vsg::dvec3 position, vsg::dquat orientation) 39 | { 40 | auto pose = Pose(position, orientation).getPose(); 41 | createSpace(session, referenceSpaceType, pose); 42 | } 43 | ReferenceSpace::ReferenceSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType, XrPosef poseInReferenceSpace) 44 | { 45 | createSpace(session, referenceSpaceType, poseInReferenceSpace); 46 | } 47 | ReferenceSpace::~ReferenceSpace() 48 | { 49 | destroySpace(); 50 | } 51 | 52 | XrSpaceLocation ReferenceSpace::locate(XrSpace baseSpace, XrTime time) 53 | { 54 | XrSpaceLocation s; 55 | s.type = XR_TYPE_SPACE_LOCATION; 56 | s.next = nullptr; 57 | xr_check(xrLocateSpace(_space, baseSpace, time, &s)); 58 | return s; 59 | } 60 | 61 | void ReferenceSpace::createSpace(vsg::ref_ptr session, XrReferenceSpaceType referenceSpaceType, XrPosef poseInReferenceSpace) 62 | { 63 | XrReferenceSpaceCreateInfo info; 64 | info.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO; 65 | info.next = nullptr; 66 | info.referenceSpaceType = referenceSpaceType; 67 | info.poseInReferenceSpace = poseInReferenceSpace; 68 | xr_check(xrCreateReferenceSpace(session->getSession(), &info, &_space)); 69 | } 70 | 71 | void ReferenceSpace::destroySpace() 72 | { 73 | if (_space != XR_NULL_HANDLE) 74 | { 75 | xrDestroySpace(_space); 76 | _space = XR_NULL_HANDLE; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/xr/Swapchain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | 24 | #include "Macros.cpp" 25 | 26 | #include 27 | 28 | using namespace vsg; 29 | 30 | namespace vsgvr { 31 | 32 | SwapchainImage::SwapchainImage(VkImage image, Device* device) : 33 | Inherit(image, device) 34 | { 35 | } 36 | 37 | SwapchainImage::~SwapchainImage() 38 | { 39 | for (auto& vd : _vulkanData) 40 | { 41 | vd.deviceMemory = nullptr; 42 | vd.image = VK_NULL_HANDLE; 43 | } 44 | } 45 | 46 | Swapchain::Swapchain(XrSession session, VkFormat swapchainFormat, uint32_t width, uint32_t height, uint32_t sampleCount, vsg::ref_ptr graphicsBinding) 47 | : _swapchainFormat(swapchainFormat) 48 | { 49 | createSwapchain(session, width, height, sampleCount, graphicsBinding); 50 | } 51 | 52 | Swapchain::~Swapchain() 53 | { 54 | destroySwapchain(); 55 | } 56 | 57 | VkImage Swapchain::acquireImage(uint32_t& index) 58 | { 59 | xr_check(xrAcquireSwapchainImage(_swapchain, nullptr, &index), "Failed to acquire image"); 60 | return _images[index]; 61 | } 62 | 63 | bool Swapchain::waitImage(XrDuration timeout) 64 | { 65 | auto info = XrSwapchainImageWaitInfo(); 66 | info.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO; 67 | info.next = nullptr; 68 | info.timeout = timeout; 69 | auto result = xrWaitSwapchainImage(_swapchain, &info); 70 | if (result == XR_TIMEOUT_EXPIRED) 71 | { 72 | return false; 73 | } 74 | xr_check(result, "Failed to wait on image"); 75 | return true; 76 | } 77 | 78 | void Swapchain::releaseImage() 79 | { 80 | auto info = XrSwapchainImageReleaseInfo(); 81 | info.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO; 82 | info.next = nullptr; 83 | xr_check(xrReleaseSwapchainImage(_swapchain, &info), "Failed to release image"); 84 | } 85 | 86 | void Swapchain::createSwapchain(XrSession session, uint32_t width, uint32_t height, uint32_t sampleCount, vsg::ref_ptr graphicsBinding) 87 | { 88 | XrSwapchainUsageFlags usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT; 89 | XrSwapchainCreateFlags createFlags = 0; 90 | 91 | _extent.width = width; 92 | _extent.height = height; 93 | 94 | auto info = XrSwapchainCreateInfo(); 95 | info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO; 96 | info.next = nullptr; 97 | info.createFlags = createFlags; 98 | info.usageFlags = usageFlags; 99 | info.format = _swapchainFormat; 100 | info.sampleCount = sampleCount; 101 | info.width = width; 102 | info.height = height; 103 | info.faceCount = 1; 104 | info.arraySize = 1; 105 | info.mipCount = 1; 106 | 107 | xr_check(xrCreateSwapchain(session, &info, &_swapchain)); 108 | 109 | uint32_t imageCount = 0; 110 | xr_check(xrEnumerateSwapchainImages(_swapchain, 0, &imageCount, nullptr)); 111 | 112 | std::vector images(imageCount, XrSwapchainImageVulkanKHR()); 113 | for (auto& i : images) 114 | { 115 | i.type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; 116 | i.next = nullptr; 117 | } 118 | xr_check(xrEnumerateSwapchainImages(_swapchain, static_cast(images.size()), &imageCount, 119 | reinterpret_cast(images.data()))); 120 | 121 | for (auto& i : images) 122 | { 123 | _images.push_back(i.image); 124 | } 125 | 126 | // Create image views, used by Session::createSwapchain to bind to vsg::Framebuffer 127 | for (std::size_t i = 0; i < _images.size(); ++i) 128 | { 129 | auto imageView = ImageView::create(SwapchainImage::create(_images[i], graphicsBinding->getVsgDevice())); 130 | imageView->viewType = VkImageViewType::VK_IMAGE_VIEW_TYPE_2D; 131 | imageView->format = _swapchainFormat; 132 | imageView->subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 133 | imageView->subresourceRange.baseMipLevel = 0; 134 | imageView->subresourceRange.levelCount = 1; 135 | imageView->subresourceRange.baseArrayLayer = 0; 136 | imageView->subresourceRange.layerCount = 1; 137 | imageView->compile(graphicsBinding->getVsgDevice()); 138 | 139 | _imageViews.push_back(imageView); 140 | } 141 | } 142 | 143 | void Swapchain::destroySwapchain() 144 | { 145 | xrDestroySwapchain(_swapchain); 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /vsgvr/src/vsgvr/xr/Traits.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright(c) 2022 Gareth Francis 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | 24 | namespace vsgvr 25 | { 26 | Traits::Traits() {} 27 | 28 | Traits::~Traits() {} 29 | 30 | void Traits::setApplicationVersion(uint32_t maj, uint32_t min, uint32_t patch) 31 | { 32 | applicationVersion = XR_MAKE_VERSION(maj, min, patch); 33 | } 34 | void Traits::setEngineVersion(uint32_t maj, uint32_t min, uint32_t patch) 35 | { 36 | engineVersion = XR_MAKE_VERSION(maj, min, patch); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /vsgvrConfig.cmake.in: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | 3 | @FIND_DEPENDENCY_OUT@ 4 | 5 | include("${CMAKE_CURRENT_LIST_DIR}/vsgvrTargets.cmake") 6 | --------------------------------------------------------------------------------