Skip to content

Commit

Permalink
ENH: Add support for "OpenXR" XR runtime
Browse files Browse the repository at this point in the history
- Add SlicerVirtualReality_HAS_OPENXR_SUPPORT CMake option

- Add OpenXR-SDK and vtkRenderingOpenXR external projects

- Add OpenXR specialized interactor style class for.

- Add OpenXR specialized interactor class. Thanks to the shared
  `vtkVirtualRealityComplexGestureRecognizer`, there is no duplicated code.

- Add OpenXR specialized interactor style class. Thanks to the shared
  `vtkVirtualRealityViewInteractorStyleDelegate`, there is no duplicated code.

- Update vtkSlicerVirtualRealityLogic::ComputeActionManifestPath support
  for `OpenXR`.

- Update `vtkMRMLVirtualRealityViewNode` adding `OpenXR` to `XRRuntimeType` enum

- Update `qMRMLVirtualRealityView::createRenderWindow` to instantiate `vtkOpenXR*` classes

- Update  `qMRMLVirtualRealityView::currentXRRuntime` to check for OpenXR
  • Loading branch information
jcfr committed Dec 30, 2023
1 parent 111d0c1 commit 240a60a
Show file tree
Hide file tree
Showing 18 changed files with 597 additions and 0 deletions.
41 changes: 41 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ message(STATUS "")
message(STATUS "Setting SlicerVirtualReality_HAS_OPENVR_SUPPORT to ${SlicerVirtualReality_HAS_OPENVR_SUPPORT}${_reason}")
message(STATUS "")

# OpenXR
set(_default ON)
set(_reason)
option(SlicerVirtualReality_HAS_OPENXR_SUPPORT "Build OpenXR XR runtime" ${_default})
mark_as_superbuild(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
message(STATUS "")
message(STATUS "Setting SlicerVirtualReality_HAS_OPENXR_SUPPORT to ${SlicerVirtualReality_HAS_OPENXR_SUPPORT}${_reason}")
message(STATUS "")

#-----------------------------------------------------------------------------
# SuperBuild setup
option(${EXTENSION_NAME}_SUPERBUILD "Build ${EXTENSION_NAME} and the projects it depends on." ON)
Expand Down Expand Up @@ -86,6 +95,12 @@ if(SlicerVirtualReality_HAS_OPENVR_SUPPORT)
set(vtkRenderingOpenVR_DIR \"${vtkRenderingOpenVR_DIR}\")
find_package(vtkRenderingOpenVR REQUIRED)
endif()
set(SlicerVirtualReality_HAS_OPENXR_SUPPORT ${SlicerVirtualReality_HAS_OPENXR_SUPPORT})
if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
set(vtkRenderingOpenXR_DIR \"${vtkRenderingOpenXR_DIR}\")
find_package(vtkRenderingOpenXR REQUIRED)
endif()
##################################################
")
include(${Slicer_EXTENSION_GENERATE_CONFIG})
Expand All @@ -102,13 +117,32 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
COMPONENT RuntimeLibraries
)
endif()

if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
# ${OpenXR_LIBRARY} contains import library which does not have to be installed.
# Instead, the dll must be added to the package.
set(_library "${OpenXR-SDK_LIBRARY_PATHS_LAUNCHER_BUILD}/openxr_loader.dll")
# Since the launcher settings include the placeholder <CMAKE_CFG_INTDIR>, let's
# replace if with the corresponding generator expression.
install(FILES ${_library}
DESTINATION ${Slicer_THIRDPARTY_LIB_DIR}
COMPONENT RuntimeLibraries
)
endif()
else()
if(SlicerVirtualReality_HAS_OPENVR_SUPPORT)
install(FILES ${OpenVR_LIBRARY}
DESTINATION ${Slicer_THIRDPARTY_LIB_DIR}
COMPONENT RuntimeLibraries
)
endif()

if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
install(FILES ${OpenXR_LIBRARY}
DESTINATION ${Slicer_INSTALL_THIRDPARTY_LIB_DIR}
COMPONENT RuntimeLibraries
)
endif()
endif()

#-----------------------------------------------------------------------------
Expand All @@ -126,6 +160,13 @@ if(SlicerVirtualReality_HAS_OPENVR_SUPPORT)
endif()
endif()

if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
list(APPEND EXTENSION_CPACK_INSTALL_CMAKE_PROJECTS "${vtkRenderingOpenXR_DIR};vtkRenderingOpenXR;runtime;/")
if(Slicer_USE_PYTHONQT)
list(APPEND EXTENSION_CPACK_INSTALL_CMAKE_PROJECTS "${vtkRenderingOpenXR_DIR};vtkRenderingOpenXR;python;/")
endif()
endif()

set(${EXTENSION_NAME}_CPACK_INSTALL_CMAKE_PROJECTS "${EXTENSION_CPACK_INSTALL_CMAKE_PROJECTS}" CACHE STRING "List of external projects to install" FORCE)

#-----------------------------------------------------------------------------
Expand Down
113 changes: 113 additions & 0 deletions SuperBuild/External_OpenXR-SDK.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@

set(proj OpenXR-SDK)

set(${proj}_DEPENDENCIES "")

# Include dependent projects if any
ExternalProject_Include_Dependencies(${proj} PROJECT_VAR proj DEPENDS_VAR ${proj}_DEPENDENCIES)

if(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj})
unset(OpenXR_INCLUDE_DIR CACHE)
unset(OpenXR_LIBRARY CACHE)
find_package(OpenXR REQUIRED)
if(NOT DEFINED OpenXR_LIBRARY)
# Since the OpenXRConfig.cmake file provided by OpenXR-SDK does not set OpenXR_LIBRARY, its
# value may be retrieved from the OpenXR::OpenXR target.
# TODO
endif()
endif()

# Sanity checks
if(DEFINED OpenXR_INCLUDE_DIR AND NOT EXISTS ${OpenXR_INCLUDE_DIR})
message(FATAL_ERROR "OpenXR_INCLUDE_DIR variable is defined but corresponds to nonexistent directory")
endif()
if(DEFINED OpenXR_LIBRARY AND NOT EXISTS ${OpenXR_LIBRARY})
message(FATAL_ERROR "OpenXR_LIBRARY variable is defined but corresponds to nonexistent path")
endif()

if((NOT OpenXR_INCLUDE_DIR OR NOT OpenXR_LIBRARY)
AND NOT ${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj})

ExternalProject_SetIfNotDefined(
${SUPERBUILD_TOPLEVEL_PROJECT}_${proj}_GIT_REPOSITORY
"https://github.com/KhronosGroup/OpenXR-SDK.git"
QUIET
)

ExternalProject_SetIfNotDefined(
${SUPERBUILD_TOPLEVEL_PROJECT}_${proj}_GIT_TAG
"release-1.0.26"
QUIET
)

set(EP_SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj})
set(EP_BINARY_DIR ${CMAKE_BINARY_DIR}/${proj}-build)
set(EP_INSTALL_DIR ${CMAKE_BINARY_DIR}/${proj}-install)

