Compare commits

...

26 commits

Author SHA1 Message Date
Simon
c9922b1d94 Proper External SDCARD access
No need to use scoped storage
2024-05-06 19:49:08 +01:00
Simon
cf5f737f53 Various version upgrades
Gradle 8
API level 32
Using Scoped Storage
NDK version 25
2024-05-01 22:40:39 +01:00
Simon
6832052d78 Update version number to latest release 2023-05-10 21:45:13 +01:00
Simon
54c38e489f Ensure screen layer appears in front of player 2023-05-10 21:21:12 +01:00
Simon
1d7aecfa26 Fix crash on quest firmware v53 2023-04-28 19:47:55 +01:00
Simon
e8a6928ce9 Version update 2023-02-05 22:56:25 +00:00
Simon
4ef27a7d6d Gradle changes to support building without dependency on the Meta OpenXR SDK package 2023-02-05 22:56:11 +00:00
Simon
732bfd13ea Update TBXR_Common.c 2023-02-05 19:44:11 +00:00
Simon
a4c79755e9 Update version number 2023-02-04 23:32:52 +00:00
Simon
08abd5fd16 Single APK scheme for all devices 2023-02-04 23:31:24 +00:00
Simon
c0fbe43f8d Some tidy up and improvement to selection of openxr_loader.so based on OPENXR_HMD 2023-01-27 22:04:30 +00:00
Simon
d4c6c925d9 Fixed missing thumbstick click 2023-01-21 20:27:25 +00:00
Simon
844495401f Cleaned up input 2023-01-21 15:08:25 +00:00
Simon
c67d34354c Couple of fixes
- Ensure diagonal movement is not faster than in a straight line
- Ensure config file saves on exit
2023-01-18 20:35:55 +00:00
Simon
f0843f9508
Update README.md 2023-01-17 21:45:02 +00:00
Simon
ce8bea0db6 increase movement speed 2023-01-17 21:30:46 +00:00
Simon
cbbc7490e8 Merge branch 'master' of https://github.com/DrBeef/QuakeQuest 2023-01-17 14:08:07 +00:00
Simon
277f84f9c4 Ensure correct call order of xrWaitFrame/xrBeginFrame/xrEndFrame 2023-01-17 14:08:05 +00:00
Grant Bagwell
7bdba7ac1d Defaults for SS and Brightness
SS 1.3
r_hdr_scenebrightness 1.4 on both devices
2023-01-17 14:33:12 +01:00
Grant Bagwell
4b75af0e31 Include library for OpenXR v47 2023-01-17 14:02:09 +01:00
Simon
b5e9618d81 Several Fixes
- Allow super sampling
- Fixes to haptic feedback
- Default brightness on Pico to 1.4
2023-01-15 15:44:20 +00:00
Simon
44cd598e2b Corrected Vr to Xr 2022-12-23 21:11:00 +00:00
Simon
d9d27e62ad Fix "moving" sky on Pico 2022-12-23 10:45:55 +00:00
Simon
865cbc11cc Quit menu option fix 2022-12-23 10:39:26 +00:00
Simon
3dcc4573a7 Another small OpenXR change 2022-12-22 22:25:43 +00:00
Simon
b4a24d1765 Updated to OpenXR
Also means the Pico 4 works now
2022-12-22 22:22:52 +00:00
45 changed files with 14046 additions and 4208 deletions

17
.gitignore vendored
View file

