Skip to content

Commit

Permalink
Add support for the Android XR OpenXR vendor (including hybrid app su…
Browse files Browse the repository at this point in the history
…pport)
  • Loading branch information
m4gr3d committed Feb 11, 2025
1 parent 39d91be commit a4852c9
Show file tree
Hide file tree
Showing 8 changed files with 482 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/make_rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
STYLES: Dict[str, str] = {}

SKIP_CLASSES: List[str] = [
"AndroidEditorExportPlugin",
"AndroidEditorPlugin",
"KhronosEditorExportPlugin",
"KhronosEditorPlugin",
"LynxEditorPlugin",
Expand Down
19 changes: 19 additions & 0 deletions plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ android {

flavorDimensions = ["vendor"]
productFlavors {
android {
dimension "vendor"
ndk {
//noinspection ChromeOsAbiSupport
abiFilters 'arm64-v8a', 'x86_64'
}
}
khronos {
dimension "vendor"
ndk {
Expand Down Expand Up @@ -104,6 +111,13 @@ android {
debug.jniLibs.srcDirs += ['src/main/libs/debug/arm64-v8a']
release.jniLibs.srcDirs += ['src/main/libs/release/arm64-v8a']

android.jniLibs.srcDirs += [
"${khronosOpenxrLoaderTargetDir}/arm64-v8a",
"${khronosOpenxrLoaderTargetDir}/x86_64",
]
androidDebug.jniLibs.srcDirs += ['src/main/libs/debug/x86_64']
androidRelease.jniLibs.srcDirs += ['src/main/libs/release/x86_64']

khronos.jniLibs.srcDirs += [
"${khronosOpenxrLoaderTargetDir}/arm64-v8a",
"${khronosOpenxrLoaderTargetDir}/x86_64",
Expand Down Expand Up @@ -140,6 +154,11 @@ android {
}

publishing {
singleVariant("androidRelease") {
withSourcesJar()
withJavadocJar()
}

singleVariant("khronosRelease") {
withSourcesJar()
withJavadocJar()
Expand Down
24 changes: 24 additions & 0 deletions plugin/src/android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Permissions needed by OpenXR -->
<uses-permission android:name="org.khronos.openxr.permission.OPENXR" />
<uses-permission android:name="org.khronos.openxr.permission.OPENXR_SYSTEM" />

<queries>
<intent>
<action android:name="org.khronos.openxr.OpenXRRuntimeService"/>
</intent>
<provider android:authorities="org.khronos.openxr.runtime_broker;org.khronos.openxr.system_runtime_broker" />
</queries>

<application>
<meta-data
android:name="org.godotengine.plugin.v2.GodotOpenXRAndroid"
android:value="org.godotengine.openxr.vendors.android.GodotOpenXRAndroid" />

<meta-data android:name="org.godotengine.plugin.v2.GodotOpenXRHybridAppInternal"
android:value="org.godotengine.openxr.vendors.GodotOpenXRHybridAppInternal" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**************************************************************************/
/* GodotOpenXRAndroid.kt */
/**************************************************************************/
/* This file is part of: */
/* GODOT XR */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

package org.godotengine.openxr.vendors.android

import org.godotengine.godot.Godot
import org.godotengine.godot.utils.PermissionsUtil
import org.godotengine.openxr.vendors.GodotOpenXR

/**
* Godot OpenXR plugin for the Android XR platform.
*/
class GodotOpenXRAndroid(godot: Godot?) : GodotOpenXR(godot) {
companion object {
/**
* Representing the user's eye pose and orientation, for the purposes of avatars
*/
private const val EYE_TRACKING_PERMISSION = "android.permission.EYE_TRACKING"

/**
* Eye gaze input and interactions
*/
private const val EYE_TRACKING_FINE_PERMISSION = "android.permission.EYE_TRACKING_FINE"

/**
* Tracking and rendering facial expressions
*/
private const val FACE_TRACKING_PERMISSION = "android.permission.FACE_TRACKING"

/**
* Tracking hand joint poses and angular and linear velocities; Using a mesh representation of the user's hands
*/
private const val HAND_TRACKING_PERMISSION = "android.permission.HAND_TRACKING"

/**
* - Light estimation
* - projecting passthrough onto mesh surfaces
* - performing raycasts against trackables in the environment
* - plane tracking
* - object tracking
* - working with depth for occlusion and hit testing
* - persistent anchors
*/
private const val SCENE_UNDERSTANDING_PERMISSION = "android.permission.SCENE_UNDERSTANDING"

private val ANDROID_XR_PERMISSIONS_LIST = listOf(
EYE_TRACKING_PERMISSION,
EYE_TRACKING_FINE_PERMISSION,
FACE_TRACKING_PERMISSION,
HAND_TRACKING_PERMISSION,
SCENE_UNDERSTANDING_PERMISSION,
)
}
override fun getPluginName() = "GodotOpenXRAndroid"

override fun getPluginPermissionsToEnable(): MutableList<String> {
val permissionsToEnable = super.getPluginPermissionsToEnable()

// Go through the list of permissions, and request the ones that are included in the
// manifest.
for (permission in ANDROID_XR_PERMISSIONS_LIST) {
if (PermissionsUtil.hasManifestPermission(activity, permission)) {
permissionsToEnable.add(permission)
}
}
return permissionsToEnable
}

override fun supportsFeature(featureTag: String): Boolean {
if ("PERMISSION_XR_EXT_eye_gaze_interaction" == featureTag) {
val grantedPermissions = godot?.getGrantedPermissions()
if (grantedPermissions != null) {
for (permission in grantedPermissions) {
if (EYE_TRACKING_FINE_PERMISSION == permission) {
return true
}
}
}
}
return false
}
}
Loading

0 comments on commit a4852c9

Please sign in to comment.