ExternalProject_Add(${proj}
${${proj}_EP_ARGS}
GIT_REPOSITORY "${${SUPERBUILD_TOPLEVEL_PROJECT}_${proj}_GIT_REPOSITORY}"
GIT_TAG "${${SUPERBUILD_TOPLEVEL_PROJECT}_${proj}_GIT_TAG}"
SOURCE_DIR ${EP_SOURCE_DIR}
BINARY_DIR ${EP_BINARY_DIR}
INSTALL_DIR ${EP_INSTALL_DIR}
CMAKE_CACHE_ARGS
# Compiler settings
-DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
-DCMAKE_C_FLAGS:STRING=${ep_common_c_flags}
-DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
-DCMAKE_CXX_FLAGS:STRING=${ep_common_cxx_flags}
-DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD}
-DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED}
-DCMAKE_CXX_EXTENSIONS:BOOL=${CMAKE_CXX_EXTENSIONS}
# Options
-DBUILD_TESTING:BOOL=OFF
-DDYNAMIC_LOADER:BOOL=ON
# Install directories
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
${EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS}
DEPENDS
${${proj}_DEPENDENCIES}
)
set(OpenXR_DIR "${EP_INSTALL_DIR}/lib/cmake/openxr")

set(OpenXR_INCLUDE_DIR "${EP_INSTALL_DIR}/include/openxr")

if(WIN32)
set(OpenXR_LIBRARY "${EP_INSTALL_DIR}/lib/openxr_loader.lib")
elseif(APPLE)
set(OpenXR_LIBRARY "${EP_INSTALL_DIR}/lib/libopenxr_loader.dylib")
elseif(UNIX)
set(OpenXR_LIBRARY "${EP_INSTALL_DIR}/lib/libopenxr_loader.so")
endif()

#-----------------------------------------------------------------------------
# Launcher setting specific to build tree

# library paths
set(${proj}_LIBRARY_PATHS_LAUNCHER_BUILD
${EP_BINARY_DIR}/src/loader/<CMAKE_CFG_INTDIR>
)
mark_as_superbuild(
VARS ${proj}_LIBRARY_PATHS_LAUNCHER_BUILD
LABELS "LIBRARY_PATHS_LAUNCHER_BUILD"
)

#-----------------------------------------------------------------------------
# Launcher setting specific to install tree

# NA

else()
ExternalProject_Add_Empty(${proj} DEPENDS ${${proj}_DEPENDS})
endif()