@ -15,8 +15,6 @@ $RECYCLE.BIN/
*.o
*.d
#binaries
*.so
#libs
*.a
@ -32,9 +30,24 @@ Projects/Android/.cxx/*
Projects/Android/.externalNativeBuild/*
*.bin
Projects/Android/.gradle/*
.gradle/*
*.ser
Projects/Android/.idea/codeStyles/Project.xml
*.xml
Projects/Android/.gradle/*
drbeef-release-key.keystore
Projects/Android/.idea/.name
Projects/Android/jni/SupportLibs/liboggvorbis/libs/armeabi-v7a/libogg.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/armeabi-v7a/libvorbis-jni.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/armeabi-v7a/libvorbis.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/armeabi/libogg.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/armeabi/libvorbis-jni.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/armeabi/libvorbis.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/mips/libogg.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/mips/libvorbis-jni.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/mips/libvorbis.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/x86/libogg.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/x86/libvorbis-jni.so
Projects/Android/jni/SupportLibs/liboggvorbis/libs/x86/libvorbis.so
Projects/Android/libs/arm64-v8a/libopenxr_loader_meta.so
Projects/Android/libs/arm64-v8a/libopenxr_loader_pico.so

View file

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":VrSamples:QuakeQuest:Projects:Android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="QuakeQuest.VrSamples.QuakeQuest.Projects" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":VrSamples:QuakeQuest:Projects:Android" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="4.0.2" />
<option name="LAST_KNOWN_AGP_VERSION" value="4.0.2" />
</configuration>
</facet>
<facet type="native-android-gradle" name="Native-Android-Gradle">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug-arm64-v8a" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/../../res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../res;file://$MODULE_DIR$/src/debug/res;file://$MODULE_DIR$/build/generated/res/rs/debug" />
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/androidTest/res;file://$MODULE_DIR$/src/test/res;file://$MODULE_DIR$/src/androidTestDebug/res;file://$MODULE_DIR$/src/testDebug/res;file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/../../assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/classes" />
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/jni/SupportLibs/liboggvorbis/libogg" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/jni/SupportLibs/liboggvorbis/libvorbis" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/jni/SupportLibs/liboggvorbis/libvorbis-jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/jni/QuakeQuestSrc" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/jni/darkplaces" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/ap_generated_sources/debug/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debug/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/ap_generated_sources/debugAndroidTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debugAndroidTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/ap_generated_sources/debugUnitTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/jni" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/.cxx" />
<excludeFolder url="file://$MODULE_DIR$/.externalNativeBuild" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<content url="file://$MODULE_DIR$/../../assets">
<sourceFolder url="file://$MODULE_DIR$/../../assets" type="java-resource" />
</content>
<content url="file://$MODULE_DIR$/../../java">
<sourceFolder url="file://$MODULE_DIR$/../../java" isTestSource="false" />
</content>
<content url="file://$MODULE_DIR$/../../res">
<sourceFolder url="file://$MODULE_DIR$/../../res" type="java-resource" />
</content>
<orderEntry type="jdk" jdkName="Android API 26 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:26.1.0@jar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.0.0@jar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:common:1.0.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils:26.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-compat:26.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: android-android-26" level="project" />
</component>
</module>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.drbeef.quakequest"
android:versionCode="18"
android:versionName="1.4.11"
android:versionCode="26"
android:versionName="1.5.7"
android:installLocation="auto" >
<!-- Tell the system this app requires OpenGL ES 3.1. -->
@ -11,26 +11,28 @@
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1"
android:required="true" />
<!-- Network access needed for OVRMonitor -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Volume Control -->
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="false"
android:icon="@drawable/ic_qquest"
android:label="@string/quakequest"
android:extractNativeLibs="true">
<!-- META QUEST -->
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
<!-- The activity is the built-in NativeActivity framework class. -->
<!-- launchMode is set to singleTask because there should never be multiple copies of the app running. -->
<!-- Theme.Black.NoTitleBar.Fullscreen gives solid black instead of a (bad stereoscopic) gradient on app transition. -->
<!-- If targeting API level 24+, configChanges should additionally include 'density'. -->
<!-- If targeting API level 24+, android:resizeableActivity="false" should be added. -->
<meta-data android:name="com.oculus.vr.focusaware" android:value="true" />
<!-- PICO XR -->
<meta-data android:name="pvr.app.type" android:value="vr" />
<activity
android:exported="true"
android:name="com.drbeef.quakequest.GLES3JNIActivity"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:label="@string/quakequest"
@ -38,8 +40,10 @@
android:screenOrientation="landscape"
android:excludeFromRecents="true"
android:configChanges="screenSize|screenLayout|orientation|keyboardHidden|keyboard|navigation|uiMode">
<!-- Tell NativeActivity the name of the .so -->
<meta-data android:name="android.app.lib_name" android:value="quakequest" />
<!-- This filter lets the apk show up as a launchable icon. -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View file

@ -1,29 +0,0 @@
@rem Only edit the master copy of this file in SDK_ROOT/bin/scripts/build/perproject
@setlocal enableextensions enabledelayedexpansion
@if not exist "build.gradle" @echo Build script must be executed from project directory. & goto :Abort
@set P=..
:TryAgain
@rem @echo P = %P%
@if exist "%P%\bin\scripts\build\build.py.bat" goto :Found
@if exist "%P%\bin\scripts\build" @echo "Could not find build.py.bat" & goto :Abort
@set P=%P%\..
@goto :TryAgain
:Found
@set P=%P%\bin\scripts\build
@call %P%\build.py.bat %1 %2 %3 %4 %5
@goto :End
:Abort
:End

View file

@ -1,7 +1,20 @@
buildscript {
repositories {
google() // For Gradle 4.0+
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.1'
}
}
apply plugin: 'com.android.application'
apply from: "${rootProject.projectDir}/VrApp.gradle"
android {
namespace = "com.drbeef.quakequest"
// This is the name of the generated apk file, which will have
// -debug.apk or -release.apk appended to it.
// The filename doesn't effect the Android installation process.
@ -20,15 +33,77 @@ android {
abiFilters 'arm64-v8a'
}
ndkBuild {
abiFilters 'arm64-v8a'
def numProcs = Runtime.runtime.availableProcessors()
arguments "V=0", "-j$numProcs", "-C$project.buildDir.parent", "APP_PLATFORM=android-29", "NDK_TOOLCHAIN_VERSION=clang", "APP_STL=c++_static"
abiFilters 'arm64-v8a'
}
}
minSdkVersion 26
targetSdkVersion 26
minSdkVersion 32
targetSdkVersion 32
}
task prepareKotlinBuildScriptModel {
externalNativeBuild {
ndkBuild {
path file('jni/Android.mk')
}
}
signingConfigs {
def keystorePath = (project.hasProperty('key.store')) ?
new File(project.getProperty('key.store')) :
project.file('android.debug.keystore')
def keystorePassword = (project.hasProperty('key.store.password')) ?
project.getProperty('key.store.password') : 'android'
def keystoreKeyAlias = (project.hasProperty('key.alias')) ?
project.getProperty('key.alias') : 'androiddebugkey'
def keystoreKeyPassword = (project.hasProperty('key.alias.password')) ?
project.getProperty('key.alias.password') : 'android'
debug {
storeFile keystorePath
storePassword keystorePassword
keyAlias keystoreKeyAlias
keyPassword keystoreKeyPassword
v2SigningEnabled true
}
release {
storeFile keystorePath
storePassword keystorePassword
keyAlias keystoreKeyAlias
keyPassword keystoreKeyPassword
v2SigningEnabled true
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
debuggable true
jniDebuggable true
externalNativeBuild {
ndkBuild {
arguments "NDK_DEBUG=1","USE_ASAN=1"
}
}
}
release {
signingConfig signingConfigs.release
debuggable false
jniDebuggable false
externalNativeBuild {
ndkBuild {
arguments "NDK_DEBUG=0","USE_ASAN=0"
}
}
}
}
sourceSets {
@ -44,20 +119,41 @@ android {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
compileSdkVersion = 26
buildToolsVersion = '29.0.2'
lintOptions {
checkReleaseBuilds false
disable 'ExpiredTargetSdkVersion'
}
packagingOptions {
exclude 'lib/arm64-v8a/libopenxr_loader.so'
}
compileSdkVersion = 32
buildToolsVersion = '29.0.3'
ndkVersion '25.1.8937393'
}
dependencies {
implementation "com.android.support:support-compat:26.1.0"
implementation "com.android.support:support-core-utils:26.1.0"
implementation "com.android.support:support-compat:28.0.0"
implementation "com.android.support:support-core-utils:28.0.0"
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
}
repositories {
google()
}
buildscript {
repositories {
google()
}
}
// Workaround to fix issue in Android Studio Chipmunk 2021.2.1 and later
// where opening a project would result in a 'prepareKotlinBuildScriptModel'
// not found error
if (!tasks.findByName("prepareKotlinBuildScriptModel")) {
tasks.register("prepareKotlinBuildScriptModel") {}
}

View file

@ -1,29 +0,0 @@
#!/usr/bin/python
# This first bit of code is common bootstrapping code
# to determine the SDK root, and to set up the import
# path for additional python code.
#begin bootstrap
import os
import sys
def init():
root = os.path.realpath( os.path.dirname(os.path.realpath(__file__) ) )
os.chdir(root) # make sure we are always executing from the project directory
while( os.path.isdir( os.path.join(root, 'bin/scripts/build') ) == False ):
root = os.path.realpath( os.path.join(root, '..') )
if( len(root) <= 5 ): # Should catch both Posix and Windows root directories (e.g. '/' and 'C:\')
print('Unable to find SDK root. Exiting.')
sys.exit(1)
root = os.path.abspath(root)
os.environ['OCULUS_SDK_PATH'] = root
sys.path.append( root + "/bin/scripts/build" )
init()
import ovrbuild
ovrbuild.init()
#end bootstrap
ovrbuild.build()

View file

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip

View file

@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View file

@ -1,84 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View file

@ -6,15 +6,17 @@ LOCAL_PATH:= $(call my-dir)
#--------------------------------------------------------
include $(CLEAR_VARS)
LOCAL_CFLAGS := -std=c99
LOCAL_MODULE := quakequest
LOCAL_LDLIBS := -llog -landroid -lGLESv3 -lEGL -lOpenSLES # include default libraries
LOCAL_C_INCLUDES := ../QuakeQuestSrc/ \
../darkplaces/ \
$(SUPPORT_LIBS)/liboggvorbis/include
../darkplaces/ \
$(SUPPORT_LIBS)/liboggvorbis/include \
${TOP_DIR}/OpenXR-SDK/include \
${TOP_DIR}/OpenXR-SDK/src/common
LOCAL_SHARED_LIBRARIES := vrapi libvorbis libogg libvorbis-jni
LOCAL_SHARED_LIBRARIES := openxr_loader libvorbis libogg libvorbis-jni
SRC_SND_COMMON := \
darkplaces/snd_opensl.c \
@ -120,8 +122,9 @@ SRC_COMMON := \
SRC_QUEST := \
QuakeQuestSrc/argtable3.c \
QuakeQuestSrc/QuakeQuest_SurfaceView.c \
QuakeQuestSrc/VrCompositor.c \
QuakeQuestSrc/QuakeQuest_OpenXR.c \
QuakeQuestSrc/OpenXrInput.c \
QuakeQuestSrc/TBXR_Common.c \
LOCAL_SRC_FILES := \
$(SRC_QUEST) \
@ -135,4 +138,4 @@ LOCAL_SRC_FILES := \
include $(BUILD_SHARED_LIBRARY)
include $(SUPPORT_LIBS)/liboggvorbis/Android.mk
$(call import-module,VrApi/Projects/AndroidPrebuilt/jni)
$(call import-module,AndroidPrebuilt/jni)

View file

@ -1,14 +1,9 @@
# MAKEFILE_LIST specifies the current used Makefiles, of which this is the last
# one. I use that to obtain the Application.mk dir then import the root
# Application.mk.
ROOT_DIR := $(dir $(lastword $(MAKEFILE_LIST)))../../../../..
NDK_MODULE_PATH := $(ROOT_DIR)
APP_PLATFORM := android-24
APP_CFLAGS += -Wl,--no-undefined
APPLICATIONMK_PATH = $(call my-dir)
NDK_MODULE_PATH := $(APPLICATIONMK_PATH)/../..
TOP_DIR := $(APPLICATIONMK_PATH)
SUPPORT_LIBS := $(APPLICATIONMK_PATH)/SupportLibs

View file

@ -0,0 +1,20 @@
# Copyright (c) 2017 The Khronos Group Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author:
#
add_subdirectory(openxr)

View file

@ -0,0 +1,101 @@
# Copyright (c) 2017-2022, The Khronos Group Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author:
#
# Copy the openxr_platform_defines.h file and place it in the binary (build) directory.
configure_file(openxr_platform_defines.h ${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h COPYONLY)
# Generate OpenXR header files.
set(HEADERS
openxr.h
openxr_platform.h
openxr_reflection.h)
set(HAVE_PREGENERATED TRUE)
set(SOURCE_HEADERS)
foreach(output ${HEADERS})
list(APPEND SOURCE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/${output})
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${output})
set(HAVE_PREGENERATED FALSE)
endif()
endforeach()
set(XR_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
if(HAVE_PREGENERATED AND NOT BUILD_FORCE_GENERATION)
add_custom_target(generate_openxr_header
COMMENT "Using found pre-generated OpenXR headers.")
set(INSTALL_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/openxr_platform_defines.h
${SOURCE_HEADERS})
else()
set(GENERATED_HEADERS)
set(OUTPUT_STAMPS)
# Copy the openxr_platform_defines.h file and place it in the binary (build) directory.
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/openxr_platform_defines.h
${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h
COPYONLY)
# Generate the header files and place it in the binary (build) directory.
foreach(output ${HEADERS})
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output}
COMMAND ${PYTHON_EXECUTABLE} ${XR_ROOT}/specification/scripts/genxr.py
-registry ${XR_ROOT}/specification/registry/xr.xml
-o ${CMAKE_CURRENT_BINARY_DIR} ${output}
DEPENDS
${XR_ROOT}/specification/scripts/genxr.py
${XR_ROOT}/specification/scripts/cgenerator.py
${XR_ROOT}/specification/scripts/creflectiongenerator.py
${XR_ROOT}/specification/scripts/generator.py
${XR_ROOT}/specification/scripts/reg.py
${XR_ROOT}/specification/registry/xr.xml
COMMENT "Generating ${CMAKE_CURRENT_BINARY_DIR}/${output}"
)
list(APPEND GENERATED_HEADERS "${CMAKE_CURRENT_BINARY_DIR}/${output}")
endforeach()
set_source_files_properties(
${GENERATED_HEADERS}
PROPERTIES GENERATED TRUE
)
set(INSTALL_HEADERS
${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h
${GENERATED_HEADERS})
# Define generate_openxr_header target to generate the OpenXR header files.
# Other targets that need the OpenXR headers should use generate_openxr_header as a dependency.
add_custom_target(generate_openxr_header
SOURCES ${XR_ROOT}/specification/registry/xr.xml
DEPENDS
${GENERATED_HEADERS}
${OUTPUT_STAMPS}
)
endif()
set_target_properties(generate_openxr_header PROPERTIES FOLDER ${CODEGEN_FOLDER})
if(NOT CMAKE_INSTALL_INCDIR)
set(CMAKE_INSTALL_INCDIR include)
endif()
INSTALL(FILES ${INSTALL_HEADERS}
DESTINATION ${CMAKE_INSTALL_INCDIR}/openxr
COMPONENT Headers
)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,690 @@
#ifndef OPENXR_PLATFORM_H_
#define OPENXR_PLATFORM_H_ 1
/*
** Copyright 2017-2022 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0 OR MIT
*/
/*
** This header is generated from the Khronos OpenXR XML API Registry.
**
*/
#include "openxr.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef XR_USE_PLATFORM_ANDROID
#define XR_KHR_android_thread_settings 1
#define XR_KHR_android_thread_settings_SPEC_VERSION 5
#define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings"
typedef enum XrAndroidThreadTypeKHR {
XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,
XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,
XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,
XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,
XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
} XrAndroidThreadTypeKHR;
typedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session, XrAndroidThreadTypeKHR threadType, uint32_t threadId);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(
XrSession session,
XrAndroidThreadTypeKHR threadType,
uint32_t threadId);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_PLATFORM_ANDROID */
#ifdef XR_USE_PLATFORM_ANDROID
#define XR_KHR_android_surface_swapchain 1
#define XR_KHR_android_surface_swapchain_SPEC_VERSION 4
#define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME "XR_KHR_android_surface_swapchain"
typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session, const XrSwapchainCreateInfo* info, XrSwapchain* swapchain, jobject* surface);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(
XrSession session,
const XrSwapchainCreateInfo* info,
XrSwapchain* swapchain,
jobject* surface);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_PLATFORM_ANDROID */
#ifdef XR_USE_PLATFORM_ANDROID
#define XR_KHR_android_create_instance 1
#define XR_KHR_android_create_instance_SPEC_VERSION 3
#define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME "XR_KHR_android_create_instance"
// XrInstanceCreateInfoAndroidKHR extends XrInstanceCreateInfo
typedef struct XrInstanceCreateInfoAndroidKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
void* XR_MAY_ALIAS applicationVM;
void* XR_MAY_ALIAS applicationActivity;
} XrInstanceCreateInfoAndroidKHR;
#endif /* XR_USE_PLATFORM_ANDROID */
#ifdef XR_USE_GRAPHICS_API_VULKAN
#define XR_KHR_vulkan_swapchain_format_list 1
#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 4
#define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list"
typedef struct XrVulkanSwapchainFormatListCreateInfoKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
uint32_t viewFormatCount;
const VkFormat* viewFormats;
} XrVulkanSwapchainFormatListCreateInfoKHR;
#endif /* XR_USE_GRAPHICS_API_VULKAN */
#ifdef XR_USE_GRAPHICS_API_OPENGL
#define XR_KHR_opengl_enable 1
#define XR_KHR_opengl_enable_SPEC_VERSION 10
#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable"
#ifdef XR_USE_PLATFORM_WIN32
// XrGraphicsBindingOpenGLWin32KHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingOpenGLWin32KHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
HDC hDC;
HGLRC hGLRC;
} XrGraphicsBindingOpenGLWin32KHR;
#endif // XR_USE_PLATFORM_WIN32
#ifdef XR_USE_PLATFORM_XLIB
// XrGraphicsBindingOpenGLXlibKHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingOpenGLXlibKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
Display* xDisplay;
uint32_t visualid;
GLXFBConfig glxFBConfig;
GLXDrawable glxDrawable;
GLXContext glxContext;
} XrGraphicsBindingOpenGLXlibKHR;
#endif // XR_USE_PLATFORM_XLIB
#ifdef XR_USE_PLATFORM_XCB
// XrGraphicsBindingOpenGLXcbKHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingOpenGLXcbKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
xcb_connection_t* connection;
uint32_t screenNumber;
xcb_glx_fbconfig_t fbconfigid;
xcb_visualid_t visualid;
xcb_glx_drawable_t glxDrawable;
xcb_glx_context_t glxContext;
} XrGraphicsBindingOpenGLXcbKHR;
#endif // XR_USE_PLATFORM_XCB
#ifdef XR_USE_PLATFORM_WAYLAND
// XrGraphicsBindingOpenGLWaylandKHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingOpenGLWaylandKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
struct wl_display* display;
} XrGraphicsBindingOpenGLWaylandKHR;
#endif // XR_USE_PLATFORM_WAYLAND
typedef struct XrSwapchainImageOpenGLKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t image;
} XrSwapchainImageOpenGLKHR;
typedef struct XrGraphicsRequirementsOpenGLKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrVersion minApiVersionSupported;
XrVersion maxApiVersionSupported;
} XrGraphicsRequirementsOpenGLKHR;
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_GRAPHICS_API_OPENGL */
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
#define XR_KHR_opengl_es_enable 1
#define XR_KHR_opengl_es_enable_SPEC_VERSION 8
#define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME "XR_KHR_opengl_es_enable"
#ifdef XR_USE_PLATFORM_ANDROID
// XrGraphicsBindingOpenGLESAndroidKHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingOpenGLESAndroidKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
EGLDisplay display;
EGLConfig config;
EGLContext context;
} XrGraphicsBindingOpenGLESAndroidKHR;
#endif // XR_USE_PLATFORM_ANDROID
typedef struct XrSwapchainImageOpenGLESKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t image;
} XrSwapchainImageOpenGLESKHR;
typedef struct XrGraphicsRequirementsOpenGLESKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrVersion minApiVersionSupported;
XrVersion maxApiVersionSupported;
} XrGraphicsRequirementsOpenGLESKHR;
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
#ifdef XR_USE_GRAPHICS_API_VULKAN
#define XR_KHR_vulkan_enable 1
#define XR_KHR_vulkan_enable_SPEC_VERSION 8
#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable"
// XrGraphicsBindingVulkanKHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingVulkanKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
VkInstance instance;
VkPhysicalDevice physicalDevice;
VkDevice device;
uint32_t queueFamilyIndex;
uint32_t queueIndex;
} XrGraphicsBindingVulkanKHR;
typedef struct XrSwapchainImageVulkanKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
VkImage image;
} XrSwapchainImageVulkanKHR;
typedef struct XrGraphicsRequirementsVulkanKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrVersion minApiVersionSupported;
XrVersion maxApiVersionSupported;
} XrGraphicsRequirementsVulkanKHR;
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice);
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
XrInstance instance,
XrSystemId systemId,
uint32_t bufferCapacityInput,
uint32_t* bufferCountOutput,
char* buffer);
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
XrInstance instance,
XrSystemId systemId,
uint32_t bufferCapacityInput,
uint32_t* bufferCountOutput,
char* buffer);
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
XrInstance instance,
XrSystemId systemId,
VkInstance vkInstance,
VkPhysicalDevice* vkPhysicalDevice);
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_GRAPHICS_API_VULKAN */
#ifdef XR_USE_GRAPHICS_API_D3D11
#define XR_KHR_D3D11_enable 1
#define XR_KHR_D3D11_enable_SPEC_VERSION 9
#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable"
// XrGraphicsBindingD3D11KHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingD3D11KHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
ID3D11Device* device;
} XrGraphicsBindingD3D11KHR;
typedef struct XrSwapchainImageD3D11KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
ID3D11Texture2D* texture;
} XrSwapchainImageD3D11KHR;
typedef struct XrGraphicsRequirementsD3D11KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
LUID adapterLuid;
D3D_FEATURE_LEVEL minFeatureLevel;
} XrGraphicsRequirementsD3D11KHR;
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_GRAPHICS_API_D3D11 */
#ifdef XR_USE_GRAPHICS_API_D3D12
#define XR_KHR_D3D12_enable 1
#define XR_KHR_D3D12_enable_SPEC_VERSION 9
#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable"
// XrGraphicsBindingD3D12KHR extends XrSessionCreateInfo
typedef struct XrGraphicsBindingD3D12KHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
ID3D12Device* device;
ID3D12CommandQueue* queue;
} XrGraphicsBindingD3D12KHR;
typedef struct XrSwapchainImageD3D12KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
ID3D12Resource* texture;
} XrSwapchainImageD3D12KHR;
typedef struct XrGraphicsRequirementsD3D12KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
LUID adapterLuid;
D3D_FEATURE_LEVEL minFeatureLevel;
} XrGraphicsRequirementsD3D12KHR;
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_GRAPHICS_API_D3D12 */
#ifdef XR_USE_PLATFORM_WIN32
#define XR_KHR_win32_convert_performance_counter_time 1
#define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1
#define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time"
typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time);
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
XrInstance instance,
const LARGE_INTEGER* performanceCounter,
XrTime* time);
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
XrInstance instance,
XrTime time,
LARGE_INTEGER* performanceCounter);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_PLATFORM_WIN32 */
#ifdef XR_USE_TIMESPEC
#define XR_KHR_convert_timespec_time 1
#define XR_KHR_convert_timespec_time_SPEC_VERSION 1
#define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time"
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time);
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
XrInstance instance,
const struct timespec* timespecTime,
XrTime* time);
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
XrInstance instance,
XrTime time,
struct timespec* timespecTime);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_TIMESPEC */
#ifdef XR_USE_PLATFORM_ANDROID
#define XR_KHR_loader_init_android 1
#define XR_KHR_loader_init_android_SPEC_VERSION 1
#define XR_KHR_LOADER_INIT_ANDROID_EXTENSION_NAME "XR_KHR_loader_init_android"
typedef struct XrLoaderInitInfoAndroidKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
void* XR_MAY_ALIAS applicationVM;
void* XR_MAY_ALIAS applicationContext;
} XrLoaderInitInfoAndroidKHR;
#endif /* XR_USE_PLATFORM_ANDROID */
#ifdef XR_USE_GRAPHICS_API_VULKAN
#define XR_KHR_vulkan_enable2 1
#define XR_KHR_vulkan_enable2_SPEC_VERSION 2
#define XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME "XR_KHR_vulkan_enable2"
typedef XrFlags64 XrVulkanInstanceCreateFlagsKHR;
// Flag bits for XrVulkanInstanceCreateFlagsKHR
typedef XrFlags64 XrVulkanDeviceCreateFlagsKHR;
// Flag bits for XrVulkanDeviceCreateFlagsKHR
typedef struct XrVulkanInstanceCreateInfoKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrSystemId systemId;
XrVulkanInstanceCreateFlagsKHR createFlags;
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
const VkInstanceCreateInfo* vulkanCreateInfo;
const VkAllocationCallbacks* vulkanAllocator;
} XrVulkanInstanceCreateInfoKHR;
typedef struct XrVulkanDeviceCreateInfoKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrSystemId systemId;
XrVulkanDeviceCreateFlagsKHR createFlags;
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
VkPhysicalDevice vulkanPhysicalDevice;
const VkDeviceCreateInfo* vulkanCreateInfo;
const VkAllocationCallbacks* vulkanAllocator;
} XrVulkanDeviceCreateInfoKHR;
typedef XrGraphicsBindingVulkanKHR XrGraphicsBindingVulkan2KHR;
typedef struct XrVulkanGraphicsDeviceGetInfoKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrSystemId systemId;
VkInstance vulkanInstance;
} XrVulkanGraphicsDeviceGetInfoKHR;
typedef XrSwapchainImageVulkanKHR XrSwapchainImageVulkan2KHR;
typedef XrGraphicsRequirementsVulkanKHR XrGraphicsRequirementsVulkan2KHR;
typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanInstanceKHR)(XrInstance instance, const XrVulkanInstanceCreateInfoKHR* createInfo, VkInstance* vulkanInstance, VkResult* vulkanResult);
typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanDeviceKHR)(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* vulkanDevice, VkResult* vulkanResult);
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDevice2KHR)(XrInstance instance, const XrVulkanGraphicsDeviceGetInfoKHR* getInfo, VkPhysicalDevice* vulkanPhysicalDevice);
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirements2KHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanInstanceKHR(
XrInstance instance,
const XrVulkanInstanceCreateInfoKHR* createInfo,
VkInstance* vulkanInstance,
VkResult* vulkanResult);
XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanDeviceKHR(
XrInstance instance,
const XrVulkanDeviceCreateInfoKHR* createInfo,
VkDevice* vulkanDevice,
VkResult* vulkanResult);
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDevice2KHR(
XrInstance instance,
const XrVulkanGraphicsDeviceGetInfoKHR* getInfo,
VkPhysicalDevice* vulkanPhysicalDevice);
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirements2KHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_GRAPHICS_API_VULKAN */
#ifdef XR_USE_PLATFORM_EGL
#define XR_MNDX_egl_enable 1
#define XR_MNDX_egl_enable_SPEC_VERSION 1
#define XR_MNDX_EGL_ENABLE_EXTENSION_NAME "XR_MNDX_egl_enable"
// XrGraphicsBindingEGLMNDX extends XrSessionCreateInfo
typedef struct XrGraphicsBindingEGLMNDX {
XrStructureType type;
const void* XR_MAY_ALIAS next;
PFNEGLGETPROCADDRESSPROC getProcAddress;
EGLDisplay display;
EGLConfig config;
EGLContext context;
} XrGraphicsBindingEGLMNDX;
#endif /* XR_USE_PLATFORM_EGL */
#ifdef XR_USE_PLATFORM_WIN32
#define XR_MSFT_perception_anchor_interop 1
#define XR_MSFT_perception_anchor_interop_SPEC_VERSION 1
#define XR_MSFT_PERCEPTION_ANCHOR_INTEROP_EXTENSION_NAME "XR_MSFT_perception_anchor_interop"
typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPerceptionAnchorMSFT)(XrSession session, IUnknown* perceptionAnchor, XrSpatialAnchorMSFT* anchor);
typedef XrResult (XRAPI_PTR *PFN_xrTryGetPerceptionAnchorFromSpatialAnchorMSFT)(XrSession session, XrSpatialAnchorMSFT anchor, IUnknown** perceptionAnchor);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFromPerceptionAnchorMSFT(
XrSession session,
IUnknown* perceptionAnchor,
XrSpatialAnchorMSFT* anchor);
XRAPI_ATTR XrResult XRAPI_CALL xrTryGetPerceptionAnchorFromSpatialAnchorMSFT(
XrSession session,
XrSpatialAnchorMSFT anchor,
IUnknown** perceptionAnchor);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_PLATFORM_WIN32 */
#ifdef XR_USE_PLATFORM_WIN32
#define XR_MSFT_holographic_window_attachment 1
#define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1
#define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME "XR_MSFT_holographic_window_attachment"
#ifdef XR_USE_PLATFORM_WIN32
// XrHolographicWindowAttachmentMSFT extends XrSessionCreateInfo
typedef struct XrHolographicWindowAttachmentMSFT {
XrStructureType type;
const void* XR_MAY_ALIAS next;
IUnknown* holographicSpace;
IUnknown* coreWindow;
} XrHolographicWindowAttachmentMSFT;
#endif // XR_USE_PLATFORM_WIN32
#endif /* XR_USE_PLATFORM_WIN32 */
#ifdef XR_USE_PLATFORM_ANDROID
#define XR_FB_android_surface_swapchain_create 1
#define XR_FB_android_surface_swapchain_create_SPEC_VERSION 1
#define XR_FB_ANDROID_SURFACE_SWAPCHAIN_CREATE_EXTENSION_NAME "XR_FB_android_surface_swapchain_create"
typedef XrFlags64 XrAndroidSurfaceSwapchainFlagsFB;
// Flag bits for XrAndroidSurfaceSwapchainFlagsFB
static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_SYNCHRONOUS_BIT_FB = 0x00000001;
static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_USE_TIMESTAMPS_BIT_FB = 0x00000002;
#ifdef XR_USE_PLATFORM_ANDROID
// XrAndroidSurfaceSwapchainCreateInfoFB extends XrSwapchainCreateInfo
typedef struct XrAndroidSurfaceSwapchainCreateInfoFB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrAndroidSurfaceSwapchainFlagsFB createFlags;
} XrAndroidSurfaceSwapchainCreateInfoFB;
#endif // XR_USE_PLATFORM_ANDROID
#endif /* XR_USE_PLATFORM_ANDROID */
#ifdef XR_USE_PLATFORM_WIN32
#define XR_OCULUS_audio_device_guid 1
#define XR_OCULUS_audio_device_guid_SPEC_VERSION 1
#define XR_OCULUS_AUDIO_DEVICE_GUID_EXTENSION_NAME "XR_OCULUS_audio_device_guid"
#define XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS 128
typedef XrResult (XRAPI_PTR *PFN_xrGetAudioOutputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
typedef XrResult (XRAPI_PTR *PFN_xrGetAudioInputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
#ifndef XR_NO_PROTOTYPES
#ifdef XR_EXTENSION_PROTOTYPES
XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioOutputDeviceGuidOculus(
XrInstance instance,
wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioInputDeviceGuidOculus(
XrInstance instance,
wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
#endif /* XR_EXTENSION_PROTOTYPES */
#endif /* !XR_NO_PROTOTYPES */
#endif /* XR_USE_PLATFORM_WIN32 */
#ifdef XR_USE_GRAPHICS_API_VULKAN
#define XR_FB_foveation_vulkan 1
#define XR_FB_foveation_vulkan_SPEC_VERSION 1
#define XR_FB_FOVEATION_VULKAN_EXTENSION_NAME "XR_FB_foveation_vulkan"
// XrSwapchainImageFoveationVulkanFB extends XrSwapchainImageVulkanKHR
typedef struct XrSwapchainImageFoveationVulkanFB {
XrStructureType type;
void* XR_MAY_ALIAS next;
VkImage image;
uint32_t width;
uint32_t height;
} XrSwapchainImageFoveationVulkanFB;
#endif /* XR_USE_GRAPHICS_API_VULKAN */
#ifdef XR_USE_PLATFORM_ANDROID
#define XR_FB_swapchain_update_state_android_surface 1
#define XR_FB_swapchain_update_state_android_surface_SPEC_VERSION 1
#define XR_FB_SWAPCHAIN_UPDATE_STATE_ANDROID_SURFACE_EXTENSION_NAME "XR_FB_swapchain_update_state_android_surface"
#ifdef XR_USE_PLATFORM_ANDROID
typedef struct XrSwapchainStateAndroidSurfaceDimensionsFB {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t width;
uint32_t height;
} XrSwapchainStateAndroidSurfaceDimensionsFB;
#endif // XR_USE_PLATFORM_ANDROID
#endif /* XR_USE_PLATFORM_ANDROID */
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
#define XR_FB_swapchain_update_state_opengl_es 1
#define XR_FB_swapchain_update_state_opengl_es_SPEC_VERSION 1
#define XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME "XR_FB_swapchain_update_state_opengl_es"
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
typedef struct XrSwapchainStateSamplerOpenGLESFB {
XrStructureType type;
void* XR_MAY_ALIAS next;
EGLenum minFilter;
EGLenum magFilter;
EGLenum wrapModeS;
EGLenum wrapModeT;
EGLenum swizzleRed;
EGLenum swizzleGreen;
EGLenum swizzleBlue;
EGLenum swizzleAlpha;
float maxAnisotropy;
XrColor4f borderColor;
} XrSwapchainStateSamplerOpenGLESFB;
#endif // XR_USE_GRAPHICS_API_OPENGL_ES
#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
#ifdef XR_USE_GRAPHICS_API_VULKAN
#define XR_FB_swapchain_update_state_vulkan 1
#define XR_FB_swapchain_update_state_vulkan_SPEC_VERSION 1
#define XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME "XR_FB_swapchain_update_state_vulkan"
#ifdef XR_USE_GRAPHICS_API_VULKAN
typedef struct XrSwapchainStateSamplerVulkanFB {
XrStructureType type;
void* XR_MAY_ALIAS next;
VkFilter minFilter;
VkFilter magFilter;
VkSamplerMipmapMode mipmapMode;
VkSamplerAddressMode wrapModeS;
VkSamplerAddressMode wrapModeT;
VkComponentSwizzle swizzleRed;
VkComponentSwizzle swizzleGreen;
VkComponentSwizzle swizzleBlue;
VkComponentSwizzle swizzleAlpha;
float maxAnisotropy;
XrColor4f borderColor;
} XrSwapchainStateSamplerVulkanFB;
#endif // XR_USE_GRAPHICS_API_VULKAN
#endif /* XR_USE_GRAPHICS_API_VULKAN */
#ifdef XR_USE_GRAPHICS_API_VULKAN
#define XR_META_vulkan_swapchain_create_info 1
#define XR_META_vulkan_swapchain_create_info_SPEC_VERSION 1
#define XR_META_VULKAN_SWAPCHAIN_CREATE_INFO_EXTENSION_NAME "XR_META_vulkan_swapchain_create_info"
// XrVulkanSwapchainCreateInfoMETA extends XrSwapchainCreateInfo
typedef struct XrVulkanSwapchainCreateInfoMETA {
XrStructureType type;
const void* XR_MAY_ALIAS next;
VkImageCreateFlags additionalCreateFlags;
VkImageUsageFlags additionalUsageFlags;
} XrVulkanSwapchainCreateInfoMETA;
#endif /* XR_USE_GRAPHICS_API_VULKAN */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,110 @@
/*
** Copyright (c) 2017-2022, The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0 OR MIT
*/
#ifndef OPENXR_PLATFORM_DEFINES_H_
#define OPENXR_PLATFORM_DEFINES_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/* Platform-specific calling convention macros.
*
* Platforms should define these so that OpenXR clients call OpenXR functions
* with the same calling conventions that the OpenXR implementation expects.
*
* XRAPI_ATTR - Placed before the return type in function declarations.
* Useful for C++11 and GCC/Clang-style function attribute syntax.
* XRAPI_CALL - Placed after the return type in function declarations.
* Useful for MSVC-style calling convention syntax.
* XRAPI_PTR - Placed between the '(' and '*' in function pointer types.
*
* Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void);
* Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);
*/
#if defined(_WIN32)
#define XRAPI_ATTR
// On Windows, functions use the stdcall convention
#define XRAPI_CALL __stdcall
#define XRAPI_PTR XRAPI_CALL
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
#error "API not supported for the 'armeabi' NDK ABI"
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
// On Android 32-bit ARM targets, functions use the "hardfloat"
// calling convention, i.e. float parameters are passed in registers. This
// is true even if the rest of the application passes floats on the stack,
// as it does by default when compiling for the armeabi-v7a NDK ABI.
#define XRAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#define XRAPI_CALL
#define XRAPI_PTR XRAPI_ATTR
#else
// On other platforms, use the default calling convention
#define XRAPI_ATTR
#define XRAPI_CALL
#define XRAPI_PTR
#endif
#include <stddef.h>
#if !defined(XR_NO_STDINT_H)
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#endif // !defined( XR_NO_STDINT_H )
// XR_PTR_SIZE (in bytes)
#if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__))
#define XR_PTR_SIZE 8
#else
#define XR_PTR_SIZE 4
#endif
// Needed so we can use clang __has_feature portably.
#if !defined(XR_COMPILER_HAS_FEATURE)
#if defined(__clang__)
#define XR_COMPILER_HAS_FEATURE(x) __has_feature(x)
#else
#define XR_COMPILER_HAS_FEATURE(x) 0
#endif
#endif
// Identifies if the current compiler has C++11 support enabled.
// Does not by itself identify if any given C++11 feature is present.
#if !defined(XR_CPP11_ENABLED) && defined(__cplusplus)
#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
#define XR_CPP11_ENABLED 1
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
#define XR_CPP11_ENABLED 1
#elif (__cplusplus >= 201103L) // 201103 is the first C++11 version.
#define XR_CPP11_ENABLED 1
#endif
#endif
// Identifies if the current compiler supports C++11 nullptr.
#if !defined(XR_CPP_NULLPTR_SUPPORTED)
#if defined(XR_CPP11_ENABLED) && \
((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \
(defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \
(defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))
#define XR_CPP_NULLPTR_SUPPORTED 1
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
#ifndef OPENXR_HELPERS_H_
#define OPENXR_HELPERS_H_
#include <xr_linear.h>
static inline XrTime ToXrTime(const double timeInSeconds) {
return (timeInSeconds * 1e9);
}
static inline double FromXrTime(const XrTime time) {
return (time * 1e-9);
}
static inline XrQuaternionf XrQuaternionf_Identity() {
XrQuaternionf r;
r.x = r.y = r.z = 0.0;
r.w = 1.0f;
return r;
}
static inline XrVector3f XrVector3f_Zero() {
XrVector3f r;
r.x = r.y = r.z = 0.0f;
return r;
}
static inline float XrVector3f_LengthSquared(const XrVector3f v) {
return XrVector3f_Dot(&v, &v);
}
static inline XrVector3f XrVector3f_ScalarMultiply(const XrVector3f v, float scale) {
XrVector3f u;
u.x = v.x * scale;
u.y = v.y * scale;
u.z = v.z * scale;
return u;
}
static inline XrVector3f XrVector3f_Normalized(const XrVector3f v) {
float rcpLen = 1.0f / XrVector3f_Length(&v);
return XrVector3f_ScalarMultiply(v, rcpLen);
}
static inline XrQuaternionf XrQuaternionf_Inverse(const XrQuaternionf q) {
XrQuaternionf r;
r.x = -q.x;
r.y = -q.y;
r.z = -q.z;
r.w = q.w;
return r;
}
static inline XrVector3f XrQuaternionf_Rotate(const XrQuaternionf a, const XrVector3f v) {
XrVector3f r;
XrQuaternionf q = {v.x, v.y, v.z, 0.0f};
XrQuaternionf aq;
XrQuaternionf_Multiply(&aq, &q, &a);
XrQuaternionf aInv = XrQuaternionf_Inverse(a);
XrQuaternionf aqaInv;
XrQuaternionf_Multiply(&aqaInv, &aInv, &aq);
r.x = aqaInv.x;
r.y = aqaInv.y;
r.z = aqaInv.z;
return r;
}
static inline XrQuaternionf XrQuaternionf_CreateFromVectorAngle(
const XrVector3f axis,
const float angle) {
XrQuaternionf r;
if (XrVector3f_LengthSquared(axis) == 0.0f) {
return XrQuaternionf_Identity();
}
XrVector3f unitAxis = XrVector3f_Normalized(axis);
float sinHalfAngle = sinf(angle * 0.5f);
r.w = cosf(angle * 0.5f);
r.x = unitAxis.x * sinHalfAngle;
r.y = unitAxis.y * sinHalfAngle;
r.z = unitAxis.z * sinHalfAngle;
return r;
}
static inline XrPosef XrPosef_Identity() {
XrPosef r;
r.orientation = XrQuaternionf_Identity();
r.position = XrVector3f_Zero();
return r;
}
static inline XrPosef XrPosef_Inverse(const XrPosef a) {
XrPosef b;
b.orientation = XrQuaternionf_Inverse(a.orientation);
b.position = XrQuaternionf_Rotate(b.orientation, XrVector3f_ScalarMultiply(a.position, -1.0f));
return b;
}
static inline XrVector3f XrPosef_Transform(const XrPosef a, const XrVector3f v) {
XrVector3f r0 = XrQuaternionf_Rotate(a.orientation, v);
XrVector3f result;
XrVector3f_Add(&result, &r0, &a.position);
return result;
}
static inline XrPosef XrPosef_Multiply(const XrPosef a, const XrPosef b) {
XrPosef c;
XrQuaternionf_Multiply(&c.orientation, &b.orientation, &a.orientation);
c.position = XrPosef_Transform(a, b.position);
return c;
}
#endif //OPENXR_HELPERS_H_

View file

@ -0,0 +1,787 @@
// Copyright (c) 2017 The Khronos Group Inc.
// Copyright (c) 2016 Oculus VR, LLC.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: J.M.P. van Waveren
//
#ifndef XR_LINEAR_H_
#define XR_LINEAR_H_
#if defined(OS_LINUX_XCB) || defined(OS_LINUX_XCB_GLX) || defined(OS_LINUX_WAYLAND)
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wunused-function"
#endif
#include <openxr/openxr.h>
/*
================================================================================================
Description : Vector, matrix and quaternion math.
Author : J.M.P. van Waveren
Date : 12/10/2016
Language : C99
Format : Indent 4 spaces - no tabs.
Copyright : Copyright (c) 2016 Oculus VR, LLC. All Rights reserved.
DESCRIPTION
===========
All matrices are column-major.
INTERFACE
=========
XrVector2f
XrVector3f
XrVector4f
XrQuaternionf
XrMatrix4x4f
inline static void XrVector3f_Set(XrVector3f* v, const float value);
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value);
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction);
inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor);
inline static void XrVector3f_Normalize(XrVector3f* v);
inline static float XrVector3f_Length(const XrVector3f* v);
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction);
inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b;
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result);
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z);
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
const float degreesZ);
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z);
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
const XrQuaternionf* rotation, const XrVector3f* scale);
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, const float tanAngleLeft, const float tanAngleRight,
const float tanAngleUp, float const tanAngleDown, const float nearZ,
const float farZ);
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, const float fovDegreesLeft, const float fovDegreesRight,
const float fovDegreeUp, const float fovDegreesDown, const float nearZ,
const float farZ);
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* src);
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
const XrVector3f* maxs);
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon);
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon);
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon);
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon);
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src);
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src);
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src);
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b);
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src);
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src);
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src);
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v);
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v);
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
const XrVector3f* mins, const XrVector3f* maxs);
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs);
================================================================================================
*/
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#define MATH_PI 3.14159265358979323846f
#define DEFAULT_NEAR_Z 0.015625f // exact floating point representation
#define INFINITE_FAR_Z 0.0f
static const XrColor4f XrColorRed = {1.0f, 0.0f, 0.0f, 1.0f};
static const XrColor4f XrColorGreen = {0.0f, 1.0f, 0.0f, 1.0f};
static const XrColor4f XrColorBlue = {0.0f, 0.0f, 1.0f, 1.0f};
static const XrColor4f XrColorYellow = {1.0f, 1.0f, 0.0f, 1.0f};
static const XrColor4f XrColorPurple = {1.0f, 0.0f, 1.0f, 1.0f};
static const XrColor4f XrColorCyan = {0.0f, 1.0f, 1.0f, 1.0f};
static const XrColor4f XrColorLightGrey = {0.7f, 0.7f, 0.7f, 1.0f};
static const XrColor4f XrColorDarkGrey = {0.3f, 0.3f, 0.3f, 1.0f};
typedef enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D } GraphicsAPI;
// Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience.
typedef struct XrMatrix4x4f {
float m[16];
} XrMatrix4x4f;
inline static float XrRcpSqrt(const float x) {
const float SMALLEST_NON_DENORMAL = 1.1754943508222875e-038f; // ( 1U << 23 )
const float rcp = (x >= SMALLEST_NON_DENORMAL) ? 1.0f / sqrtf(x) : 1.0f;
return rcp;
}
inline static void XrVector3f_Set(XrVector3f* v, const float value) {
v->x = value;
v->y = value;
v->z = value;
}
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
result->x = a->x + b->x;
result->y = a->y + b->y;
result->z = a->z + b->z;
}
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
result->x = a->x - b->x;
result->y = a->y - b->y;
result->z = a->z - b->z;
}
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
result->x = (a->x < b->x) ? a->x : b->x;
result->y = (a->y < b->y) ? a->y : b->y;
result->z = (a->z < b->z) ? a->z : b->z;
}
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
result->x = (a->x > b->x) ? a->x : b->x;
result->y = (a->y > b->y) ? a->y : b->y;
result->z = (a->z > b->z) ? a->z : b->z;
}
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value) {
result->x = (fabsf(a->x) > value) ? ((a->x > 0.0f) ? (a->x - value) : (a->x + value)) : 0.0f;
result->y = (fabsf(a->y) > value) ? ((a->y > 0.0f) ? (a->y - value) : (a->y + value)) : 0.0f;
result->z = (fabsf(a->z) > value) ? ((a->z > 0.0f) ? (a->z - value) : (a->z + value)) : 0.0f;
}
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction) {
result->x = a->x + fraction * (b->x - a->x);
result->y = a->y + fraction * (b->y - a->y);
result->z = a->z + fraction * (b->z - a->z);
}
inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor) {
result->x = a->x * scaleFactor;
result->y = a->y * scaleFactor;
result->z = a->z * scaleFactor;
}
inline static float XrVector3f_Dot(const XrVector3f* a, const XrVector3f* b) { return a->x * b->x + a->y * b->y + a->z * b->z; }
// Compute cross product, which generates a normal vector.
// Direction vector can be determined by right-hand rule: Pointing index finder in
// direction a and middle finger in direction b, thumb will point in Cross(a, b).
inline static void XrVector3f_Cross(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
result->x = a->y * b->z - a->z * b->y;
result->y = a->z * b->x - a->x * b->z;
result->z = a->x * b->y - a->y * b->x;
}
inline static void XrVector3f_Normalize(XrVector3f* v) {
const float lengthRcp = XrRcpSqrt(v->x * v->x + v->y * v->y + v->z * v->z);
v->x *= lengthRcp;
v->y *= lengthRcp;
v->z *= lengthRcp;
}
inline static float XrVector3f_Length(const XrVector3f* v) { return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); }
inline static void XrQuaternionf_CreateFromAxisAngle(XrQuaternionf* result, const XrVector3f* axis, const float angleInRadians) {
float s = sinf(angleInRadians / 2.0f);
float lengthRcp = XrRcpSqrt(axis->x * axis->x + axis->y * axis->y + axis->z * axis->z);
result->x = s * axis->x * lengthRcp;
result->y = s * axis->y * lengthRcp;
result->z = s * axis->z * lengthRcp;
result->w = cosf(angleInRadians / 2.0f);
}
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction) {
const float s = a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w;
const float fa = 1.0f - fraction;
const float fb = (s < 0.0f) ? -fraction : fraction;
const float x = a->x * fa + b->x * fb;
const float y = a->y * fa + b->y * fb;
const float z = a->z * fa + b->z * fb;
const float w = a->w * fa + b->w * fb;
const float lengthRcp = XrRcpSqrt(x * x + y * y + z * z + w * w);
result->x = x * lengthRcp;
result->y = y * lengthRcp;
result->z = z * lengthRcp;
result->w = w * lengthRcp;
}
inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b) {
result->x = (b->w * a->x) + (b->x * a->w) + (b->y * a->z) - (b->z * a->y);
result->y = (b->w * a->y) - (b->x * a->z) + (b->y * a->w) + (b->z * a->x);
result->z = (b->w * a->z) + (b->x * a->y) - (b->y * a->x) + (b->z * a->w);
result->w = (b->w * a->w) - (b->x * a->x) - (b->y * a->y) - (b->z * a->z);
}
// Use left-multiplication to accumulate transformations.
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b) {
result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3];
result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3];
result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3];
result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3];
result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7];
result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7];
result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7];
result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7];
result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11];
result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11];
result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11];
result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11];
result->m[12] = a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
result->m[13] = a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
result->m[14] = a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
result->m[15] = a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
}
// Creates the transpose of the given matrix.
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
result->m[0] = src->m[0];
result->m[1] = src->m[4];
result->m[2] = src->m[8];
result->m[3] = src->m[12];
result->m[4] = src->m[1];
result->m[5] = src->m[5];
result->m[6] = src->m[9];
result->m[7] = src->m[13];
result->m[8] = src->m[2];
result->m[9] = src->m[6];
result->m[10] = src->m[10];
result->m[11] = src->m[14];
result->m[12] = src->m[3];
result->m[13] = src->m[7];
result->m[14] = src->m[11];
result->m[15] = src->m[15];
}
// Returns a 3x3 minor of a 4x4 matrix.
inline static float XrMatrix4x4f_Minor(const XrMatrix4x4f* matrix, int r0, int r1, int r2, int c0, int c1, int c2) {
return matrix->m[4 * r0 + c0] *
(matrix->m[4 * r1 + c1] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c1] * matrix->m[4 * r1 + c2]) -
matrix->m[4 * r0 + c1] *
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c2]) +
matrix->m[4 * r0 + c2] *
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c1] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c1]);
}
// Calculates the inverse of a 4x4 matrix.
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
const float rcpDet =
1.0f / (src->m[0] * XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) - src->m[1] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) +
src->m[2] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) - src->m[3] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2));
result->m[0] = XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) * rcpDet;
result->m[1] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 1, 2, 3) * rcpDet;
result->m[2] = XrMatrix4x4f_Minor(src, 0, 1, 3, 1, 2, 3) * rcpDet;
result->m[3] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 1, 2, 3) * rcpDet;
result->m[4] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) * rcpDet;
result->m[5] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 2, 3) * rcpDet;
result->m[6] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 2, 3) * rcpDet;
result->m[7] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 2, 3) * rcpDet;
result->m[8] = XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) * rcpDet;
result->m[9] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 3) * rcpDet;
result->m[10] = XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 3) * rcpDet;
result->m[11] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 3) * rcpDet;
result->m[12] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2) * rcpDet;
result->m[13] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 2) * rcpDet;
result->m[14] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 2) * rcpDet;
result->m[15] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 2) * rcpDet;
}
// Calculates the inverse of a rigid body transform.
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
result->m[0] = src->m[0];
result->m[1] = src->m[4];
result->m[2] = src->m[8];
result->m[3] = 0.0f;
result->m[4] = src->m[1];
result->m[5] = src->m[5];
result->m[6] = src->m[9];
result->m[7] = 0.0f;
result->m[8] = src->m[2];
result->m[9] = src->m[6];
result->m[10] = src->m[10];
result->m[11] = 0.0f;
result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]);
result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]);
result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]);
result->m[15] = 1.0f;
}
// Creates an identity matrix.
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result) {
result->m[0] = 1.0f;
result->m[1] = 0.0f;
result->m[2] = 0.0f;
result->m[3] = 0.0f;
result->m[4] = 0.0f;
result->m[5] = 1.0f;
result->m[6] = 0.0f;
result->m[7] = 0.0f;
result->m[8] = 0.0f;
result->m[9] = 0.0f;
result->m[10] = 1.0f;
result->m[11] = 0.0f;
result->m[12] = 0.0f;
result->m[13] = 0.0f;
result->m[14] = 0.0f;
result->m[15] = 1.0f;
}
// Creates a translation matrix.
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z) {
result->m[0] = 1.0f;
result->m[1] = 0.0f;
result->m[2] = 0.0f;
result->m[3] = 0.0f;
result->m[4] = 0.0f;
result->m[5] = 1.0f;
result->m[6] = 0.0f;
result->m[7] = 0.0f;
result->m[8] = 0.0f;
result->m[9] = 0.0f;
result->m[10] = 1.0f;
result->m[11] = 0.0f;
result->m[12] = x;
result->m[13] = y;
result->m[14] = z;
result->m[15] = 1.0f;
}
// Creates a rotation matrix.
// If -Z=forward, +Y=up, +X=right, then degreesX=pitch, degreesY=yaw, degreesZ=roll.
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
const float degreesZ) {
const float sinX = sinf(degreesX * (MATH_PI / 180.0f));
const float cosX = cosf(degreesX * (MATH_PI / 180.0f));
const XrMatrix4x4f rotationX = {{1, 0, 0, 0, 0, cosX, sinX, 0, 0, -sinX, cosX, 0, 0, 0, 0, 1}};
const float sinY = sinf(degreesY * (MATH_PI / 180.0f));
const float cosY = cosf(degreesY * (MATH_PI / 180.0f));
const XrMatrix4x4f rotationY = {{cosY, 0, -sinY, 0, 0, 1, 0, 0, sinY, 0, cosY, 0, 0, 0, 0, 1}};
const float sinZ = sinf(degreesZ * (MATH_PI / 180.0f));
const float cosZ = cosf(degreesZ * (MATH_PI / 180.0f));
const XrMatrix4x4f rotationZ = {{cosZ, sinZ, 0, 0, -sinZ, cosZ, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
XrMatrix4x4f rotationXY;
XrMatrix4x4f_Multiply(&rotationXY, &rotationY, &rotationX);
XrMatrix4x4f_Multiply(result, &rotationZ, &rotationXY);
}
// Creates a scale matrix.
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z) {
result->m[0] = x;
result->m[1] = 0.0f;
result->m[2] = 0.0f;
result->m[3] = 0.0f;
result->m[4] = 0.0f;
result->m[5] = y;
result->m[6] = 0.0f;
result->m[7] = 0.0f;
result->m[8] = 0.0f;
result->m[9] = 0.0f;
result->m[10] = z;
result->m[11] = 0.0f;
result->m[12] = 0.0f;
result->m[13] = 0.0f;
result->m[14] = 0.0f;
result->m[15] = 1.0f;
}
// Creates a matrix from a quaternion.
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* quat) {
const float x2 = quat->x + quat->x;
const float y2 = quat->y + quat->y;
const float z2 = quat->z + quat->z;
const float xx2 = quat->x * x2;
const float yy2 = quat->y * y2;
const float zz2 = quat->z * z2;
const float yz2 = quat->y * z2;
const float wx2 = quat->w * x2;
const float xy2 = quat->x * y2;
const float wz2 = quat->w * z2;
const float xz2 = quat->x * z2;
const float wy2 = quat->w * y2;
result->m[0] = 1.0f - yy2 - zz2;
result->m[1] = xy2 + wz2;
result->m[2] = xz2 - wy2;
result->m[3] = 0.0f;
result->m[4] = xy2 - wz2;
result->m[5] = 1.0f - xx2 - zz2;
result->m[6] = yz2 + wx2;
result->m[7] = 0.0f;
result->m[8] = xz2 + wy2;
result->m[9] = yz2 - wx2;
result->m[10] = 1.0f - xx2 - yy2;
result->m[11] = 0.0f;
result->m[12] = 0.0f;
result->m[13] = 0.0f;
result->m[14] = 0.0f;
result->m[15] = 1.0f;
}
// Creates a combined translation(rotation(scale(object))) matrix.
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
const XrQuaternionf* rotation, const XrVector3f* scale) {
XrMatrix4x4f scaleMatrix;
XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z);
XrMatrix4x4f rotationMatrix;
XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
XrMatrix4x4f translationMatrix;
XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
XrMatrix4x4f combinedMatrix;
XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix);
XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix);
}
// Creates a projection matrix based on the specified dimensions.
// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
// The far plane is placed at infinity if farZ <= nearZ.
// An infinite projection matrix is preferred for rasterization because, except for
// things *right* up against the near plane, it always provides better precision:
// "Tightening the Precision of Perspective Rendering"
// Paul Upchurch, Mathieu Desbrun
// Journal of Graphics Tools, Volume 16, Issue 1, 2012
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
const float nearZ, const float farZ) {
const float tanAngleWidth = tanAngleRight - tanAngleLeft;
// Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
// Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
// Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
// Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;
if (farZ <= nearZ) {
// place the far plane at infinity
result->m[0] = 2.0f / tanAngleWidth;
result->m[4] = 0.0f;
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result->m[12] = 0.0f;
result->m[1] = 0.0f;
result->m[5] = 2.0f / tanAngleHeight;
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
result->m[13] = 0.0f;
result->m[2] = 0.0f;
result->m[6] = 0.0f;
result->m[10] = -1.0f;
result->m[14] = -(nearZ + offsetZ);
result->m[3] = 0.0f;
result->m[7] = 0.0f;
result->m[11] = -1.0f;
result->m[15] = 0.0f;
} else {
// normal projection
result->m[0] = 2.0f / tanAngleWidth;
result->m[4] = 0.0f;
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result->m[12] = 0.0f;
result->m[1] = 0.0f;
result->m[5] = 2.0f / tanAngleHeight;
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
result->m[13] = 0.0f;
result->m[2] = 0.0f;
result->m[6] = 0.0f;
result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
result->m[3] = 0.0f;
result->m[7] = 0.0f;
result->m[11] = -1.0f;
result->m[15] = 0.0f;
}
}
// Creates a projection matrix based on the specified FOV.
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
const float nearZ, const float farZ) {
const float tanLeft = tanf(fov.angleLeft);
const float tanRight = tanf(fov.angleRight);
const float tanDown = tanf(fov.angleDown);
const float tanUp = tanf(fov.angleUp);
XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
}
// Creates a matrix that transforms the -1 to 1 cube to cover the given 'mins' and 'maxs' transformed with the given 'matrix'.
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
const XrVector3f* maxs) {
const XrVector3f offset = {(maxs->x + mins->x) * 0.5f, (maxs->y + mins->y) * 0.5f, (maxs->z + mins->z) * 0.5f};
const XrVector3f scale = {(maxs->x - mins->x) * 0.5f, (maxs->y - mins->y) * 0.5f, (maxs->z - mins->z) * 0.5f};
result->m[0] = matrix->m[0] * scale.x;
result->m[1] = matrix->m[1] * scale.x;
result->m[2] = matrix->m[2] * scale.x;
result->m[3] = matrix->m[3] * scale.x;
result->m[4] = matrix->m[4] * scale.y;
result->m[5] = matrix->m[5] * scale.y;
result->m[6] = matrix->m[6] * scale.y;
result->m[7] = matrix->m[7] * scale.y;
result->m[8] = matrix->m[8] * scale.z;
result->m[9] = matrix->m[9] * scale.z;
result->m[10] = matrix->m[10] * scale.z;
result->m[11] = matrix->m[11] * scale.z;
result->m[12] = matrix->m[12] + matrix->m[0] * offset.x + matrix->m[4] * offset.y + matrix->m[8] * offset.z;
result->m[13] = matrix->m[13] + matrix->m[1] * offset.x + matrix->m[5] * offset.y + matrix->m[9] * offset.z;
result->m[14] = matrix->m[14] + matrix->m[2] * offset.x + matrix->m[6] * offset.y + matrix->m[10] * offset.z;
result->m[15] = matrix->m[15] + matrix->m[3] * offset.x + matrix->m[7] * offset.y + matrix->m[11] * offset.z;
}
// Returns true if the given matrix is affine.
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon) {
return fabsf(matrix->m[3]) <= epsilon && fabsf(matrix->m[7]) <= epsilon && fabsf(matrix->m[11]) <= epsilon &&
fabsf(matrix->m[15] - 1.0f) <= epsilon;
}
// Returns true if the given matrix is orthogonal.
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i != j) {
if (fabsf(matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
matrix->m[4 * i + 2] * matrix->m[4 * j + 2]) > epsilon) {
return false;
}
if (fabsf(matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j]) > epsilon) {
return false;
}
}
}
}
return true;
}
// Returns true if the given matrix is orthonormal.
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
const float kd = (i == j) ? 1.0f : 0.0f; // Kronecker delta
if (fabsf(kd - (matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
matrix->m[4 * i + 2] * matrix->m[4 * j + 2])) > epsilon) {
return false;
}
if (fabsf(kd - (matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j])) > epsilon) {
return false;
}
}
}
return true;
}
// Returns true if the given matrix is a rigid body transform.
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon) {
return XrMatrix4x4f_IsAffine(matrix, epsilon) && XrMatrix4x4f_IsOrthonormal(matrix, epsilon);
}
// Get the translation from a combined translation(rotation(scale(object))) matrix.
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src) {
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
result->x = src->m[12];
result->y = src->m[13];
result->z = src->m[14];
}
// Get the rotation from a combined translation(rotation(scale(object))) matrix.
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src) {
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
const float rcpScaleX = XrRcpSqrt(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
const float rcpScaleY = XrRcpSqrt(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
const float rcpScaleZ = XrRcpSqrt(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
const float m[9] = {src->m[0] * rcpScaleX, src->m[1] * rcpScaleX, src->m[2] * rcpScaleX,
src->m[4] * rcpScaleY, src->m[5] * rcpScaleY, src->m[6] * rcpScaleY,
src->m[8] * rcpScaleZ, src->m[9] * rcpScaleZ, src->m[10] * rcpScaleZ};
if (m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] > 0.0f) {
float t = +m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
float s = XrRcpSqrt(t) * 0.5f;
result->w = s * t;
result->z = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
result->y = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
result->x = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
} else if (m[0 * 3 + 0] > m[1 * 3 + 1] && m[0 * 3 + 0] > m[2 * 3 + 2]) {
float t = +m[0 * 3 + 0] - m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
float s = XrRcpSqrt(t) * 0.5f;
result->x = s * t;
result->y = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
result->z = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
result->w = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
} else if (m[1 * 3 + 1] > m[2 * 3 + 2]) {
float t = -m[0 * 3 + 0] + m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
float s = XrRcpSqrt(t) * 0.5f;
result->y = s * t;
result->x = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
result->w = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
result->z = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
} else {
float t = -m[0 * 3 + 0] - m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
float s = XrRcpSqrt(t) * 0.5f;
result->z = s * t;
result->w = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
result->x = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
result->y = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
}
}
// Get the scale from a combined translation(rotation(scale(object))) matrix.
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src) {
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
result->x = sqrtf(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
result->y = sqrtf(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
result->z = sqrtf(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
}
// Transforms a 3D vector.
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v) {
const float w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15];
const float rcpW = 1.0f / w;
result->x = (m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12]) * rcpW;
result->y = (m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13]) * rcpW;
result->z = (m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14]) * rcpW;
}
// Transforms a 4D vector.
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v) {
result->x = m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12] * v->w;
result->y = m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13] * v->w;
result->z = m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14] * v->w;
result->w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15] * v->w;
}
// Transforms the 'mins' and 'maxs' bounds with the given 'matrix'.
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
const XrVector3f* mins, const XrVector3f* maxs) {
assert(XrMatrix4x4f_IsAffine(matrix, 1e-4f));
const XrVector3f center = {(mins->x + maxs->x) * 0.5f, (mins->y + maxs->y) * 0.5f, (mins->z + maxs->z) * 0.5f};
const XrVector3f extents = {maxs->x - center.x, maxs->y - center.y, maxs->z - center.z};
const XrVector3f newCenter = {matrix->m[0] * center.x + matrix->m[4] * center.y + matrix->m[8] * center.z + matrix->m[12],
matrix->m[1] * center.x + matrix->m[5] * center.y + matrix->m[9] * center.z + matrix->m[13],
matrix->m[2] * center.x + matrix->m[6] * center.y + matrix->m[10] * center.z + matrix->m[14]};
const XrVector3f newExtents = {
fabsf(extents.x * matrix->m[0]) + fabsf(extents.y * matrix->m[4]) + fabsf(extents.z * matrix->m[8]),
fabsf(extents.x * matrix->m[1]) + fabsf(extents.y * matrix->m[5]) + fabsf(extents.z * matrix->m[9]),
fabsf(extents.x * matrix->m[2]) + fabsf(extents.y * matrix->m[6]) + fabsf(extents.z * matrix->m[10])};
XrVector3f_Sub(resultMins, &newCenter, &newExtents);
XrVector3f_Add(resultMaxs, &newCenter, &newExtents);
}
// Returns true if the 'mins' and 'maxs' bounds is completely off to one side of the projection matrix.
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs) {
if (maxs->x <= mins->x && maxs->y <= mins->y && maxs->z <= mins->z) {
return false;
}
XrVector4f c[8];
for (int i = 0; i < 8; i++) {
const XrVector4f corner = {(i & 1) != 0 ? maxs->x : mins->x, (i & 2) != 0 ? maxs->y : mins->y,
(i & 4) != 0 ? maxs->z : mins->z, 1.0f};
XrMatrix4x4f_TransformVector4f(&c[i], mvp, &corner);
}
int i;
for (i = 0; i < 8; i++) {
if (c[i].x > -c[i].w) {
break;
}
}
if (i == 8) {
return true;
}
for (i = 0; i < 8; i++) {
if (c[i].x < c[i].w) {
break;
}
}
if (i == 8) {
return true;
}
for (i = 0; i < 8; i++) {
if (c[i].y > -c[i].w) {
break;
}
}
if (i == 8) {
return true;
}
for (i = 0; i < 8; i++) {
if (c[i].y < c[i].w) {
break;
}
}
if (i == 8) {
return true;
}
for (i = 0; i < 8; i++) {
if (c[i].z > -c[i].w) {
break;
}
}
if (i == 8) {
return true;
}
for (i = 0; i < 8; i++) {
if (c[i].z < c[i].w) {
break;
}
}
return i == 8;
}
#endif // XR_LINEAR_H_

