From 69f3c76b28bda6d0f214b8a6d1130e14bed6ad80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Thu, 9 May 2024 15:05:48 +0200 Subject: [PATCH] feat: add visionOS support --- Apps/CMakeLists.txt | 2 +- Apps/Playground/CMakeLists.txt | 46 +++++++- Apps/Playground/visionOS/App.swift | 100 ++++++++++++++++ Apps/Playground/visionOS/Info.plist | 33 ++++++ Apps/Playground/visionOS/LibNativeBridge.cpp | 110 ++++++++++++++++++ Apps/Playground/visionOS/LibNativeBridge.hpp | 25 ++++ Apps/UnitTests/CMakeLists.txt | 3 +- BUILDING.md | 38 ++++++ CMakeLists.txt | 21 +++- .../visionOS/Babylon/Graphics/Platform.h | 9 ++ .../Include/Shared/Babylon/Graphics/Device.h | 8 ++ Core/Graphics/Source/DeviceImpl.cpp | 1 + Core/Graphics/Source/DeviceImpl_visionOS.mm | 20 ++++ Dependencies/CMakeLists.txt | 6 +- Dependencies/xr/CMakeLists.txt | 17 ++- .../ARKit_visionOS/Include/IXrContextARKit.h | 10 ++ Dependencies/xr/Source/ARKit_visionOS/XR.mm | 15 +++ Plugins/CMakeLists.txt | 2 +- 18 files changed, 452 insertions(+), 14 deletions(-) create mode 100644 Apps/Playground/visionOS/App.swift create mode 100644 Apps/Playground/visionOS/Info.plist create mode 100644 Apps/Playground/visionOS/LibNativeBridge.cpp create mode 100644 Apps/Playground/visionOS/LibNativeBridge.hpp create mode 100644 Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h create mode 100644 Core/Graphics/Source/DeviceImpl_visionOS.mm create mode 100644 Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h create mode 100644 Dependencies/xr/Source/ARKit_visionOS/XR.mm diff --git a/Apps/CMakeLists.txt b/Apps/CMakeLists.txt index 0e7ade406..d4013e0e7 100644 --- a/Apps/CMakeLists.txt +++ b/Apps/CMakeLists.txt @@ -2,7 +2,7 @@ if(NOT ANDROID) add_subdirectory(Playground) endif() -if((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS) OR (UNIX AND NOT ANDROID)) +if((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS AND NOT VISIONOS) OR (UNIX AND NOT ANDROID)) add_subdirectory(UnitTests) endif() diff --git a/Apps/Playground/CMakeLists.txt b/Apps/Playground/CMakeLists.txt index ff4348518..493edcb3f 100644 --- a/Apps/Playground/CMakeLists.txt +++ b/Apps/Playground/CMakeLists.txt @@ -35,9 +35,24 @@ if(APPLE) "iOS/LibNativeBridge.mm") set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE NativeCamera) + elseif(VISIONOS) + set(PLIST_FILE + "${CMAKE_CURRENT_LIST_DIR}/visionOS/Info.plist") + set(RESOURCE_FILES ${SCRIPTS}) + set(SOURCES + ${SOURCES} + "visionOS/App.swift" + "visionOS/LibNativeBridge.cpp" + "visionOS/LibNativeBridge.hpp" + ) + set(ADDITIONAL_LIBRARIES PRIVATE NativeXr) + set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") + set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") else() set(PLIST_FILE "${CMAKE_CURRENT_LIST_DIR}/macOS/Info.plist") set(STORYBOARD "${CMAKE_CURRENT_LIST_DIR}/macOS/Base.lproj/Main.storyboard") + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE NativeCamera) set(RESOURCE_FILES ${STORYBOARD}) set(SOURCES ${SOURCES} @@ -49,9 +64,7 @@ if(APPLE) set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/ReferenceImages") endif() - set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} - PRIVATE ${JAVASCRIPTCORE_LIBRARY} - PRIVATE NativeCamera) + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE ${JAVASCRIPTCORE_LIBRARY}) set(RESOURCE_FILES ${STORYBOARD}) elseif(UNIX) set(SOURCES @@ -162,6 +175,30 @@ if(APPLE) set(CMAKE_Swift_COMPILER_FORCED TRUE) set(CMAKE_Swift_LANGUAGE_VERSION 4.0) enable_language(Swift) + elseif(VISIONOS) + set_target_properties(Playground PROPERTIES + MACOSX_BUNDLE true + MACOSX_BUNDLE_INFO_PLIST "${PLIST_FILE}" + XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES + RESOURCE "${RESOURCE_FILES}" + + XCODE_ATTRIBUTE_XROS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.BabylonNative.Playground.visionOS" + + XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" + XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/visionOS/LibNativeBridge.hpp" + XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks" + XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES YES + XCODE_ATTRIBUTE_SWIFT_OBJC_INTEROP_MODE "objcxx" + + # CMake seems to add a custom flag "-Wno-unknown-pragmas" to the Swift compiler. That flag is used for Clang, + # So we need to make sure we override it with nothing here in order to compile Swift. + XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS "") + + # Swift support + set(CMAKE_Swift_COMPILER_FORCED TRUE) + set(CMAKE_Swift_LANGUAGE_VERSION 5.0) + enable_language(Swift) else() target_link_libraries(Playground PUBLIC "-framework MetalKit") @@ -205,3 +242,6 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${REFERENCE_IMAGES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SCRIPTS}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES}) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Playground) + +set_property(TARGET Playground PROPERTY XCODE_GENERATE_SCHEME YES) +set_property(TARGET Playground PROPERTY XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED YES) diff --git a/Apps/Playground/visionOS/App.swift b/Apps/Playground/visionOS/App.swift new file mode 100644 index 000000000..d39edfe99 --- /dev/null +++ b/Apps/Playground/visionOS/App.swift @@ -0,0 +1,100 @@ +import SwiftUI +import CompositorServices + +struct ContentStageConfiguration: CompositorLayerConfiguration { + func makeConfiguration(capabilities: LayerRenderer.Capabilities, configuration: inout LayerRenderer.Configuration) { + configuration.depthFormat = .depth32Float + configuration.colorFormat = .bgra8Unorm_srgb + + let foveationEnabled = capabilities.supportsFoveation + configuration.isFoveationEnabled = foveationEnabled + + let options: LayerRenderer.Capabilities.SupportedLayoutsOptions = foveationEnabled ? [.foveationEnabled] : [] + let supportedLayouts = capabilities.supportedLayouts(options: options) + + configuration.layout = supportedLayouts.contains(.layered) ? .layered : .dedicated + } +} + +class Renderer { + let layerRenderer: LayerRenderer + var libNativeBridge: LibNativeBridge + + init(_ layerRenderer: LayerRenderer) { + self.layerRenderer = layerRenderer + self.libNativeBridge = LibNativeBridge(layerRenderer) + } + + func startRenderLoop() { + let renderThread = Thread { + self.renderLoop() + } + renderThread.name = "Render Thread" + renderThread.start() + } + + + func renderLoop() { + while true { + if layerRenderer.state == .invalidated { + print("Layer is invalidated") + + libNativeBridge.shutdown() + return + } else if layerRenderer.state == .paused { + layerRenderer.waitUntilRunning() + continue + } else { + autoreleasepool { + libNativeBridge.initialize() + libNativeBridge.render() + } + } + } + } +} + + +@main +struct ExampleApp: App { + @State private var showImmersiveSpace = false + @State private var immersiveSpaceIsShown = false + + @Environment(\.openImmersiveSpace) var openImmersiveSpace + @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace + + var body: some Scene { + WindowGroup { + VStack { + Toggle("Show Immersive Space", isOn: $showImmersiveSpace) + .toggleStyle(.button) + .padding(.top, 50) + } + .onChange(of: showImmersiveSpace) { _, newValue in + Task { + if newValue { + switch await openImmersiveSpace(id: "ImmersiveSpace") { + case .opened: + immersiveSpaceIsShown = true + case .error, .userCancelled: + fallthrough + @unknown default: + immersiveSpaceIsShown = false + showImmersiveSpace = false + } + } else if immersiveSpaceIsShown { + await dismissImmersiveSpace() + immersiveSpaceIsShown = false + } + } + } + + } + ImmersiveSpace(id: "ImmersiveSpace") { + CompositorLayer(configuration: ContentStageConfiguration()) { layerRenderer in + let renderer = Renderer(layerRenderer) + renderer.startRenderLoop() + } + }.immersionStyle(selection: .constant(.mixed), in: .mixed, .full) + } +} diff --git a/Apps/Playground/visionOS/Info.plist b/Apps/Playground/visionOS/Info.plist new file mode 100644 index 000000000..1f9bad276 --- /dev/null +++ b/Apps/Playground/visionOS/Info.plist @@ -0,0 +1,33 @@ + + + + + NSPhotoLibraryAddUsageDescription + Need photo library permission for debug code to save photo captures + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UIApplicationSceneManifest + + UIApplicationPreferredDefaultSceneSessionRole + UIWindowSceneSessionRoleApplication + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + + + diff --git a/Apps/Playground/visionOS/LibNativeBridge.cpp b/Apps/Playground/visionOS/LibNativeBridge.cpp new file mode 100644 index 000000000..77ab114cd --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.cpp @@ -0,0 +1,110 @@ +#import "LibNativeBridge.hpp" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +std::optional device{}; +std::optional update{}; +std::optional runtime{}; +std::optional nativeCanvas{}; +std::optional nativeXr{}; +Babylon::Plugins::NativeInput* nativeInput{}; +bool isXrActive{}; + + +bool LibNativeBridge::initialize() { + if (m_initialized) { + return true; + } + + Babylon::Graphics::Configuration graphicsConfig{}; + graphicsConfig.Window = m_layerRenderer; + // Pass in visionOS default widht and height. +#if TARGET_OS_SIMULATOR + graphicsConfig.Width = static_cast(2732); + graphicsConfig.Height = static_cast(2048); +#else + graphicsConfig.Width = static_cast(1920); + graphicsConfig.Height = static_cast(1824); +#endif + + device.emplace(graphicsConfig); + update.emplace(device->GetUpdate("update")); + + device->StartRenderingCurrentFrame(); + update->Start(); + + runtime.emplace(); + + runtime->Dispatch([](Napi::Env env) + { + device->AddToJavaScript(env); + + Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) { + NSLog(@"%s", message); + }); + + nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env)); + + Babylon::Polyfills::Window::Initialize(env); + + Babylon::Polyfills::XMLHttpRequest::Initialize(env); + + Babylon::Plugins::NativeEngine::Initialize(env); + + Babylon::Plugins::NativeOptimizations::Initialize(env); +// nativeXr.emplace(Babylon::Plugins::NativeXr::Initialize(env)); +// nativeXr->UpdateWindow((__bridge void*)m_layerRenderer); + + nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env); + }); + + Babylon::ScriptLoader loader{ *runtime }; + loader.LoadScript("app:///Scripts/ammo.js"); + loader.LoadScript("app:///Scripts/recast.js"); + loader.LoadScript("app:///Scripts/babylon.max.js"); + loader.LoadScript("app:///Scripts/babylonjs.loaders.js"); + loader.LoadScript("app:///Scripts/babylonjs.materials.js"); + loader.LoadScript("app:///Scripts/babylon.gui.js"); + loader.LoadScript("app:///Scripts/experience.js"); + m_initialized = true; + + return true; +} + +void LibNativeBridge::render() { + if (device && m_initialized) + { + update->Finish(); + device->FinishRenderingCurrentFrame(); + device->StartRenderingCurrentFrame(); + update->Start(); + } +} + +void LibNativeBridge::shutdown() { + if (!m_initialized) { + return; + } + + if (device) + { + update->Finish(); + device->FinishRenderingCurrentFrame(); + } + + nativeInput = {}; + nativeCanvas.reset(); + runtime.reset(); + update.reset(); + device.reset(); + m_initialized = false; +} diff --git a/Apps/Playground/visionOS/LibNativeBridge.hpp b/Apps/Playground/visionOS/LibNativeBridge.hpp new file mode 100644 index 000000000..c1d544175 --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.hpp @@ -0,0 +1,25 @@ +#ifndef BgfxAdapter_hpp +#define BgfxAdapter_hpp + +#include +#include + +class LibNativeBridge { +private: + bool m_initialized = false; + cp_layer_renderer_t m_layerRenderer = NULL; + +public: + LibNativeBridge(cp_layer_renderer_t layerRenderer) : m_layerRenderer(layerRenderer) { + } + + ~LibNativeBridge() { + shutdown(); + } + + bool initialize(void); + void shutdown(void); + void render(void); +}; + +#endif /* BgfxAdapter_hpp */ diff --git a/Apps/UnitTests/CMakeLists.txt b/Apps/UnitTests/CMakeLists.txt index 2f981dff2..7aa3a5679 100644 --- a/Apps/UnitTests/CMakeLists.txt +++ b/Apps/UnitTests/CMakeLists.txt @@ -60,4 +60,5 @@ endforeach() set_property(TARGET UnitTests PROPERTY FOLDER Apps) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES} ${SCRIPTS}) -source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/../node_modules PREFIX node_modules FILES ${EXTERNAL_SCRIPTS}) \ No newline at end of file +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/../node_modules PREFIX node_modules FILES ${EXTERNAL_SCRIPTS}) +set_property(TARGET UnitTests PROPERTY XCODE_GENERATE_SCHEME YES) diff --git a/BUILDING.md b/BUILDING.md index b9840ed6f..b086e7498 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -192,6 +192,44 @@ demo app, click on the project selector and find `Playground` in the list of pos selections. The `Play` button will subsequently allow you to build, run, and debug the selected Babylon Native demo app. +## **Building on macOS, Targeting visionOS** + +_Follow the steps from [All Development Platforms](#all-development-platforms) before proceeding._ + +**Required Tools:** [Xcode 15](https://developer.apple.com/xcode/) or newer, +[Python 3.0](https://www.python.org/) or newer (required by dependencies) + +For macOS development, CMake will generate a Makefile by default. It may be possible +to build Babylon Native for macOS using this approach, but only the Xcode method is +supported at present. To generate an Xcode project using CMake, you must specify the +correct build system generator for CMake to use. Additionally, you must tell CMake +what toolchain to use, which provides additional information about how to generate an +visionOS Xcode project correctly. Run the following command from the repository root: + +``` +cmake -B build/visionOS -G Xcode -D VISIONOS=ON +``` + +To enable bitcode support, add this option to the cmake command line parameters: + +``` +-D ENABLE_BITCODE=ON +``` + +CMake will generate a new `BabylonNative.xcodeproj` file in the specified build folder. +Open the project by double-clicking on it in Finder or by entering the following command: + +``` +open build/visionOS/BabylonNative.xcodeproj +``` + +To select which project to build with Xcode, select the correct project name in the +menu to the right of the greyed-out `Stop` button adjacent to the `Play` button in +the top-left corner of the Xcode window. For example, to build and run the Playground +demo app, click on the project selector and find `Playground` in the list of possible +selections. The `Play` button will subsequently allow you to build, run, and debug +the selected Babylon Native demo app. + ## **Building on Windows, Targeting Android** _Follow the steps from [All Development Platforms](#all-development-platforms) before proceeding._ diff --git a/CMakeLists.txt b/CMakeLists.txt index b1cd1915c..14adf3bfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ FetchContent_Declare(base-n GIT_REPOSITORY https://github.com/azawadzki/base-n.git GIT_TAG 7573e77c0b9b0e8a5fb63d96dbde212c921993b4) FetchContent_Declare(bgfx.cmake - GIT_REPOSITORY https://github.com/BabylonJS/bgfx.cmake.git - GIT_TAG 345e3e28a9912983fc64d1dcb4da22a445afe3fd) + GIT_REPOSITORY https://github.com/okwasniewski/bgfx.cmake + GIT_TAG cda4bfa23342) FetchContent_Declare(CMakeExtensions GIT_REPOSITORY https://github.com/BabylonJS/CMakeExtensions.git GIT_TAG ea28b7689530bfdc4905806f27ecf7e8ed4b5419) @@ -34,7 +34,7 @@ FetchContent_Declare(googletest URL "https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz") FetchContent_Declare(ios-cmake GIT_REPOSITORY https://github.com/leetal/ios-cmake.git - GIT_TAG 4.4.1) + GIT_TAG a52c591bc9056f3ae20a461d16fdd73ab4325be7) FetchContent_Declare(JsRuntimeHost GIT_REPOSITORY https://github.com/BabylonJS/JsRuntimeHost.git GIT_TAG 9ccb9477a97501525f3f9ca0e00e6971934037ec) @@ -51,6 +51,15 @@ FetchContent_Declare(SPIRV-Cross FetchContent_MakeAvailable(CMakeExtensions) + +if(VISIONOS) + FetchContent_MakeAvailable_With_Message(ios-cmake) + set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") + set(PLATFORM "VISIONOSCOMBINED" CACHE STRING "") + set(DEPLOYMENT_TARGET "1.0" CACHE STRING "") + set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") +endif() + if(IOS) FetchContent_MakeAvailable_With_Message(ios-cmake) set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") @@ -59,6 +68,7 @@ if(IOS) set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") endif() + project(BabylonNative) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -98,6 +108,8 @@ if(ANDROID) set(BABYLON_NATIVE_PLATFORM "Android") elseif(IOS) set(BABYLON_NATIVE_PLATFORM "iOS") +elseif (VISIONOS) + set(BABYLON_NATIVE_PLATFORM "visionOS") elseif(APPLE) set(BABYLON_NATIVE_PLATFORM "macOS") elseif(WINDOWS_STORE) @@ -141,6 +153,9 @@ if(MSVC) # https://gitlab.kitware.com/cmake/cmake/-/issues/18837 add_compile_options(/Zc:__cplusplus) + # https://devblogs.microsoft.com/cppblog/announcing-full-support-for-a-c-c-conformant-preprocessor-in-msvc/ + add_compile_options(/Zc:preprocessor) + # default to /W3 add_compile_options(/W3) endif() diff --git a/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h new file mode 100644 index 000000000..2592b6201 --- /dev/null +++ b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h @@ -0,0 +1,9 @@ +#pragma once + +#import + + +namespace Babylon::Graphics +{ + using WindowT = cp_layer_renderer_t; +} diff --git a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h index 9a42719c1..cc0de0ef9 100644 --- a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h +++ b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h @@ -4,6 +4,10 @@ #include #include +#if TARGET_OS_VISION +#include +#endif + #include #include @@ -28,6 +32,10 @@ namespace Babylon::Graphics // When enabled, back buffer will be premultiplied with alpha value. bool AlphaPremultiplied{}; + +#if TARGET_OS_VISION + ar_world_tracking_provider_t WorldTracking; +#endif }; class Device; diff --git a/Core/Graphics/Source/DeviceImpl.cpp b/Core/Graphics/Source/DeviceImpl.cpp index 1a21f3903..c9f6d6e3f 100644 --- a/Core/Graphics/Source/DeviceImpl.cpp +++ b/Core/Graphics/Source/DeviceImpl.cpp @@ -44,6 +44,7 @@ namespace Babylon::Graphics init.callback = &m_bgfxCallback; init.platformData.context = config.Device; + UpdateWindow(config.Window); UpdateSize(config.Width, config.Height); UpdateMSAA(config.MSAASamples); diff --git a/Core/Graphics/Source/DeviceImpl_visionOS.mm b/Core/Graphics/Source/DeviceImpl_visionOS.mm new file mode 100644 index 000000000..2f2fdae5f --- /dev/null +++ b/Core/Graphics/Source/DeviceImpl_visionOS.mm @@ -0,0 +1,20 @@ +#include +#include "DeviceImpl.h" + +namespace Babylon::Graphics +{ + void DeviceImpl::ConfigureBgfxPlatformData(bgfx::PlatformData& pd, WindowT window) + { + pd.nwh = window; + } + + void DeviceImpl::ConfigureBgfxRenderType(bgfx::PlatformData& /*pd*/, bgfx::RendererType::Enum& /*renderType*/) + { + } + + float DeviceImpl::GetDevicePixelRatio(WindowT window) + { + BX_UNUSED(window); + return 2.0; + } +} diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt index 47cee4242..27a8ebed2 100644 --- a/Dependencies/CMakeLists.txt +++ b/Dependencies/CMakeLists.txt @@ -106,7 +106,7 @@ set_property(TARGET SPIRV PROPERTY FOLDER Dependencies/glslang) # -------------------------------------------------- # googletest # -------------------------------------------------- -if(BABYLON_NATIVE_BUILD_APPS AND (WIN32 OR (APPLE AND NOT IOS) OR (UNIX AND NOT ANDROID))) +if(BABYLON_NATIVE_BUILD_APPS AND (WIN32 OR (APPLE AND NOT IOS AND NOT VISIONOS) OR (UNIX AND NOT ANDROID))) if(WIN32) # For Windows: Prevent overriding the parent project's compiler/linker settings # Default build type for my test projects are /MDd (MultiThreaded DLL) but GTests default to /MTd (MultiTreaded) @@ -186,8 +186,8 @@ disable_warnings(MachineIndependent) # -------------------------------------------------- # xr # -------------------------------------------------- -# Currently supported on Windows via OpenXR, Android via ARCore, and iOS via ARKit. -if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS)) +# Currently supported on Windows via OpenXR, Android via ARCore, iOS and visionOS via ARKit. +if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS OR VISIONOS)) add_subdirectory(xr) set_property(TARGET xr PROPERTY FOLDER Dependencies/xr) warnings_as_errors(xr) diff --git a/Dependencies/xr/CMakeLists.txt b/Dependencies/xr/CMakeLists.txt index 593b5043d..66d1fafae 100644 --- a/Dependencies/xr/CMakeLists.txt +++ b/Dependencies/xr/CMakeLists.txt @@ -10,7 +10,7 @@ FetchContent_Declare(CMakeExtensions GIT_TAG ea28b7689530bfdc4905806f27ecf7e8ed4b5419) FetchContent_Declare(ios-cmake GIT_REPOSITORY https://github.com/leetal/ios-cmake.git - GIT_TAG 4.4.1) + GIT_TAG a52c591bc9056f3ae20a461d16fdd73ab4325be7) # -------------------------------------------------- FetchContent_MakeAvailable(CMakeExtensions) @@ -22,6 +22,15 @@ if(IOS) set(DEPLOYMENT_TARGET "13" CACHE STRING "") endif() +if(VISIONOS) + FetchContent_MakeAvailable_With_Message(ios-cmake) + set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") + set(PLATFORM "VISIONOSCOMBINED" CACHE STRING "") + set(DEPLOYMENT_TARGET "1.0" CACHE STRING "") + set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") +endif() + + project(xr) # Avoid picking up system installed jsoncpp in favor of source distributed with openxr_loader project @@ -47,6 +56,10 @@ elseif (IOS) set(SOURCES ${SOURCES} "Source/ARKit/Include/IXrContextARKit.h" "Source/ARKit/XR.mm") +elseif (VISIONOS) + set(SOURCES ${SOURCES} + "Source/ARKit_visionOS/Include/IXrContextARKit.h" + "Source/ARKit_visionOS/XR.mm") else() set(SOURCES ${SOURCES} "Source/OpenXR/XR.cpp") @@ -91,7 +104,7 @@ if (ANDROID) set_target_properties(glm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${arcore-android-sdk_SOURCE_DIR}/libraries/glm) target_link_libraries(xr PRIVATE glm arcore AndroidExtensions) -elseif (IOS) +elseif (IOS OR VISIONOS) target_link_libraries(xr PRIVATE "-framework ARKit") else() if(WIN32) diff --git a/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h b/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h new file mode 100644 index 000000000..a3d2ffecd --- /dev/null +++ b/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h @@ -0,0 +1,10 @@ + +#pragma once + +#include + +typedef struct IXrContextARKit +{ + virtual bool IsInitialized() const = 0; + virtual ar_session_t XrSession() const = 0; +} IXrContextARKit; diff --git a/Dependencies/xr/Source/ARKit_visionOS/XR.mm b/Dependencies/xr/Source/ARKit_visionOS/XR.mm new file mode 100644 index 000000000..b442beb45 --- /dev/null +++ b/Dependencies/xr/Source/ARKit_visionOS/XR.mm @@ -0,0 +1,15 @@ +#import +#import + +#import +#import +#import + +#import "Include/IXrContextARKit.h" + + +// TODO: Implement the visionOS ARKit api +namespace xr { +struct System::Session::Impl { +}; +} diff --git a/Plugins/CMakeLists.txt b/Plugins/CMakeLists.txt index 89d8982b2..0f216f16c 100644 --- a/Plugins/CMakeLists.txt +++ b/Plugins/CMakeLists.txt @@ -30,6 +30,6 @@ if(BABYLON_NATIVE_PLUGIN_TESTUTILS) add_subdirectory(TestUtils) endif() -if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS)) +if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS OR VISIONOS)) add_subdirectory(NativeXr) endif()