This repository contains the source code for the Godot Oculus Mobile plugin. See the intro documentation for a reference on how to use the plugin.
This is a Godot Android plugin that supports the Oculus Quest 1 & 2 standalone headsets.
The use of this plugin require Godot 3.2.2 or later.
- This project is released under the MIT license.
- Please check the Oculus Mobile SDK license for information about the Oculus Mobile SDK used in this project.
Official binaries can be found in the project releases section.
Instructions for building from source can be found in the Contributions section.
Note:
- Version
2.0.0
(and higher) of the plugin is only supported starting with Godot 3.2.2.- Deployment instructions for version
1.0.0
of the plugin can be found here.
- Deployment instructions for version
- Using Android custom builds is required to use the plugin. The setup instructions can be found here.
In the Godot editor project view:
- Install the Android build template by following these instructions.
- In the
FileSystem
pane, add the plugin binary (.aar
) file and its configuration (.gdap
) file to the Godot project's custom build directory:res://android/plugins
.
When exporting the project apk in Godot, the following Android export options should be set:
Xr Features
Xr Mode
must be set toOculus Mobile VR
.Degrees of Freedom
:- If deploying only on Oculus Quest, this must be set to
6DOF
- If deploying on Oculus Go, or on Oculus Go and Oculus Quest, this must be set to
3DOF and 6DOF
- If deploying only on Oculus Quest, this must be set to
Hand Tracking
: This is only supported on the Oculus Quest- Select
None
if your app doesn't need hand tracking - Select
Optional
if your app can use hand tracking, but doesn't require it (i.e: also works with controllers). - Select
Required
if your app only uses hand tracking.
- Select
Custom Template
Use Custom Build
must be enabled.
Plugins
OVRMobile
must be listed and enabled in thePlugins
section.
Clone the repository and initialise the submodules with git submodule update --init --recursive
.
- Note: When you've pulled a newer version make sure to run
git submodule update --init --recursive
.
- Download the latest version
(Oculus Mobile SDK 23.0 (1.40.0) or higher) of the Oculus Mobile SDK and extract it into the
plugin/libs/ovr_sdk_mobile
directory (create the directory if it doesn't exist).- If you change the default install location, update the
OVR_ROOT_DIR
cmake variable in the theplugin/CMakeLists.txt
build file to point to the Oculus Mobile SDK install location.
- If you change the default install location, update the
- Checkout the godot-cpp repo as a submodule by running the following command:
git submodule update --init --recursive
.- The godot-cpp repo will checkout under the
plugin/libs/godot-cpp
directory.
- The godot-cpp repo will checkout under the
- Navigate to the
plugin/libs/godot-cpp
directory and follow these steps to generate the cpp bindings.
- Download and setup
Android Studio version 4.1 or higher.
- After setup, ensure you have the latest versions by checking the SDK Manager for updates.
- Set the environment variable
ANDROID_HOME
to the Android SDK location. - Follow the instructions here and install version 21.1.6352462 of the NDK.
In the project root directory:
- Run
./gradlew :generatePluginBinary
to generate the plugin binary files. - Once the build successfully completes, the binary files can be found in the
build/outputs/pluginBin
directory.
In the project root directory:
- Run
./gradlew :generateSharedLibs
to generate the plugin shared libraries. - Once the build successfully completes, the shared libraries can be found in the
build/outputs/sharedLibs
directory.
The hand tracking API is still in early state and might change in future updates. It is contained in OvrHandTracking.gdns
. To see an example
on how it can be used check the example setup in samples/demo/godot/addons/godot_ovrmobile/example_scenes/ARVROriginWithHandTracking.gd and the associated scene file.
To test this in the demo replace the ARVROriginWithInitiAndMovement scene reference with the provided ARVROriginWithHandTracking.tscn.
To enable hand tracking, make sure to follow the Deployment/Hand Tracking steps in the Deployment section.
This plugin exposes parts of the Oculus VrApi via GDNative script classes.
Here is an example of how to use these classes inside GDScript:
onready var ovrTrackingTransform = preload("res://addons/godot_ovrmobile/OvrTrackingTransform.gdns").new()
onready var ovrGuardianSystem = preload("res://addons/godot_ovrmobile/OvrGuardianSystem.gdns").new()
func _process(delta):
print("GetTrackingSpace: " , ovrTrackingTransform.get_tracking_space())
print("GetBoundaryVisible: ", ovrGuardianSystem.get_boundary_visible())
print("GetBoundaryOrientedBoundingBox: ", ovrGuardianSystem.get_boundary_oriented_bounding_box())
There is also a OvrUtility GDNative script class that exposes some utility functions to configure the compositor or query information:
onready var ovrUtilities = preload("res://addons/godot_ovrmobile/OvrUtilities.gdns").new()
func do_something():
# Query the current IPD; return value is in m
print("Current IPD is: %.1fmm" % (ovrUtilities.get_ipd() * 1000.0))
# set a color multiply (also useful for fade to black)
ovrUtilities.set_default_layer_color_scale(Color(1.0, 0.3, 0.4, 1.0));
# query controller acceleration/velocities; return value is Vector3
print(ovrUtilities.get_controller_angular_velocity(1)); # parameter is the controller_id (either 1 or 2)
print(ovrUtilities.get_controller_linear_velocity(1));
print(ovrUtilities.get_controller_angular_acceleration(1));
print(ovrUtilities.get_controller_linear_acceleration(1));
# the same is available for the head:
print(ovrUtilities.get_head_angular_velocity());
print(ovrUtilities.get_head_linear_velocity());
print(ovrUtilities.get_head_angular_acceleration());
print(ovrUtilities.get_head_linear_acceleration());
Performance settings are in the OvrPerformance GDNative script class:
onready var ovrPerformance = preload("res://addons/godot_ovrmobile/OvrPerformance.gdns").new()
func change_performance_settings():
# enable the extra latency mode: this gives some performance headroom at the cost
# of one more frame of latency
ovrPerformance.set_extra_latency_mode(1);
# set fixed foveation level
# for details see https://developer.oculus.com/documentation/quest/latest/concepts/mobile-ffr/
ovrPerformance.set_foveation_level(4);
# if you want dynamic foveation make sure to set the maximum desired foveation with the previous function
# before you enable dynamic foveation
ovrPerformance.set_enable_dynamic_foveation(true);
In addition to the official API above there is the experimental OvrVrApiProxy.gdns
class that exposes partially the low level property setters/getters from the VrApi.h.
This API is to be considered temporary and might be removed in future releases of the plugin. If possible it is recommended to use the offical API described above.
The functions inside the API rely on enum values so there is an convenience class OvrVrApiTypes.gd
that contains the enum values.
In the example below you can see a sample usage of the API. For details of the different enum values and query options
please check the VrApi.h file from the oculus mobile sdk.
onready var ovr_vr_api_proxy = preload("res://addons/godot_ovrmobile/OvrVrApiProxy.gdns").new();
onready var ovr_types = preload("res://addons/godot_ovrmobile/OvrVrApiTypes.gd").new();
func test_property_access():
print("Testing vrapi access:")
print("System property:")
print(" vrapi_get_system_property_int(VRAPI_SYS_PROP_DEVICE_TYPE) = ", ovr_vr_api_proxy.vrapi_get_system_property_int(ovr_types.OvrSystemProperty.VRAPI_SYS_PROP_DEVICE_TYPE));
print(" vrapi_get_system_property_int(VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH) = ", ovr_vr_api_proxy.vrapi_get_system_property_int(ovr_types.OvrSystemProperty.VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH));
print("Property:")
print(" vrapi_get_property_int(VRAPI_DEVICE_EMULATION_MODE) = ", ovr_vr_api_proxy.vrapi_get_property_int(ovr_types.OvrProperty.VRAPI_DEVICE_EMULATION_MODE));
print(" vrapi_get_property_int(VRAPI_ACTIVE_INPUT_DEVICE_ID) = ", ovr_vr_api_proxy.vrapi_get_property_int(ovr_types.OvrProperty.VRAPI_ACTIVE_INPUT_DEVICE_ID));
print(" vrapi_get_property_int(VRAPI_FOVEATION_LEVEL) = ", ovr_vr_api_proxy.vrapi_get_property_int(ovr_types.OvrProperty.VRAPI_FOVEATION_LEVEL));
ovr_vr_api_proxy.vrapi_set_property_int(ovr_types.OvrProperty.VRAPI_FOVEATION_LEVEL, 3);
print(" vrapi_get_property_int(VRAPI_FOVEATION_LEVEL) = ", ovr_vr_api_proxy.vrapi_get_property_int(ovr_types.OvrProperty.VRAPI_FOVEATION_LEVEL));
print("System Status:")
print(" vrapi_get_system_status_int(VRAPI_SYS_STATUS_MOUNTED) = ", ovr_vr_api_proxy.vrapi_get_system_status_int(ovr_types.OvrSystemStatus.VRAPI_SYS_STATUS_MOUNTED));
print(" vrapi_get_system_status_int(VRAPI_SYS_STATUS_RENDER_LATENCY_MILLISECONDS) = ", ovr_vr_api_proxy.vrapi_get_system_status_int(ovr_types.OvrSystemStatus.VRAPI_SYS_STATUS_RENDER_LATENCY_MILLISECONDS));
print(" vrapi_get_system_status_int(VRAPI_SYS_STATUS_FRONT_BUFFER_SRGB) = ", ovr_vr_api_proxy.vrapi_get_system_status_int(ovr_types.OvrSystemStatus.VRAPI_SYS_STATUS_FRONT_BUFFER_SRGB));