View file

@ -0,0 +1,569 @@
#include "VrCommon.h"
extern ovrApp gAppState;
XrResult CheckXrResult(XrResult res, const char* originator) {
if (XR_FAILED(res)) {
ALOGE("error: %s", originator);
}
return res;
}
#define CHECK_XRCMD(cmd) CheckXrResult(cmd, #cmd);
#define SIDE_LEFT 0
#define SIDE_RIGHT 1
#define SIDE_COUNT 2
XrActionSet actionSet = NULL;
XrAction grabAction = 0;
XrAction poseAction = 0;
XrAction vibrateAction = 0;
XrAction quitAction = 0;
XrAction touchpadAction = 0;
XrAction AXAction = 0;
XrAction homeAction = 0;
XrAction BYAction = 0;
XrAction backAction = 0;
XrAction sideAction = 0;
XrAction triggerAction = 0;
XrAction joystickAction = 0;
XrAction batteryAction = 0;
XrAction AXTouchAction = 0;
XrAction BYTouchAction = 0;
XrAction thumbstickTouchAction = 0;
XrAction TriggerTouchAction = 0;
XrAction ThumbrestTouchAction = 0;
XrAction GripAction = 0;
XrAction AAction = 0;
XrAction BAction = 0;
XrAction XAction = 0;
XrAction YAction = 0;
XrAction ATouchAction = 0;
XrAction BTouchAction = 0;
XrAction XTouchAction = 0;
XrAction YTouchAction = 0;
XrAction aimAction = 0;
XrSpace aimSpace[SIDE_COUNT];
XrPath handSubactionPath[SIDE_COUNT];
XrSpace handSpace[SIDE_COUNT];
XrActionSuggestedBinding ActionSuggestedBinding(XrAction action, XrPath path) {
XrActionSuggestedBinding asb;
asb.action = action;
asb.binding = path;
return asb;
}
XrActionStateBoolean GetActionStateBoolean(XrAction action, int hand) {
XrActionStateGetInfo getInfo = {};
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
getInfo.action = action;
getInfo.next = NULL;
if (hand >= 0)
getInfo.subactionPath = handSubactionPath[hand];
XrActionStateBoolean state = {};
state.type = XR_TYPE_ACTION_STATE_BOOLEAN;
state.next = NULL;
CHECK_XRCMD(xrGetActionStateBoolean(gAppState.Session, &getInfo, &state));
return state;
}
XrActionStateFloat GetActionStateFloat(XrAction action, int hand) {
XrActionStateGetInfo getInfo = {};
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
getInfo.action = action;
getInfo.next = NULL;
if (hand >= 0)
getInfo.subactionPath = handSubactionPath[hand];
XrActionStateFloat state = {};
state.type = XR_TYPE_ACTION_STATE_FLOAT;
state.next = NULL;
CHECK_XRCMD(xrGetActionStateFloat(gAppState.Session, &getInfo, &state));
return state;
}
XrActionStateVector2f GetActionStateVector2(XrAction action, int hand) {
XrActionStateGetInfo getInfo = {};
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
getInfo.action = action;
getInfo.next = NULL;
if (hand >= 0)
getInfo.subactionPath = handSubactionPath[hand];
XrActionStateVector2f state = {};
state.type = XR_TYPE_ACTION_STATE_VECTOR2F;
state.next = NULL;
CHECK_XRCMD(xrGetActionStateVector2f(gAppState.Session, &getInfo, &state));
return state;
}
void CreateAction(
XrActionSet actionSet,
XrActionType type,
const char* actionName,
const char* localizedName,
int countSubactionPaths,
XrPath* subactionPaths,
XrAction* action) {
ALOGV("CreateAction %s, %", actionName, countSubactionPaths);
XrActionCreateInfo aci = {};
aci.type = XR_TYPE_ACTION_CREATE_INFO;
aci.next = NULL;
aci.actionType = type;
if (countSubactionPaths > 0) {
aci.countSubactionPaths = countSubactionPaths;
aci.subactionPaths = subactionPaths;
}
strcpy(aci.actionName, actionName);
strcpy(aci.localizedActionName, localizedName ? localizedName : actionName);
*action = XR_NULL_HANDLE;
OXR(xrCreateAction(actionSet, &aci, action));
}
void TBXR_InitActions( void )
{
// Create an action set.
{
XrActionSetCreateInfo actionSetInfo = {};
actionSetInfo.type = XR_TYPE_ACTION_SET_CREATE_INFO;
strcpy(actionSetInfo.actionSetName, "gameplay");
strcpy(actionSetInfo.localizedActionSetName, "Gameplay");
actionSetInfo.priority = 0;
actionSetInfo.next = NULL;
CHECK_XRCMD(xrCreateActionSet(gAppState.Instance, &actionSetInfo, &actionSet));
}
// Get the XrPath for the left and right hands - we will use them as subaction paths.
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left", &handSubactionPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right", &handSubactionPath[SIDE_RIGHT]));
// Create actions.
{
// Create an input action for grabbing objects with the left and right hands.
CreateAction(actionSet, XR_ACTION_TYPE_POSE_INPUT, "grab_object", "Grab Object", SIDE_COUNT, handSubactionPath, &grabAction);
// Create an input action getting the left and right hand poses.
CreateAction(actionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose", "Hand Pose", SIDE_COUNT, handSubactionPath, &poseAction);
CreateAction(actionSet, XR_ACTION_TYPE_POSE_INPUT, "aim_pose", "Aim Pose", SIDE_COUNT, handSubactionPath, &aimAction);
// Create output actions for vibrating the left and right controller.
CreateAction(actionSet, XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_hand", "Vibrate Hand", SIDE_COUNT, handSubactionPath, &vibrateAction);
//All remaining actions (not necessarily supported by all controllers)
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "quit_session", "Quit Session", SIDE_COUNT, handSubactionPath, &quitAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "touchpad", "Touchpad", SIDE_COUNT, handSubactionPath, &touchpadAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "axkey", "AXkey", SIDE_COUNT, handSubactionPath, &AXAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "homekey", "Homekey", SIDE_COUNT, handSubactionPath, &homeAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "bykey", "BYkey", SIDE_COUNT, handSubactionPath, &BYAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "backkey", "Backkey", SIDE_COUNT, handSubactionPath, &backAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "sidekey", "Sidekey", SIDE_COUNT, handSubactionPath, &sideAction);
CreateAction(actionSet, XR_ACTION_TYPE_FLOAT_INPUT, "trigger", "Trigger", SIDE_COUNT, handSubactionPath, &triggerAction);
CreateAction(actionSet, XR_ACTION_TYPE_VECTOR2F_INPUT, "joystick", "Joystick", SIDE_COUNT, handSubactionPath, &joystickAction);
CreateAction(actionSet, XR_ACTION_TYPE_FLOAT_INPUT, "battery", "battery", SIDE_COUNT, handSubactionPath, &batteryAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "axtouch", "AXtouch", SIDE_COUNT, handSubactionPath, &AXTouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "bytouch", "BYtouch", SIDE_COUNT, handSubactionPath, &BYTouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "rockertouch", "Rockertouch", SIDE_COUNT, handSubactionPath, &thumbstickTouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "triggertouch", "Triggertouch", SIDE_COUNT, handSubactionPath, &TriggerTouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbresttouch", "Thumbresttouch", SIDE_COUNT, handSubactionPath, &ThumbrestTouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_FLOAT_INPUT, "gripvalue", "GripValue", SIDE_COUNT, handSubactionPath, &GripAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "akey", "Akey", SIDE_COUNT, handSubactionPath, &AAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "bkey", "Bkey", SIDE_COUNT, handSubactionPath, &BAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "xkey", "Xkey", SIDE_COUNT, handSubactionPath, &XAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "ykey", "Ykey", SIDE_COUNT, handSubactionPath, &YAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "atouch", "Atouch", SIDE_COUNT, handSubactionPath, &ATouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "btouch", "Btouch", SIDE_COUNT, handSubactionPath, &BTouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "xtouch", "Xtouch", SIDE_COUNT, handSubactionPath, &XTouchAction);
CreateAction(actionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "ytouch", "Ytouch", SIDE_COUNT, handSubactionPath, &YTouchAction);
}
XrPath selectPath[SIDE_COUNT];
XrPath squeezeValuePath[SIDE_COUNT];
XrPath squeezeClickPath[SIDE_COUNT];
XrPath posePath[SIDE_COUNT];
XrPath hapticPath[SIDE_COUNT];
XrPath menuClickPath[SIDE_COUNT];
XrPath systemPath[SIDE_COUNT];
XrPath thumbrestPath[SIDE_COUNT];
XrPath triggerTouchPath[SIDE_COUNT];
XrPath triggerValuePath[SIDE_COUNT];
XrPath thumbstickClickPath[SIDE_COUNT];
XrPath thumbstickTouchPath[SIDE_COUNT];
XrPath thumbstickPosPath[SIDE_COUNT];
XrPath aimPath[SIDE_COUNT];
XrPath touchpadPath[SIDE_COUNT];
XrPath AXValuePath[SIDE_COUNT];
XrPath homeClickPath[SIDE_COUNT];
XrPath BYValuePath[SIDE_COUNT];
XrPath backPath[SIDE_COUNT];
XrPath sideClickPath[SIDE_COUNT];
XrPath triggerPath[SIDE_COUNT];
XrPath joystickPath[SIDE_COUNT];
XrPath batteryPath[SIDE_COUNT];
XrPath GripPath[SIDE_COUNT];
XrPath AXTouchPath[SIDE_COUNT];
XrPath BYTouchPath[SIDE_COUNT];
XrPath RockerTouchPath[SIDE_COUNT];
XrPath TriggerTouchPath[SIDE_COUNT];
XrPath ThumbresetTouchPath[SIDE_COUNT];
XrPath AValuePath[SIDE_COUNT];
XrPath BValuePath[SIDE_COUNT];
XrPath XValuePath[SIDE_COUNT];
XrPath YValuePath[SIDE_COUNT];
XrPath ATouchPath[SIDE_COUNT];
XrPath BTouchPath[SIDE_COUNT];
XrPath XTouchPath[SIDE_COUNT];
XrPath YTouchPath[SIDE_COUNT];
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/select/click", &selectPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/select/click", &selectPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/menu/click", &menuClickPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/menu/click", &menuClickPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/squeeze/value", &squeezeValuePath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/squeeze/value", &squeezeValuePath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/squeeze/click", &squeezeClickPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/squeeze/click", &squeezeClickPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/grip/pose", &posePath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/grip/pose", &posePath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/aim/pose", &aimPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/aim/pose", &aimPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/output/haptic", &hapticPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/output/haptic", &hapticPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/trigger/touch", &triggerTouchPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/trigger/touch", &triggerTouchPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/trigger/value", &triggerValuePath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/trigger/value", &triggerValuePath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/thumbstick/click", &thumbstickClickPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/thumbstick/click", &thumbstickClickPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/thumbstick/touch", &thumbstickTouchPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/thumbstick/touch", &thumbstickTouchPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/thumbstick", &thumbstickPosPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/thumbstick", &thumbstickPosPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/system/click", &systemPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/system/click", &systemPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/thumbrest/touch", &thumbrestPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/thumbrest/touch", &thumbrestPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/back/click", &backPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/back/click", &backPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/battery/value", &batteryPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/battery/value", &batteryPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/x/click", &XValuePath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/y/click", &YValuePath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/a/click", &AValuePath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/b/click", &BValuePath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/x/touch", &XTouchPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/left/input/y/touch", &YTouchPath[SIDE_LEFT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/a/touch", &ATouchPath[SIDE_RIGHT]));
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/user/hand/right/input/b/touch", &BTouchPath[SIDE_RIGHT]));
XrResult result;
//First try Pico Devices
{
XrPath picoMixedRealityInteractionProfilePath;
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/interaction_profiles/pico/neo3_controller",
&picoMixedRealityInteractionProfilePath));
XrActionSuggestedBinding bindings[128];
int currBinding = 0;
bindings[currBinding++] = ActionSuggestedBinding(touchpadAction, thumbstickClickPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(touchpadAction, thumbstickClickPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(joystickAction, thumbstickPosPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(joystickAction, thumbstickPosPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(thumbstickTouchAction, thumbstickTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(thumbstickTouchAction, thumbstickTouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(triggerAction, triggerValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(triggerAction, triggerValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(TriggerTouchAction, triggerTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(TriggerTouchAction, triggerTouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(sideAction, squeezeClickPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(sideAction, squeezeClickPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(GripAction, squeezeValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(GripAction, squeezeValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(poseAction, posePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(poseAction, posePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(homeAction, systemPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(homeAction, systemPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(backAction, backPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(backAction, backPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(batteryAction, batteryPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(batteryAction, batteryPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(ThumbrestTouchAction, thumbrestPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(ThumbrestTouchAction, thumbrestPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(vibrateAction, hapticPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(vibrateAction, hapticPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(XTouchAction, XTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(YTouchAction, YTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(ATouchAction, ATouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(BTouchAction, BTouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(XAction, XValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(YAction, YValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(AAction, AValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(BAction, BValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(aimAction, aimPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(aimAction, aimPath[SIDE_RIGHT]);
XrInteractionProfileSuggestedBinding suggestedBindings = {};
suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
suggestedBindings.interactionProfile = picoMixedRealityInteractionProfilePath;
suggestedBindings.suggestedBindings = bindings;
suggestedBindings.countSuggestedBindings = currBinding;
suggestedBindings.next = NULL;
result = xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings);
}
if (result != XR_SUCCESS)
{
XrPath touchControllerInteractionProfilePath;
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/interaction_profiles/oculus/touch_controller",
&touchControllerInteractionProfilePath));
XrActionSuggestedBinding bindings[128];
int currBinding = 0;
bindings[currBinding++] = ActionSuggestedBinding(touchpadAction, thumbstickClickPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(touchpadAction, thumbstickClickPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(joystickAction, thumbstickPosPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(joystickAction, thumbstickPosPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(thumbstickTouchAction, thumbstickTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(thumbstickTouchAction, thumbstickTouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(triggerAction, triggerValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(triggerAction, triggerValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(TriggerTouchAction, triggerTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(TriggerTouchAction, triggerTouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(GripAction, squeezeValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(GripAction, squeezeValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(poseAction, posePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(poseAction, posePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(backAction, menuClickPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(ThumbrestTouchAction, thumbrestPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(ThumbrestTouchAction, thumbrestPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(vibrateAction, hapticPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(vibrateAction, hapticPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(XTouchAction, XTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(YTouchAction, YTouchPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(ATouchAction, ATouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(BTouchAction, BTouchPath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(XAction, XValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(YAction, YValuePath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(AAction, AValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(BAction, BValuePath[SIDE_RIGHT]);
bindings[currBinding++] = ActionSuggestedBinding(aimAction, aimPath[SIDE_LEFT]);
bindings[currBinding++] = ActionSuggestedBinding(aimAction, aimPath[SIDE_RIGHT]);
XrInteractionProfileSuggestedBinding suggestedBindings = {};
suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
suggestedBindings.interactionProfile = touchControllerInteractionProfilePath;
suggestedBindings.suggestedBindings = bindings;
suggestedBindings.countSuggestedBindings = currBinding;
suggestedBindings.next = NULL;
result = xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings);
}
XrActionSpaceCreateInfo actionSpaceInfo = {};
actionSpaceInfo.type = XR_TYPE_ACTION_SPACE_CREATE_INFO;
actionSpaceInfo.action = poseAction;
actionSpaceInfo.poseInActionSpace.orientation.w = 1.f;
actionSpaceInfo.subactionPath = handSubactionPath[SIDE_LEFT];
CHECK_XRCMD(xrCreateActionSpace(gAppState.Session, &actionSpaceInfo, &handSpace[SIDE_LEFT]));
actionSpaceInfo.subactionPath = handSubactionPath[SIDE_RIGHT];
CHECK_XRCMD(xrCreateActionSpace(gAppState.Session, &actionSpaceInfo, &handSpace[SIDE_RIGHT]));
actionSpaceInfo.action = aimAction;
actionSpaceInfo.poseInActionSpace.orientation.w = 1.f;
actionSpaceInfo.subactionPath = handSubactionPath[SIDE_LEFT];
CHECK_XRCMD(xrCreateActionSpace(gAppState.Session, &actionSpaceInfo, &aimSpace[SIDE_LEFT]));
actionSpaceInfo.subactionPath = handSubactionPath[SIDE_RIGHT];
actionSpaceInfo.next = NULL;
CHECK_XRCMD(xrCreateActionSpace(gAppState.Session, &actionSpaceInfo, &aimSpace[SIDE_RIGHT]));
XrSessionActionSetsAttachInfo attachInfo = {};
attachInfo.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO;
attachInfo.countActionSets = 1;
attachInfo.actionSets = &actionSet;
attachInfo.next = NULL;
CHECK_XRCMD(xrAttachSessionActionSets(gAppState.Session, &attachInfo));
}
void TBXR_SyncActions( void )
{
if (actionSet)
{
XrActiveActionSet activeActionSet = {};
activeActionSet.actionSet = actionSet;
activeActionSet.subactionPath = XR_NULL_PATH;
XrActionsSyncInfo syncInfo;
syncInfo.type = XR_TYPE_ACTIONS_SYNC_INFO;
syncInfo.countActiveActionSets = 1;
syncInfo.activeActionSets = &activeActionSet;
syncInfo.next = NULL;
CHECK_XRCMD(xrSyncActions(gAppState.Session, &syncInfo));
}
}
void TBXR_UpdateControllers( )
{
TBXR_SyncActions();
//get controller poses
for (int i = 0; i < 2; i++) {
XrSpaceVelocity vel = {};
vel.type = XR_TYPE_SPACE_VELOCITY;
XrSpaceLocation loc = {};
loc.type = XR_TYPE_SPACE_LOCATION;
loc.next = &vel;
XrResult res = xrLocateSpace(aimSpace[i], gAppState.CurrentSpace, gAppState.FrameState.predictedDisplayTime, &loc);
if (res != XR_SUCCESS) {
ALOGE("xrLocateSpace error: %d", (int)res);
}
gAppState.TrackedController[i].Active = (loc.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0;
gAppState.TrackedController[i].Pose = loc.pose;
gAppState.TrackedController[i].Velocity = vel;
}
leftRemoteTracking_new = gAppState.TrackedController[0];
rightRemoteTracking_new = gAppState.TrackedController[1];
//button mapping
leftTrackedRemoteState_new.Buttons = 0;
leftTrackedRemoteState_new.Touches = 0;
if (GetActionStateBoolean(backAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Enter;
if (GetActionStateBoolean(XAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_X;
if (GetActionStateBoolean(XTouchAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Touches |= xrButton_X;
if (GetActionStateBoolean(YAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Y;
if (GetActionStateBoolean(YTouchAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Touches |= xrButton_Y;
leftTrackedRemoteState_new.GripTrigger = GetActionStateFloat(GripAction, SIDE_LEFT).currentState;
if (leftTrackedRemoteState_new.GripTrigger > 0.5f) leftTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
if (GetActionStateBoolean(touchpadAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_LThumb;
if (GetActionStateBoolean(touchpadAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Joystick;
if (GetActionStateBoolean(thumbstickTouchAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Touches |= xrButton_LThumb;
if (GetActionStateBoolean(thumbstickTouchAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Touches |= xrButton_Joystick;
leftTrackedRemoteState_new.IndexTrigger = GetActionStateFloat(triggerAction, SIDE_LEFT).currentState;
if (leftTrackedRemoteState_new.IndexTrigger > 0.5f) leftTrackedRemoteState_new.Buttons |= xrButton_Trigger;
if (GetActionStateBoolean(TriggerTouchAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Touches |= xrButton_Trigger;
if (GetActionStateBoolean(ThumbrestTouchAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Touches |= xrButton_ThumbRest;
rightTrackedRemoteState_new.Buttons = 0;
rightTrackedRemoteState_new.Touches = 0;
if (GetActionStateBoolean(backAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_Enter;
if (GetActionStateBoolean(AAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_A;
if (GetActionStateBoolean(ATouchAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Touches |= xrButton_A;
if (GetActionStateBoolean(BAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_B;
if (GetActionStateBoolean(BTouchAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Touches |= xrButton_B;
rightTrackedRemoteState_new.GripTrigger = GetActionStateFloat(GripAction, SIDE_RIGHT).currentState;
if (rightTrackedRemoteState_new.GripTrigger > 0.5f) rightTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
if (GetActionStateBoolean(touchpadAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_RThumb;
if (GetActionStateBoolean(touchpadAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_Joystick;
if (GetActionStateBoolean(thumbstickTouchAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Touches |= xrButton_RThumb;
if (GetActionStateBoolean(thumbstickTouchAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Touches |= xrButton_Joystick;
rightTrackedRemoteState_new.IndexTrigger = GetActionStateFloat(triggerAction, SIDE_RIGHT).currentState;
if (rightTrackedRemoteState_new.IndexTrigger > 0.5f) rightTrackedRemoteState_new.Buttons |= xrButton_Trigger;
if (GetActionStateBoolean(TriggerTouchAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Touches |= xrButton_Trigger;
if (GetActionStateBoolean(ThumbrestTouchAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Touches |= xrButton_ThumbRest;
//thumbstick
XrActionStateVector2f moveJoystickState;
moveJoystickState = GetActionStateVector2(joystickAction, SIDE_LEFT);
leftTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
leftTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
moveJoystickState = GetActionStateVector2(joystickAction, SIDE_RIGHT);
rightTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
rightTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
}
//0 = left, 1 = right
float vibration_channel_duration[2] = {0.0f, 0.0f};
float vibration_channel_intensity[2] = {0.0f, 0.0f};
void TBXR_Vibrate( int duration, int chan, float intensity )
{
for (int i = 0; i < 2; ++i)
{
int channel = i;
if ((i + 1) & chan)
{
if (vibration_channel_duration[channel] > 0.0f)
return;
if (vibration_channel_duration[channel] == -1.0f && duration != 0.0f)
return;
vibration_channel_duration[channel] = duration;
vibration_channel_intensity[channel] = intensity;
}
}
}
void TBXR_ProcessHaptics() {
static float lastFrameTime = 0.0f;
float timestamp = (float)(TBXR_GetTimeInMilliSeconds( ));
float frametime = timestamp - lastFrameTime;
lastFrameTime = timestamp;
for (int i = 0; i < 2; ++i) {
if (vibration_channel_duration[i] > 0.0f ||
vibration_channel_duration[i] == -1.0f) {
// fire haptics using output action
XrHapticVibration vibration = {};
vibration.type = XR_TYPE_HAPTIC_VIBRATION;
vibration.next = NULL;
vibration.amplitude = vibration_channel_intensity[i];
vibration.duration = ToXrTime(vibration_channel_duration[i]);
vibration.frequency = 3000;
XrHapticActionInfo hapticActionInfo = {};
hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO;
hapticActionInfo.next = NULL;
hapticActionInfo.action = vibrateAction;
hapticActionInfo.subactionPath = handSubactionPath[i];
OXR(xrApplyHapticFeedback(gAppState.Session, &hapticActionInfo, (const XrHapticBaseHeader*)&vibration));
if (vibration_channel_duration[i] != -1.0f) {
vibration_channel_duration[i] -= frametime;
if (vibration_channel_duration[i] < 0.0f) {
vibration_channel_duration[i] = 0.0f;
vibration_channel_intensity[i] = 0.0f;
}
}
} else {
// Stop haptics
XrHapticActionInfo hapticActionInfo = {};
hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO;
hapticActionInfo.next = NULL;
hapticActionInfo.action = vibrateAction;
hapticActionInfo.subactionPath = handSubactionPath[i];
OXR(xrStopHapticFeedback(gAppState.Session, &hapticActionInfo));
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,345 @@
#if !defined(tbxr_common_h)
#define tbxr_common_h
//OpenXR
#define XR_USE_GRAPHICS_API_OPENGL_ES 1
#define XR_USE_PLATFORM_ANDROID 1
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <jni.h>
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
#include <openxr_helpers.h>
#include <android/native_window_jni.h>
#include <android/log.h>
#include <stdbool.h>
#include <pthread.h>
#ifndef NDEBUG
#define DEBUG 1
#endif
#define LOG_TAG "TBXR"
#define ALOGE(...) __android_log_print( ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__ )
#if DEBUG
#define ALOGV(...) __android_log_print( ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__ )
#else
#define ALOGV(...)
#endif
enum { ovrMaxLayerCount = 1 };
enum { ovrMaxNumEyes = 2 };
typedef enum xrButton_ {
xrButton_A = 0x00000001, // Set for trigger pulled on the Gear VR and Go Controllers
xrButton_B = 0x00000002,
xrButton_RThumb = 0x00000004,
xrButton_RShoulder = 0x00000008,
xrButton_X = 0x00000100,
xrButton_Y = 0x00000200,
xrButton_LThumb = 0x00000400,
xrButton_LShoulder = 0x00000800,
xrButton_Up = 0x00010000,
xrButton_Down = 0x00020000,
xrButton_Left = 0x00040000,
xrButton_Right = 0x00080000,
xrButton_Enter = 0x00100000,
xrButton_Back = 0x00200000,
xrButton_GripTrigger = 0x04000000,
xrButton_Trigger = 0x20000000,
xrButton_Joystick = 0x80000000,
//Define additional controller touch points (not button presses)
xrButton_ThumbRest = 0x00000010,
xrButton_EnumSize = 0x7fffffff
} xrButton;
typedef struct {
uint32_t Buttons;
uint32_t Touches;
float IndexTrigger;
float GripTrigger;
XrVector2f Joystick;
} ovrInputStateTrackedRemote;
typedef struct {
GLboolean Active;
XrPosef Pose;
XrSpaceVelocity Velocity;
} ovrTrackedController;
typedef enum control_scheme {
RIGHT_HANDED_DEFAULT = 0,
LEFT_HANDED_DEFAULT = 10,
WEAPON_ALIGN = 99
} control_scheme_t;
typedef struct {
float M[4][4];
} ovrMatrix4f;
typedef struct {
XrSwapchain Handle;
uint32_t Width;
uint32_t Height;
} ovrSwapChain;
typedef struct {
int Width;
int Height;
int Multisamples;
uint32_t TextureSwapChainLength;
uint32_t TextureSwapChainIndex;
ovrSwapChain ColorSwapChain;
XrSwapchainImageOpenGLESKHR* ColorSwapChainImage;
GLuint* DepthBuffers;
GLuint* FrameBuffers;
} ovrFramebuffer;
/*
================================================================================
ovrRenderer
================================================================================
*/
typedef struct
{
ovrFramebuffer FrameBuffer[ovrMaxNumEyes];
} ovrRenderer;
/*
================================================================================
ovrApp
================================================================================
*/
typedef enum
{
MQ_WAIT_NONE, // don't wait
MQ_WAIT_RECEIVED, // wait until the consumer thread has received the message
MQ_WAIT_PROCESSED // wait until the consumer thread has processed the message
} ovrMQWait;
#define MAX_MESSAGE_PARMS 8
#define MAX_MESSAGES 1024
typedef struct
{
int Id;
ovrMQWait Wait;
long long Parms[MAX_MESSAGE_PARMS];
} srufaceMessage;
typedef struct
{
srufaceMessage Messages[MAX_MESSAGES];
volatile int Head; // dequeue at the head
volatile int Tail; // enqueue at the tail
ovrMQWait Wait;
volatile bool EnabledFlag;
volatile bool PostedFlag;
volatile bool ReceivedFlag;
volatile bool ProcessedFlag;
pthread_mutex_t Mutex;
pthread_cond_t PostedCondition;
pthread_cond_t ReceivedCondition;
pthread_cond_t ProcessedCondition;
} surfaceMessageQueue;
typedef struct
{
JavaVM * JavaVm;
jobject ActivityObject;
jclass ActivityClass;
pthread_t Thread;
surfaceMessageQueue MessageQueue;
ANativeWindow * NativeWindow;
} ovrAppThread;
typedef union {
XrCompositionLayerProjection Projection;
XrCompositionLayerQuad Quad;
} xrCompositorLayer_Union;
#define GL(func) func;
// Forward declarations
XrInstance TBXR_GetXrInstance();
#if defined(DEBUG)
static void
OXR_CheckErrors(XrInstance instance, XrResult result, const char* function, bool failOnError) {
if (XR_FAILED(result)) {
char errorBuffer[XR_MAX_RESULT_STRING_SIZE];
xrResultToString(instance, result, errorBuffer);
if (failOnError) {
ALOGE("OpenXR error: %s: %s\n", function, errorBuffer);
} else {
ALOGV("OpenXR error: %s: %s\n", function, errorBuffer);
}
}
}
#endif
#if defined(DEBUG)
#define OXR(func) OXR_CheckErrors(TBXR_GetXrInstance(), func, #func, true);
#else
#define OXR(func) func;
#endif
typedef struct {
EGLint MajorVersion;
EGLint MinorVersion;
EGLDisplay Display;
EGLConfig Config;
EGLSurface TinySurface;
EGLSurface MainSurface;
EGLContext Context;
} ovrEgl;
/// Java details about an activity
typedef struct ovrJava_ {
JavaVM* Vm; //< Java Virtual Machine
JNIEnv* Env; //< Thread specific environment
jobject ActivityObject; //< Java activity object
} ovrJava;
typedef struct
{
ovrJava Java;
ovrEgl Egl;
ANativeWindow* NativeWindow;
bool Resumed;
bool Focused;
bool Visible;
bool FrameSetup;
char* OpenXRHMD;
float Width;
float Height;
XrInstance Instance;
XrSession Session;
XrViewConfigurationProperties ViewportConfig;
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
XrSystemId SystemId;
XrSpace HeadSpace;
XrSpace StageSpace;
XrSpace FakeStageSpace;
XrSpace CurrentSpace;
GLboolean SessionActive;
XrPosef xfStageFromHead;
XrView* Projections;
XrMatrix4x4f ProjectionMatrices[2];
float currentDisplayRefreshRate;
float* SupportedDisplayRefreshRates;
uint32_t RequestedDisplayRefreshRateIndex;
uint32_t NumSupportedDisplayRefreshRates;
PFN_xrGetDisplayRefreshRateFB pfnGetDisplayRefreshRate;
PFN_xrRequestDisplayRefreshRateFB pfnRequestDisplayRefreshRate;
XrFrameState FrameState;
int SwapInterval;
int MainThreadTid;
int RenderThreadTid;
xrCompositorLayer_Union Layers[ovrMaxLayerCount];
int LayerCount;
ovrRenderer Renderer;
ovrTrackedController TrackedController[2];
} ovrApp;
enum
{
MESSAGE_ON_CREATE,
MESSAGE_ON_START,
MESSAGE_ON_RESUME,
MESSAGE_ON_PAUSE,
MESSAGE_ON_STOP,
MESSAGE_ON_DESTROY,
MESSAGE_ON_SURFACE_CREATED,
MESSAGE_ON_SURFACE_DESTROYED
};
extern ovrAppThread * gAppThread;
extern ovrApp gAppState;
extern ovrJava java;
void ovrTrackedController_Clear(ovrTrackedController* controller);
void * AppThreadFunction(void * parm );
void ovrAppThread_Create( ovrAppThread * appThread, JNIEnv * env, jobject activityObject, jclass activityClass );
void ovrAppThread_Destroy( ovrAppThread * appThread, JNIEnv * env );
void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out);
/*
* Surface Lifecycle Message Queue
*/
void surfaceMessage_Init(srufaceMessage * message, const int id, const int wait );
void * surfaceMessage_GetPointerParm(srufaceMessage * message, int index );
void surfaceMessage_SetPointerParm(srufaceMessage * message, int index, void * ptr );
void surfaceMessageQueue_Create(surfaceMessageQueue * messageQueue );
void surfaceMessageQueue_Destroy(surfaceMessageQueue * messageQueue );
void surfaceMessageQueue_Enable(surfaceMessageQueue * messageQueue, const bool set );
void surfaceMessageQueue_PostMessage(surfaceMessageQueue * messageQueue, const srufaceMessage * message );
//Functions that need to be implemented by the game specific code
void VR_FrameSetup();
bool VR_UseScreenLayer();
float VR_GetScreenLayerDistance();
bool VR_GetVRProjection(int eye, float zNear, float zFar, float* projection);
void VR_HandleControllerInput();
void VR_SetHMDOrientation(float pitch, float yaw, float roll );
void VR_SetHMDPosition(float x, float y, float z );
void VR_HapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight );
void VR_HapticUpdateEvent(const char* event, int intensity, float angle );
void VR_HapticEndFrame();
void VR_HapticStopEvent(const char* event);
void VR_HapticEnable();
void VR_HapticDisable();
void VR_Shutdown();
//Reusable Team Beef OpenXR stuff (in TBXR_Common.cpp)
double TBXR_GetTimeInMilliSeconds();
int TBXR_GetRefresh();
void TBXR_Recenter();
void TBXR_InitialiseOpenXR();
void TBXR_WaitForSessionActive();
void TBXR_InitRenderer();
void TBXR_EnterVR();
void TBXR_LeaveVR( );
void TBXR_GetScreenRes(int *width, int *height);
void TBXR_InitActions( void );
void TBXR_Vibrate(int duration, int channel, float intensity );
void TBXR_ProcessHaptics();
void TBXR_FrameSetup();
void TBXR_updateProjections();
void TBXR_UpdateControllers( );
void TBXR_prepareEyeBuffer(int eye );
void TBXR_finishEyeBuffer(int eye );
void TBXR_submitFrame();
#endif //vrcommon_h

View file

@ -1,13 +1,12 @@
#if !defined(vrcommon_h)
#define vrcommon_h
//#include <VrApi_Ext.h>
#include <VrApi_Input.h>
#include <android/log.h>
#include "../darkplaces/mathlib.h"
#include "TBXR_Common.h"
#define LOG_TAG "QuakeQuest"
#ifndef NDEBUG
@ -22,17 +21,21 @@
#define ALOGV(...)
#endif
float playerHeight;
float playerYaw;
extern ovrInputStateTrackedRemote leftTrackedRemoteState_old;
extern ovrInputStateTrackedRemote leftTrackedRemoteState_new;
extern ovrTrackedController leftRemoteTracking_new;
extern ovrInputStateTrackedRemote rightTrackedRemoteState_old;
extern ovrInputStateTrackedRemote rightTrackedRemoteState_new;
extern ovrTrackedController rightRemoteTracking_new;
extern float playerHeight;
extern float playerYaw;
extern vec3_t hmdorientation;
float radians(float deg);
float degrees(float rad);
qboolean isMultiplayer();
double GetTimeInMilliSeconds();
float length(float x, float y);
float nonLinearFilter(float in);
bool between(float min, float val, float max);
void QuatToYawPitchRoll(ovrQuatf q, float pitchAdjust, vec3_t out);
qboolean useScreenLayer();
#endif //vrcommon_h

View file

@ -1,595 +0,0 @@
/************************************************************************************
Filename : VrCompositor.c
*************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/prctl.h> // for prctl( PR_SET_NAME )
#include <android/log.h>
#include <android/window.h> // for AWINDOW_FLAG_KEEP_SCREEN_ON
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <VrApi.h>
#include <VrApi_Helpers.h>
#include "VrCompositor.h"
/*
================================================================================
renderState
================================================================================
*/
void getCurrentRenderState( renderState * state)
{
state->VertexBuffer = 0;
state->IndexBuffer = 0;
state->VertexArrayObject = 0;
state->Program = 0;
glGetIntegerv(GL_ARRAY_BUFFER, &state->VertexBuffer );
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER, &state->IndexBuffer );
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &state->VertexArrayObject );
glGetIntegerv(GL_CURRENT_PROGRAM, &state->Program );
}
void restoreRenderState( renderState * state )
{
GL( glUseProgram( state->Program ) );
GL( glBindVertexArray( state->VertexArrayObject ) );
GL( glBindBuffer( GL_ARRAY_BUFFER, state->VertexBuffer ) );
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, state->IndexBuffer ) );
}
/*
================================================================================
ovrGeometry
================================================================================
*/
enum VertexAttributeLocation
{
VERTEX_ATTRIBUTE_LOCATION_POSITION,
VERTEX_ATTRIBUTE_LOCATION_COLOR,
VERTEX_ATTRIBUTE_LOCATION_UV,
};
typedef struct
{
enum VertexAttributeLocation location;
const char * name;
} ovrVertexAttribute;
static ovrVertexAttribute ProgramVertexAttributes[] =
{
{ VERTEX_ATTRIBUTE_LOCATION_POSITION, "vertexPosition" },
{ VERTEX_ATTRIBUTE_LOCATION_COLOR, "vertexColor" },
{ VERTEX_ATTRIBUTE_LOCATION_UV, "vertexUv" },
};
static void ovrGeometry_Clear( ovrGeometry * geometry )
{
geometry->VertexBuffer = 0;
geometry->IndexBuffer = 0;
geometry->VertexArrayObject = 0;
geometry->VertexCount = 0;
geometry->IndexCount = 0;
for ( int i = 0; i < MAX_VERTEX_ATTRIB_POINTERS; i++ )
{
memset( &geometry->VertexAttribs[i], 0, sizeof( geometry->VertexAttribs[i] ) );
geometry->VertexAttribs[i].Index = -1;
}
}
static void ovrGeometry_CreateGroundPlane( ovrGeometry * geometry )
{
typedef struct
{
float positions[4][4];
unsigned char colors[4][4];
} ovrCubeVertices;
static const ovrCubeVertices cubeVertices =
{
// positions
{
{ 4.5f, -1.2f, 4.5f, 1.0f },
{ 4.5f, -1.2f, -4.5f, 1.0f },
{ -4.5f, -1.2f, -4.5f, 1.0f },
{ -4.5f, -1.2f, 4.5f, 1.0f }
},
// colors
{
{ 255, 0, 0, 255 },
{ 0, 255, 0, 255 },
{ 0, 0, 255, 255 },
{ 255, 255, 0, 255 },
},
};
static const unsigned short cubeIndices[6] =
{
0, 1, 2,
0, 2, 3,
};
geometry->VertexCount = 4;
geometry->IndexCount = 6;
geometry->VertexAttribs[0].Index = VERTEX_ATTRIBUTE_LOCATION_POSITION;
geometry->VertexAttribs[0].Size = 4;
geometry->VertexAttribs[0].Type = GL_FLOAT;
geometry->VertexAttribs[0].Normalized = false;
geometry->VertexAttribs[0].Stride = sizeof( cubeVertices.positions[0] );
geometry->VertexAttribs[0].Pointer = (const GLvoid *)offsetof( ovrCubeVertices, positions );
geometry->VertexAttribs[1].Index = VERTEX_ATTRIBUTE_LOCATION_COLOR;
geometry->VertexAttribs[1].Size = 4;
geometry->VertexAttribs[1].Type = GL_UNSIGNED_BYTE;
geometry->VertexAttribs[1].Normalized = true;
geometry->VertexAttribs[1].Stride = sizeof( cubeVertices.colors[0] );
geometry->VertexAttribs[1].Pointer = (const GLvoid *)offsetof( ovrCubeVertices, colors );
renderState state;
getCurrentRenderState(&state);
GL( glGenBuffers( 1, &geometry->VertexBuffer ) );
GL( glBindBuffer( GL_ARRAY_BUFFER, geometry->VertexBuffer ) );
GL( glBufferData( GL_ARRAY_BUFFER, sizeof( cubeVertices ), &cubeVertices, GL_STATIC_DRAW ) );
GL( glGenBuffers( 1, &geometry->IndexBuffer ) );
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, geometry->IndexBuffer ) );
GL( glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( cubeIndices ), cubeIndices, GL_STATIC_DRAW ) );
restoreRenderState(&state);
}
static void ovrGeometry_Destroy( ovrGeometry * geometry )
{
GL( glDeleteBuffers( 1, &geometry->IndexBuffer ) );
GL( glDeleteBuffers( 1, &geometry->VertexBuffer ) );
ovrGeometry_Clear( geometry );
}
static void ovrGeometry_CreateVAO( ovrGeometry * geometry )
{
renderState state;
getCurrentRenderState(&state);
GL( glGenVertexArrays( 1, &geometry->VertexArrayObject ) );
GL( glBindVertexArray( geometry->VertexArrayObject ) );
GL( glBindBuffer( GL_ARRAY_BUFFER, geometry->VertexBuffer ) );
for ( int i = 0; i < MAX_VERTEX_ATTRIB_POINTERS; i++ )
{
if ( geometry->VertexAttribs[i].Index != -1 )
{
GL( glEnableVertexAttribArray( geometry->VertexAttribs[i].Index ) );
GL( glVertexAttribPointer( geometry->VertexAttribs[i].Index, geometry->VertexAttribs[i].Size,
geometry->VertexAttribs[i].Type, geometry->VertexAttribs[i].Normalized,
geometry->VertexAttribs[i].Stride, geometry->VertexAttribs[i].Pointer ) );
}
}
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, geometry->IndexBuffer ) );
restoreRenderState(&state);
}
static void ovrGeometry_DestroyVAO( ovrGeometry * geometry )
{
GL( glDeleteVertexArrays( 1, &geometry->VertexArrayObject ) );
}
/*
================================================================================
ovrProgram
================================================================================
*/
typedef struct
{
enum
{
UNIFORM_VIEW_PROJ_MATRIX,
} index;
enum
{
UNIFORM_TYPE_VECTOR4,
UNIFORM_TYPE_MATRIX4X4,
UNIFORM_TYPE_INT,
UNIFORM_TYPE_BUFFER,
} type;
const char * name;
} ovrUniform;
static ovrUniform ProgramUniforms[] =
{
{ UNIFORM_VIEW_PROJ_MATRIX, UNIFORM_TYPE_MATRIX4X4, "viewProjectionMatrix" },
};
static void ovrProgram_Clear( ovrProgram * program )
{
program->Program = 0;
program->VertexShader = 0;
program->FragmentShader = 0;
memset( program->UniformLocation, 0, sizeof( program->UniformLocation ) );
memset( program->UniformBinding, 0, sizeof( program->UniformBinding ) );
memset( program->Textures, 0, sizeof( program->Textures ) );
}
static bool ovrProgram_Create( ovrProgram * program, const char * vertexSource, const char * fragmentSource )
{
GLint r;
GL( program->VertexShader = glCreateShader( GL_VERTEX_SHADER ) );
GL( glShaderSource( program->VertexShader, 1, &vertexSource, 0 ) );
GL( glCompileShader( program->VertexShader ) );
GL( glGetShaderiv( program->VertexShader, GL_COMPILE_STATUS, &r ) );
if ( r == GL_FALSE )
{
GLchar msg[4096];
GL( glGetShaderInfoLog( program->VertexShader, sizeof( msg ), 0, msg ) );
ALOGE( "%s\n%s\n", vertexSource, msg );
return false;
}
GL( program->FragmentShader = glCreateShader( GL_FRAGMENT_SHADER ) );
GL( glShaderSource( program->FragmentShader, 1, &fragmentSource, 0 ) );
GL( glCompileShader( program->FragmentShader ) );
GL( glGetShaderiv( program->FragmentShader, GL_COMPILE_STATUS, &r ) );
if ( r == GL_FALSE )
{
GLchar msg[4096];
GL( glGetShaderInfoLog( program->FragmentShader, sizeof( msg ), 0, msg ) );
ALOGE( "%s\n%s\n", fragmentSource, msg );
return false;
}
GL( program->Program = glCreateProgram() );
GL( glAttachShader( program->Program, program->VertexShader ) );
GL( glAttachShader( program->Program, program->FragmentShader ) );
// Bind the vertex attribute locations.
for ( int i = 0; i < sizeof( ProgramVertexAttributes ) / sizeof( ProgramVertexAttributes[0] ); i++ )
{
GL( glBindAttribLocation( program->Program, ProgramVertexAttributes[i].location, ProgramVertexAttributes[i].name ) );
}
GL( glLinkProgram( program->Program ) );
GL( glGetProgramiv( program->Program, GL_LINK_STATUS, &r ) );
if ( r == GL_FALSE )
{
GLchar msg[4096];
GL( glGetProgramInfoLog( program->Program, sizeof( msg ), 0, msg ) );
ALOGE( "Linking program failed: %s\n", msg );
return false;
}
int numBufferBindings = 0;
// Get the uniform locations.
memset( program->UniformLocation, -1, sizeof( program->UniformLocation ) );
for ( int i = 0; i < sizeof( ProgramUniforms ) / sizeof( ProgramUniforms[0] ); i++ )
{
const int uniformIndex = ProgramUniforms[i].index;
if ( ProgramUniforms[i].type == UNIFORM_TYPE_BUFFER )
{
GL( program->UniformLocation[uniformIndex] = glGetUniformBlockIndex( program->Program, ProgramUniforms[i].name ) );
program->UniformBinding[uniformIndex] = numBufferBindings++;
GL( glUniformBlockBinding( program->Program, program->UniformLocation[uniformIndex], program->UniformBinding[uniformIndex] ) );
}
else
{
GL( program->UniformLocation[uniformIndex] = glGetUniformLocation( program->Program, ProgramUniforms[i].name ) );
program->UniformBinding[uniformIndex] = program->UniformLocation[uniformIndex];
}
}
renderState state;
getCurrentRenderState(&state);
GL( glUseProgram( program->Program ) );
// Get the texture locations.
for ( int i = 0; i < MAX_PROGRAM_TEXTURES; i++ )
{
char name[32];
sprintf( name, "Texture%i", i );
program->Textures[i] = glGetUniformLocation( program->Program, name );
if ( program->Textures[i] != -1 )
{
GL( glUniform1i( program->Textures[i], i ) );
}
}
restoreRenderState(&state);
return true;
}
static void ovrProgram_Destroy( ovrProgram * program )
{
if ( program->Program != 0 )
{
GL( glDeleteProgram( program->Program ) );
program->Program = 0;
}
if ( program->VertexShader != 0 )
{
GL( glDeleteShader( program->VertexShader ) );
program->VertexShader = 0;
}
if ( program->FragmentShader != 0 )
{
GL( glDeleteShader( program->FragmentShader ) );
program->FragmentShader = 0;
}
}
static const char VERTEX_SHADER[] =
"#version 300 es\n"
"in vec3 vertexPosition;\n"
"in vec4 vertexColor;\n"
"uniform mat4 viewProjectionMatrix;\n"
"out vec4 fragmentColor;\n"
"void main()\n"
"{\n"
" gl_Position = viewProjectionMatrix * vec4( vertexPosition, 1.0 );\n"
" fragmentColor = vertexColor;\n"
"}\n";
static const char FRAGMENT_SHADER[] =
"#version 300 es\n"
"in lowp vec4 fragmentColor;\n"
"out lowp vec4 outColor;\n"
"void main()\n"
"{\n"
" outColor = fragmentColor;\n"
"}\n";
/*
================================================================================
ovrScene
================================================================================
*/
void ovrScene_Clear( ovrScene * scene )
{
scene->CreatedScene = false;
scene->CreatedVAOs = false;
ovrProgram_Clear( &scene->Program );
ovrGeometry_Clear( &scene->GroundPlane );
ovrRenderer_Clear( &scene->CylinderRenderer );
scene->CylinderWidth = 0;
scene->CylinderHeight = 0;
}
bool ovrScene_IsCreated( ovrScene * scene )
{
return scene->CreatedScene;
}
void ovrScene_CreateVAOs( ovrScene * scene )
{
if ( !scene->CreatedVAOs )
{
ovrGeometry_CreateVAO( &scene->GroundPlane );
scene->CreatedVAOs = true;
}
}
void ovrScene_DestroyVAOs( ovrScene * scene )
{
if ( scene->CreatedVAOs )
{
ovrGeometry_DestroyVAO( &scene->GroundPlane );
scene->CreatedVAOs = false;
}
}
void ovrScene_Create( int width, int height, ovrScene * scene, const ovrJava * java )
{
// Simple ground plane geometry.
{
ovrProgram_Create( &scene->Program, VERTEX_SHADER, FRAGMENT_SHADER );
ovrGeometry_CreateGroundPlane( &scene->GroundPlane );
ovrScene_CreateVAOs( scene );
}
// Create Cylinder renderer
{
scene->CylinderWidth = width;
scene->CylinderHeight = height;
//Create cylinder renderer
ovrRenderer_Create( width, height, &scene->CylinderRenderer, java );
}
scene->CreatedScene = true;
}
void ovrScene_Destroy( ovrScene * scene )
{
ovrScene_DestroyVAOs( scene );
ovrProgram_Destroy( &scene->Program );
ovrGeometry_Destroy( &scene->GroundPlane );
ovrRenderer_Destroy( &scene->CylinderRenderer );
scene->CreatedScene = false;
}
/*
================================================================================
ovrRenderer
================================================================================
*/
ovrLayerProjection2 ovrRenderer_RenderGroundPlaneToEyeBuffer( ovrRenderer * renderer, const ovrJava * java,
const ovrScene * scene, const ovrTracking2 * tracking )
{
ovrLayerProjection2 layer = vrapi_DefaultLayerProjection2();
layer.HeadPose = tracking->HeadPose;
for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ )
{
ovrFramebuffer * frameBuffer = &renderer->FrameBuffer[eye];
layer.Textures[eye].ColorSwapChain = frameBuffer->ColorTextureSwapChain;
layer.Textures[eye].SwapChainIndex = frameBuffer->TextureSwapChainIndex;
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection( &tracking->Eye[eye].ProjectionMatrix );
}
layer.Header.Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION;
for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ )
{
ovrFramebuffer * frameBuffer = &renderer->FrameBuffer[eye];
ovrFramebuffer_SetCurrent( frameBuffer );
renderState state;
getCurrentRenderState(&state);
GL( glUseProgram( scene->Program.Program ) );
ovrMatrix4f viewProjMatrix = ovrMatrix4f_Multiply( &tracking->Eye[eye].ProjectionMatrix, &tracking->Eye[eye].ViewMatrix );
glUniformMatrix4fv( scene->Program.UniformLocation[UNIFORM_VIEW_PROJ_MATRIX], 1, GL_TRUE, &viewProjMatrix.M[0][0] );
GL( glEnable( GL_SCISSOR_TEST ) );
GL( glDepthMask( GL_TRUE ) );
GL( glEnable( GL_DEPTH_TEST ) );
GL( glDepthFunc( GL_LEQUAL ) );
GL( glEnable( GL_CULL_FACE ) );
GL( glCullFace( GL_BACK ) );
GL( glViewport( 0, 0, frameBuffer->Width, frameBuffer->Height ) );
GL( glScissor( 0, 0, frameBuffer->Width, frameBuffer->Height ) );
GL( glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ) );
GL( glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) );
//bind buffers
GL( glBindBuffer( GL_ARRAY_BUFFER, scene->GroundPlane.VertexBuffer ) );
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, scene->GroundPlane.IndexBuffer ) );
GL( glBindVertexArray( scene->GroundPlane.VertexArrayObject ) );
GL( glDrawElements( GL_TRIANGLES, scene->GroundPlane.IndexCount, GL_UNSIGNED_SHORT, NULL ) );
restoreRenderState(&state);
// Explicitly clear the border texels to black when GL_CLAMP_TO_BORDER is not available.
ovrFramebuffer_ClearEdgeTexels( frameBuffer );
ovrFramebuffer_Resolve( frameBuffer );
ovrFramebuffer_Advance( frameBuffer );
}
ovrFramebuffer_SetNone();
return layer;
}
// Assumes landscape cylinder shape.
static ovrMatrix4f CylinderModelMatrix( const int texWidth, const int texHeight,
const ovrVector3f translation,
const float rotateYaw,
const float rotatePitch,
const float radius,
const float density )
{
const ovrMatrix4f scaleMatrix = ovrMatrix4f_CreateScale( radius, radius * (float)texHeight * VRAPI_PI / density, radius );
const ovrMatrix4f transMatrix = ovrMatrix4f_CreateTranslation( translation.x, translation.y, translation.z );
const ovrMatrix4f rotXMatrix = ovrMatrix4f_CreateRotation( rotateYaw, 0.0f, 0.0f );
const ovrMatrix4f rotYMatrix = ovrMatrix4f_CreateRotation( 0.0f, rotatePitch, 0.0f );
const ovrMatrix4f m0 = ovrMatrix4f_Multiply( &transMatrix, &scaleMatrix );
const ovrMatrix4f m1 = ovrMatrix4f_Multiply( &rotXMatrix, &m0 );
const ovrMatrix4f m2 = ovrMatrix4f_Multiply( &rotYMatrix, &m1 );
return m2;
}
ovrLayerCylinder2 BuildCylinderLayer( ovrRenderer * cylinderRenderer,
const int textureWidth, const int textureHeight,
const ovrTracking2 * tracking, float rotatePitch )
{
ovrLayerCylinder2 layer = vrapi_DefaultLayerCylinder2();
const float fadeLevel = 1.0f;
layer.Header.ColorScale.x =
layer.Header.ColorScale.y =
layer.Header.ColorScale.z =
layer.Header.ColorScale.w = fadeLevel;
layer.Header.SrcBlend = VRAPI_FRAME_LAYER_BLEND_SRC_ALPHA;
layer.Header.DstBlend = VRAPI_FRAME_LAYER_BLEND_ONE_MINUS_SRC_ALPHA;
//layer.Header.Flags = VRAPI_FRAME_LAYER_FLAG_CLIP_TO_TEXTURE_RECT;
layer.HeadPose = tracking->HeadPose;
const float density = 4500.0f;
const float rotateYaw = 0.0f;
const float radius = 2.0f;
const ovrVector3f translation = { 0.0f, 1.5f, -2.5f };
ovrMatrix4f cylinderTransform =
CylinderModelMatrix( textureWidth, textureHeight, translation,
rotateYaw, rotatePitch, radius, density );
const float circScale = density * 0.5f / textureWidth;
const float circBias = -circScale * ( 0.5f * ( 1.0f - 1.0f / circScale ) );
for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ )
{
ovrFramebuffer * cylinderFrameBuffer = &cylinderRenderer->FrameBuffer[eye];
ovrMatrix4f modelViewMatrix = ovrMatrix4f_Multiply( &tracking->Eye[eye].ViewMatrix, &cylinderTransform );
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_Inverse( &modelViewMatrix );
layer.Textures[eye].ColorSwapChain = cylinderFrameBuffer->ColorTextureSwapChain;
layer.Textures[eye].SwapChainIndex = cylinderFrameBuffer->TextureSwapChainIndex;
// Texcoord scale and bias is just a representation of the aspect ratio. The positioning
// of the cylinder is handled entirely by the TexCoordsFromTanAngles matrix.
const float texScaleX = circScale;
const float texBiasX = circBias;
const float texScaleY = -0.5f;
const float texBiasY = texScaleY * ( 0.5f * ( 1.0f - ( 1.0f / texScaleY ) ) );
layer.Textures[eye].TextureMatrix.M[0][0] = texScaleX;
layer.Textures[eye].TextureMatrix.M[0][2] = texBiasX;
layer.Textures[eye].TextureMatrix.M[1][1] = texScaleY;
layer.Textures[eye].TextureMatrix.M[1][2] = -texBiasY;
layer.Textures[eye].TextureRect.width = 1.0f;
layer.Textures[eye].TextureRect.height = 1.0f;
}
return layer;
}

View file

@ -1,216 +0,0 @@
/************************************************************************************
Filename : VrCompositor.h
*************************************************************************************/
#define CHECK_GL_ERRORS
#ifdef CHECK_GL_ERRORS
#include "VrCommon.h"
static const char * GlErrorString( GLenum error )
{
switch ( error )
{
case GL_NO_ERROR: return "GL_NO_ERROR";
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
default: return "unknown";
}
}
static void GLCheckErrors( int line )
{
for ( int i = 0; i < 10; i++ )
{
const GLenum error = glGetError();
if ( error == GL_NO_ERROR )
{
break;
}
ALOGE( "GL error on line %d: %s", line, GlErrorString( error ) );
}
}
#define GL( func ) func; GLCheckErrors( __LINE__ );
#else // CHECK_GL_ERRORS
#define GL( func ) func;
#endif // CHECK_GL_ERRORS
/*
================================================================================
ovrFramebuffer
================================================================================
*/
typedef struct
{
int Width;
int Height;
int Multisamples;
int TextureSwapChainLength;
int TextureSwapChainIndex;
ovrTextureSwapChain * ColorTextureSwapChain;
GLuint * DepthBuffers;
GLuint * FrameBuffers;
} ovrFramebuffer;
void ovrFramebuffer_SetCurrent( ovrFramebuffer * frameBuffer );
void ovrFramebuffer_Destroy( ovrFramebuffer * frameBuffer );
void ovrFramebuffer_SetNone();
void ovrFramebuffer_Resolve( ovrFramebuffer * frameBuffer );
void ovrFramebuffer_Advance( ovrFramebuffer * frameBuffer );
void ovrFramebuffer_ClearEdgeTexels( ovrFramebuffer * frameBuffer );
/*
================================================================================
ovrRenderer
================================================================================
*/
typedef struct
{
ovrFramebuffer FrameBuffer[VRAPI_FRAME_LAYER_EYE_MAX];
int NumBuffers;
} ovrRenderer;
void ovrRenderer_Clear( ovrRenderer * renderer );
void ovrRenderer_Create( int width, int height, ovrRenderer * renderer, const ovrJava * java );
void ovrRenderer_Destroy( ovrRenderer * renderer );
/*
================================================================================
renderState
================================================================================
*/
typedef struct
{
GLuint VertexBuffer;
GLuint IndexBuffer;
GLuint VertexArrayObject;
GLuint Program;
GLuint VertexShader;
GLuint FragmentShader;
} renderState;
void getCurrentRenderState( renderState * state);
void restoreRenderState( renderState * state );
/*
================================================================================
ovrGeometry
================================================================================
*/
typedef struct
{
GLuint Index;
GLint Size;
GLenum Type;
GLboolean Normalized;
GLsizei Stride;
const GLvoid * Pointer;
} ovrVertexAttribPointer;
#define MAX_VERTEX_ATTRIB_POINTERS 3
typedef struct
{
GLuint VertexBuffer;
GLuint IndexBuffer;
GLuint VertexArrayObject;
int VertexCount;
int IndexCount;
ovrVertexAttribPointer VertexAttribs[MAX_VERTEX_ATTRIB_POINTERS];
} ovrGeometry;
/*
================================================================================
ovrProgram
================================================================================
*/
#define MAX_PROGRAM_UNIFORMS 8
#define MAX_PROGRAM_TEXTURES 8
typedef struct
{
GLuint Program;
GLuint VertexShader;
GLuint FragmentShader;
// These will be -1 if not used by the program.
GLint UniformLocation[MAX_PROGRAM_UNIFORMS]; // ProgramUniforms[].name
GLint UniformBinding[MAX_PROGRAM_UNIFORMS]; // ProgramUniforms[].name
GLint Textures[MAX_PROGRAM_TEXTURES]; // Texture%i
} ovrProgram;
/*
================================================================================
ovrScene
================================================================================
*/
typedef struct
{
bool CreatedScene;
bool CreatedVAOs;
ovrProgram Program;
ovrGeometry GroundPlane;
//Proper renderer for stereo rendering to the cylinder layer
ovrRenderer CylinderRenderer;
int CylinderWidth;
int CylinderHeight;
} ovrScene;
bool ovrScene_IsCreated( ovrScene * scene );
void ovrScene_Clear( ovrScene * scene );
void ovrScene_Create( int width, int height, ovrScene * scene, const ovrJava * java );
void ovrScene_CreateVAOs( ovrScene * scene );
void ovrScene_DestroyVAOs( ovrScene * scene );
void ovrScene_Destroy( ovrScene * scene );
/*
================================================================================
ovrRenderer
================================================================================
*/
ovrLayerProjection2 ovrRenderer_RenderGroundPlaneToEyeBuffer( ovrRenderer * renderer, const ovrJava * java,
const ovrScene * scene, const ovrTracking2 * tracking );
ovrLayerProjection2 ovrRenderer_RenderToEyeBuffer( ovrRenderer * renderer, const ovrJava * java,
const ovrTracking2 * tracking );
ovrLayerCylinder2 BuildCylinderLayer( ovrRenderer * cylinderRenderer,
const int textureWidth, const int textureHeight,
const ovrTracking2 * tracking, float rotateYaw );
;

View file

@ -430,7 +430,7 @@ float CL_KeyState (kbutton_t *key)
//==========================================================================
cvar_t cl_upspeed = {CVAR_SAVE, "cl_upspeed","400","vertical movement speed (while swimming or flying)"};
cvar_t cl_movementspeed = {CVAR_SAVE, "cl_movementspeed","150","forward movement speed"};
cvar_t cl_movementspeed = {CVAR_SAVE, "cl_movementspeed","170","forward movement speed"};
cvar_t cl_movespeedkey = {CVAR_SAVE, "cl_movespeedkey","2.0","how much +speed multiplies keyboard movement speed"};
cvar_t cl_movecliptokeyboard = {0, "cl_movecliptokeyboard", "0", "if set to 1, any move is clipped to the nine keyboard states; if set to 2, only the direction is clipped, not the amount"};

View file

@ -2116,8 +2116,10 @@ float GetFOV();
r_refdef.view.ortho_x = atan(r_refdef.view.frustum_x) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView
r_refdef.view.ortho_y = atan(r_refdef.view.frustum_y) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView
if(!CL_VM_UpdateView(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime)))
R_RenderView();
if(r_stereo_side == 0)
CL_VM_UpdateView(max(0.0, cl.time - cl.oldtime));
R_RenderView();
}
r_refdef.view.width = vid.width;
@ -2749,7 +2751,9 @@ void CL_BeginUpdateScreen()
GL_DepthMask(true);
R_ClearScreen(false);
r_refdef.view.clear = false;
//For some reason, with this line in it breaks the left eye rendering on OpenXR, I HAVE NO IDEA WHY!?!
//r_refdef.view.clear = false;
r_refdef.view.isoverlay = false;
// calculate r_refdef.view.quality

View file

@ -3,6 +3,7 @@
#include "cl_collision.h"
#include "dpsoftrast.h"
#include "glquake.h"
#include <stdbool.h>
// on GLES we have to use some proper #define's
#ifndef GL_FRAMEBUFFER
@ -916,6 +917,7 @@ void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int
#endif
}
bool VR_GetVRProjection(int eye, float zNear, float zFar, float* projection);
void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
{
matrix4x4_t tempmatrix, basematrix;
@ -955,6 +957,7 @@ void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix
m[12] = -m[12];
}
VR_GetVRProjection(r_stereo_side, nearclip, farclip, m);
Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
}
@ -998,6 +1001,7 @@ void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *came
m[12] = -m[12];
}
VR_GetVRProjection(r_stereo_side, nearclip, (1<<23), m);
Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
}
@ -2629,6 +2633,9 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi
void R_Mesh_Start(void)
{
BACKENDACTIVECHECK
//Get the current fbo
qglGetIntegerv(GL_FRAMEBUFFER_BINDING, &gl_state.defaultframebufferobject);
R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
R_Mesh_SetUseVBO();
if (gl_printcheckerror.integer && !gl_paranoid.integer)

View file

@ -51,11 +51,11 @@ static qboolean r_gpuskeletal;
// 1.0 pixel unit / 1.5 inch == 0.666666 pixel units per inch
cvar_t vr_worldscale = {CVAR_SAVE, "vr_worldscale", "26.2467", "VR World scale multiplier"};
qboolean useScreenLayer();
qboolean VR_UseScreenLayer();
float GetStereoSeparation()
{
return useScreenLayer() ? 0.0f : vr_worldscale.value * 0.065f;
return VR_UseScreenLayer() ? 0.0f : vr_worldscale.value * 0.065f;
}
@ -126,7 +126,7 @@ cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of r
cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
#define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
cvar_t r_lasersight = {CVAR_SAVE, "r_lasersight", "0","Whether laser sight aim is used"};
cvar_t r_lasersight = {CVAR_SAVE, "r_lasersight", "2","Whether laser sight aim is used"};
cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","0.7", "opacity of water polygons"};
cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
@ -226,7 +226,9 @@ cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how ex
cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
//1.4 on both devices as per Bummsers suggestion (17/01/2023)
cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1.4", "global rendering brightness"};
cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};

View file

@ -3597,7 +3597,7 @@ static void M_Credits_Draw (void)
" QQQQQQQQ QQQQQQQQ ",
" QQQ QQQ ",
" Q Q ",
" Q Q v1.4.11");
" Q Q v1.5.7");
int i, l, linelength, firstline, lastline, lines;
for (i = 0, linelength = 0, firstline = 9999, lastline = -1;m_credits_message[i];i++)

View file

@ -134,11 +134,11 @@ int Sbar_GetYOffset()
return offset;
}
qboolean useScreenLayer();
qboolean VR_UseScreenLayer();
int Sbar_GetXOffset()
{
if (useScreenLayer())
if (VR_UseScreenLayer())
return 0;
//This will give the status bar depth in the 3D space

View file

@ -0,0 +1,4 @@
Into this folder copy the libopenxr_loader.so for each HMD required to support, suffixed with the headset type:
libopenxr_loader_meta.so
libopenxr_loader_pico.so

View file

@ -4,6 +4,5 @@
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Sat Oct 13 12:29:31 BST 2018
ndk.dir=C\:\\Users\\Simon\\AppData\\Local\\Android\\Sdk\\ndk-bundle
sdk.dir=C\:\\Users\\Simon\\AppData\\Local\\Android\\sdk
#Thu Dec 12 20:21:11 GMT 2019
sdk.dir=C\:\\Users\\Simon\\AppData\\Local\\Android\\Sdk

View file

@ -1,4 +1 @@
rootProject.projectDir = new File(settingsDir, '../../../..')
rootProject.name = "QuakeQuest"
include ':', 'VrSamples:QuakeQuest:Projects:Android'

View file

@ -0,0 +1,13 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := openxr_loader
LOCAL_SRC_FILES := lib$(LOCAL_MODULE).so
# NOTE: This check is added to prevent the following error when running a "make clean" where
# the prebuilt lib may have been deleted: "LOCAL_SRC_FILES points to a missing file"
ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_SRC_FILES)))
include $(PREBUILT_SHARED_LIBRARY)
endif

Binary file not shown.

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":VrSamples:QuakeQuest:Projects" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/Android" external.system.id="GRADLE" external.system.module.group="QuakeQuest.VrSamples.QuakeQuest" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":VrSamples:QuakeQuest:Projects" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
<option name="LAST_KNOWN_AGP_VERSION" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -1,7 +1,7 @@
QuakeQuest
==========
Welcome to the only implementation of the Quake Engine for the Oculus Quest 1 and 2, using DarkPlaces as a base for this port.
Welcome to the only implementation of the Quake Engine for the Oculus Quest 1 and 2 and Pico 4, using DarkPlaces as a base for this port.
The easiest way to install this on your Quest is using SideQuest, download SideQuest here:
https://sidequestvr.com/

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":VrSamples:QuakeQuest" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/Projects/Android" external.system.id="GRADLE" external.system.module.group="QuakeQuest.VrSamples" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":VrSamples:QuakeQuest" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
<option name="LAST_KNOWN_AGP_VERSION" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
gradle.properties Normal file
View file

@ -0,0 +1,8 @@
org.gradle.jvmargs=-Xmx1536M \
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED \
--add-opens=java.base/java.lang=ALL-UNNAMED \
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
--add-opens=java.base/java.io=ALL-UNNAMED \
--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED
org.gradle.caching=true
org.gradle.configureondemand=true

View file

@ -1,6 +1,7 @@
package com.drbeef.quakequest;
import static android.system.Os.setenv;
import java.io.BufferedReader;
import java.io.File;
@ -10,14 +11,21 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.system.ErrnoException;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@ -29,36 +37,50 @@ import android.support.v4.content.ContextCompat;
@SuppressLint("SdCardPath") public class GLES3JNIActivity extends Activity implements SurfaceHolder.Callback
{
private static String manufacturer = "";
// Load the gles3jni library right away to make sure JNI_OnLoad() gets called as the very first thing.
static
{
manufacturer = Build.MANUFACTURER.toLowerCase(Locale.ROOT);
if (manufacturer.contains("oculus")) // rename oculus to meta as this will probably happen in the future anyway
{
manufacturer = "meta";
}
try
{
//Load manufacturer specific loader
System.loadLibrary("openxr_loader_" + manufacturer);
setenv("OPENXR_HMD", manufacturer, true);
} catch (Exception e)
{}
System.loadLibrary( "quakequest" );
}
private static final String TAG = "QuakeQuest";
private int permissionCount = 0;
private static final int READ_EXTERNAL_STORAGE_PERMISSION_ID = 1;
private static final int WRITE_EXTERNAL_STORAGE_PERMISSION_ID = 2;
String commandLineParams;
private SurfaceView mView;
private SurfaceHolder mSurfaceHolder;
private SurfaceHolder mSurfaceHolder;
private long mNativeHandle;
private final boolean m_asynchronousTracking = false;
String dir;
@Override protected void onCreate( Bundle icicle )
{
Log.v( TAG, "----------------------------------------------------------------" );
Log.v( TAG, "GLES3JNIActivity::onCreate()" );
super.onCreate( icicle );
mView = new SurfaceView( this );
setContentView( mView );
SurfaceView mView = new SurfaceView(this);
setContentView(mView);
mView.getHolder().addCallback( this );
dir = "/sdcard/QuakeQuest";
//dir = getBaseContext().getExternalFilesDir(null).getAbsolutePath();
// Force the screen to stay on, rather than letting it dim and shut off
// while the user is watching a movie.
getWindow().addFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON );
@ -73,83 +95,47 @@ import android.support.v4.content.ContextCompat;
/** Initializes the Activity only if the permission has been granted. */
private void checkPermissionsAndInitialize() {
// Boilerplate for checking runtime permissions in Android.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(
GLES3JNIActivity.this,
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_EXTERNAL_STORAGE_PERMISSION_ID);
if (!Environment.isExternalStorageManager()) {
//request for the permission
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 1);
}
else
{
permissionCount++;
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(
GLES3JNIActivity.this,
new String[] {Manifest.permission.READ_EXTERNAL_STORAGE},
READ_EXTERNAL_STORAGE_PERMISSION_ID);
}
else
{
permissionCount++;
}
if (permissionCount == 2) {
// Permissions have already been granted.
create();
}
}
/** Handles the user accepting the permission. */
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
if (requestCode == READ_EXTERNAL_STORAGE_PERMISSION_ID) {
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
permissionCount++;
}
else
{
System.exit(0);
}
}
if (requestCode == WRITE_EXTERNAL_STORAGE_PERMISSION_ID) {
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
permissionCount++;
}
else
{
System.exit(0);
}
}
checkPermissionsAndInitialize();
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
create();
}
public void create()
{
public void create() {
//This will copy the shareware version of quake if user doesn't have anything installed
copy_asset("/sdcard/QuakeQuest/id1", "pak0.pak");
copy_asset("/sdcard/QuakeQuest/id1", "config.cfg");
copy_asset("/sdcard/QuakeQuest", "commandline.txt");
copy_asset(dir + "/id1", "pak0.pak");
copy_asset(dir + "/id1", "config.cfg");
copy_asset(dir, "commandline.txt");
GLES3JNILib.setCallbackObjects(this);
try {
setenv("QUAKEQUEST_DIR", dir, true);
} catch (Exception ignored)
{
System.exit(-9);;
}
//Read these from a file and pass through
commandLineParams = new String("quake");
//See if user is trying to use command line params
if(new File("/sdcard/QuakeQuest/commandline.txt").exists()) // should exist!
if(new File(dir + "/commandline.txt").exists()) // should exist!
{
BufferedReader br;
try {
br = new BufferedReader(new FileReader("/sdcard/QuakeQuest/commandline.txt"));
br = new BufferedReader(new FileReader(dir + "/commandline.txt"));
String s;
StringBuilder sb=new StringBuilder(0);
while ((s=br.readLine())!=null)
@ -209,13 +195,16 @@ import android.support.v4.content.ContextCompat;
}
}
public void shutdown() {
System.exit(0);
}
@Override protected void onStart()
{
Log.v( TAG, "GLES3JNIActivity::onStart()" );
super.onStart();
GLES3JNILib.onStart( mNativeHandle );
GLES3JNILib.onStart( mNativeHandle, this );
}
@Override protected void onResume()

View file

@ -10,7 +10,7 @@ public class GLES3JNILib
{
// Activity lifecycle
public static native long onCreate( Activity obj, String commandLineParams );
public static native void onStart( long handle );
public static native void onStart( long handle, Object obj );
public static native void onResume( long handle );
public static native void onPause( long handle );
public static native void onStop( long handle );
@ -20,6 +20,4 @@ public class GLES3JNILib
public static native void onSurfaceCreated( long handle, Surface s );
public static native void onSurfaceChanged( long handle, Surface s );
public static native void onSurfaceDestroyed( long handle );
public static native void setCallbackObjects(Object obj);
}

8
local.properties Normal file
View file

@ -0,0 +1,8 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Thu Dec 12 20:21:11 GMT 2019
sdk.dir=C\:\\Users\\Simon\\AppData\\Local\\Android\\Sdk