ExternalProject_Message(${proj} "OpenXR_INCLUDE_DIR:${OpenXR_INCLUDE_DIR}")
ExternalProject_Message(${proj} "OpenXR_LIBRARY:${OpenXR_LIBRARY}")

mark_as_superbuild(
VARS
OpenXR_INCLUDE_DIR:PATH
OpenXR_LIBRARY:FILEPATH
)

123 changes: 123 additions & 0 deletions SuperBuild/External_vtkRenderingOpenXR.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#-----------------------------------------------------------------------------
# Build VTK Rendering OpenXR module, pointing it to Slicer's VTK and the OpenXR
# libraries also built by this extension.

set(proj vtkRenderingOpenXR)

# Set dependency list
set(${proj}_DEPENDS
OpenXR-SDK
vtkRenderingVR
)

# Include dependent projects if any
ExternalProject_Include_Dependencies(${proj} PROJECT_VAR proj)

if(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj})
message(FATAL_ERROR "Enabling ${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj} is not supported !")
endif()

# Sanity checks
if(DEFINED ${proj}_DIR AND NOT EXISTS ${${proj}_DIR})
message(FATAL_ERROR "${proj}_DIR [${${proj}_DIR}] variable is defined but corresponds to nonexistent directory")
endif()

if(NOT DEFINED ${proj}_DIR AND NOT ${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj})

set(EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS)
if(VTK_WRAP_PYTHON)
list(APPEND EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS
-DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}
-DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR}
-DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY}
# Required by FindPython3 CMake module used by VTK
-DPython3_ROOT_DIR:PATH=${Python3_ROOT_DIR}
-DPython3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR}
-DPython3_LIBRARY:FILEPATH=${Python3_LIBRARY}
-DPython3_LIBRARY_DEBUG:FILEPATH=${Python3_LIBRARY_DEBUG}
-DPython3_LIBRARY_RELEASE:FILEPATH=${Python3_LIBRARY_RELEASE}
-DPython3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE}
)
endif()

if(NOT EXISTS ${VTKExternalModule_SOURCE_DIR})
message(FATAL_ERROR "VTKExternalModule_SOURCE_DIR [${VTKExternalModule_SOURCE_DIR}] variable is set to a nonexistent directory")
endif()

set(VTK_SOURCE_DIR ${VTK_DIR}/../VTK)
ExternalProject_Message(${proj} "VTK_SOURCE_DIR:${VTK_SOURCE_DIR}")

set(_module_subdir Rendering/OpenXR)
set(_module_name RenderingOpenXR)

set(EP_SOURCE_DIR ${VTK_SOURCE_DIR}/${_module_subdir})
set(EP_BINARY_DIR ${CMAKE_BINARY_DIR}/${proj}-build)

# The "vtk_openxr_actions.json" and "vtk_openxr_binding_*.json" files
# are then installed into "${_manifest_install_dir}/xr_actions/" directory.
set(_openxr_manifest_install_dir ${Slicer_INSTALL_THIRDPARTY_LIB_DIR})

ExternalProject_Add(${proj}
${${proj}_EP_ARGS}
DOWNLOAD_COMMAND ""
SOURCE_DIR ${VTKExternalModule_SOURCE_DIR}
BINARY_DIR ${EP_BINARY_DIR}
INSTALL_COMMAND ""
CMAKE_CACHE_ARGS
# VTKExternalModule
-DVTK_MODULE_NAME:STRING=${_module_name}
-DVTK_MODULE_SOURCE_DIR:PATH=${EP_SOURCE_DIR}
-DVTK_MODULE_CMAKE_MODULE_PATH:PATH=${VTK_SOURCE_DIR}/CMake
-DOpenXR_FIND_PACKAGE_VARS:STRING=OpenXR_INCLUDE_DIR;OpenXR_LIBRARY
# vtkRenderingOpenXR
-DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
-DCMAKE_CXX_FLAGS:STRING=${ep_common_cxx_flags}
-DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
-DCMAKE_C_FLAGS:STRING=${ep_common_c_flags}
-DBUILD_TESTING:BOOL=OFF
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${CMAKE_BINARY_DIR}/${Slicer_THIRDPARTY_BIN_DIR}
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=${CMAKE_BINARY_DIR}/${Slicer_THIRDPARTY_LIB_DIR}
-DCMAKE_INSTALL_BINDIR:STRING=${Slicer_INSTALL_THIRDPARTY_BIN_DIR}
-DCMAKE_INSTALL_LIBDIR:STRING=${Slicer_INSTALL_THIRDPARTY_LIB_DIR}
-DCMAKE_INSTALL_DATAROOTDIR:STRING=${_openxr_manifest_install_dir}
-DCMAKE_MACOSX_RPATH:BOOL=0
# Required to find VTK
-DVTK_DIR:PATH=${VTK_DIR}
# Required to find vtkRenderingVR
-DvtkRenderingVR_DIR:PATH=${vtkRenderingVR_DIR}
# Required to find OpenXR
-DOpenXR_INCLUDE_DIR:PATH=${OpenXR_INCLUDE_DIR}
-DOpenXR_LIBRARY:PATH=${OpenXR_LIBRARY}
${EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS}
DEPENDS
${${proj}_DEPENDS}
)

ExternalProject_AlwaysConfigure(${proj})

set(${proj}_DIR ${EP_BINARY_DIR})

#-----------------------------------------------------------------------------
# Launcher setting specific to build tree

# pythonpath
set(${proj}_PYTHONPATH_LAUNCHER_BUILD
${${proj}_DIR}/${Slicer_INSTALL_THIRDPARTY_LIB_DIR}/${PYTHON_SITE_PACKAGES_SUBDIR}/vtkmodules
)
mark_as_superbuild(
VARS ${proj}_PYTHONPATH_LAUNCHER_BUILD
LABELS "PYTHONPATH_LAUNCHER_BUILD"
)

#-----------------------------------------------------------------------------
# Launcher setting specific to install tree

# NA

else()
ExternalProject_Add_Empty(${proj} DEPENDS ${${proj}_DEPENDS})
endif()

mark_as_superbuild(VARS ${proj}_DIR:PATH)
ExternalProject_Message(${proj} "${proj}_DIR:${${proj}_DIR}")

26 changes: 26 additions & 0 deletions SuperBuildPrerequisites.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ endif()
if(NOT DEFINED SlicerVirtualReality_HAS_OPENVR_SUPPORT)
message(FATAL_ERROR "SlicerVirtualReality_HAS_OPENVR_SUPPORT is not set")
endif()
if(NOT DEFINED SlicerVirtualReality_HAS_OPENXR_SUPPORT)
message(FATAL_ERROR "SlicerVirtualReality_HAS_OPENXR_SUPPORT is not set")
endif()

# Set list of dependencies to ensure the custom application bundling this
# extension does NOT automatically collect the project list and attempt to
Expand All @@ -24,6 +27,11 @@ if(DEFINED Slicer_SOURCE_DIR)
OpenVR
)
endif()
if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
list(APPEND SlicerVirtualReality_EXTERNAL_PROJECT_DEPENDENCIES
OpenXR-SDK
)
endif()
else()
# Extension is build standalone against Slicer itself built
# against VTK without the relevant modules enabled.
Expand All @@ -35,6 +43,11 @@ else()
vtkRenderingOpenVR
)
endif()
if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
list(APPEND SlicerVirtualReality_EXTERNAL_PROJECT_DEPENDENCIES
vtkRenderingOpenXR
)
endif()
endif()
message(STATUS "SlicerVirtualReality_EXTERNAL_PROJECT_DEPENDENCIES:${SlicerVirtualReality_EXTERNAL_PROJECT_DEPENDENCIES}")

Expand All @@ -44,6 +57,7 @@ if(NOT DEFINED Slicer_SOURCE_DIR)
# VTKExternalModule is required to configure these external projects:
# - vtkRenderingVR
# - vtkRenderingOpenVR
# - vtkRenderingOpenXR
include(${SlicerVirtualReality_SOURCE_DIR}/FetchVTKExternalModule.cmake)

else()
Expand All @@ -56,6 +70,12 @@ else()
OpenVR
)
endif()
if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
ExternalProject_Add_Dependencies(VTK
DEPENDS
OpenXR-SDK
)
endif()

# Additional external project options
set(VTK_MODULE_ENABLE_VTK_RenderingVR YES)
Expand All @@ -64,11 +84,17 @@ else()
else()
set(VTK_MODULE_ENABLE_VTK_RenderingOpenVR NO)
endif()
if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
set(VTK_MODULE_ENABLE_VTK_RenderingOpenXR YES)
else()
set(VTK_MODULE_ENABLE_VTK_RenderingOpenXR NO)
endif()

mark_as_superbuild(
VARS
VTK_MODULE_ENABLE_VTK_RenderingVR:STRING
VTK_MODULE_ENABLE_VTK_RenderingOpenVR:STRING
VTK_MODULE_ENABLE_VTK_RenderingOpenXR:STRING
PROJECTS
VTK
)
Expand Down
3 changes: 3 additions & 0 deletions VirtualReality/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ find_package(vtkRenderingVR REQUIRED)
if(SlicerVirtualReality_HAS_OPENVR_SUPPORT)
find_package(vtkRenderingOpenVR REQUIRED)
endif()
if(SlicerVirtualReality_HAS_OPENXR_SUPPORT)
find_package(vtkRenderingOpenXR REQUIRED)
endif()

#-----------------------------------------------------------------------------
add_subdirectory(MRML)
Expand Down
Loading

0 comments on commit 240a60a

Please sign in to comment.