mirror of
https://github.com/DrBeef/JKXR.git
synced 2024-11-25 05:21:00 +00:00
Full OpenXR compatibility
Including Pico 4 support!!
This commit is contained in:
parent
9af30f39ba
commit
c509e29ee1
14 changed files with 1304 additions and 577 deletions
|
@ -24,9 +24,14 @@
|
||||||
>
|
>
|
||||||
|
|
||||||
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
||||||
|
|
||||||
|
<!-- META QUEST -->
|
||||||
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
|
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
|
||||||
<meta-data android:name="com.oculus.ossplash" android:value="true"/>
|
<meta-data android:name="com.oculus.ossplash" android:value="true"/>
|
||||||
|
|
||||||
|
<!-- PICO XR -->
|
||||||
|
<meta-data android:name="pvr.app.type" android:value="vr" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.drbeef.jkquest.GLES3JNIActivity"
|
android:name="com.drbeef.jkquest.GLES3JNIActivity"
|
||||||
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
|
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
|
||||||
|
|
|
@ -105,6 +105,7 @@ int argc=0;
|
||||||
|
|
||||||
GLboolean stageSupported = GL_FALSE;
|
GLboolean stageSupported = GL_FALSE;
|
||||||
|
|
||||||
|
#ifdef META_QUEST
|
||||||
|
|
||||||
const char* const requiredExtensionNames[] = {
|
const char* const requiredExtensionNames[] = {
|
||||||
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
|
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
|
||||||
|
@ -112,6 +113,69 @@ const char* const requiredExtensionNames[] = {
|
||||||
XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME,
|
XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME,
|
||||||
XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME,
|
XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME,
|
||||||
XR_FB_COLOR_SPACE_EXTENSION_NAME};
|
XR_FB_COLOR_SPACE_EXTENSION_NAME};
|
||||||
|
#endif //META_QUEST
|
||||||
|
|
||||||
|
#ifdef PICO_XR
|
||||||
|
#define XR_PICO_CONFIGS_EXT_EXTENSION_NAME "XR_PICO_configs_ext"
|
||||||
|
|
||||||
|
enum ConfigsEXT
|
||||||
|
{
|
||||||
|
RENDER_TEXTURE_WIDTH = 0,
|
||||||
|
RENDER_TEXTURE_HEIGHT,
|
||||||
|
SHOW_FPS,
|
||||||
|
RUNTIME_LOG_LEVEL,
|
||||||
|
PXRPLUGIN_LOG_LEVEL,
|
||||||
|
UNITY_LOG_LEVEL,
|
||||||
|
UNREAL_LOG_LEVEL,
|
||||||
|
NATIVE_LOG_LEVEL,
|
||||||
|
TARGET_FRAME_RATE,
|
||||||
|
NECK_MODEL_X,
|
||||||
|
NECK_MODEL_Y,
|
||||||
|
NECK_MODEL_Z,
|
||||||
|
DISPLAY_REFRESH_RATE,
|
||||||
|
ENABLE_6DOF,
|
||||||
|
CONTROLLER_TYPE,
|
||||||
|
PHYSICAL_IPD,
|
||||||
|
TO_DELTA_SENSOR_Y,
|
||||||
|
GET_DISPLAY_RATE,
|
||||||
|
FOVEATION_SUBSAMPLED_ENABLED = 18,
|
||||||
|
TRACKING_ORIGIN_HEIGHT
|
||||||
|
};
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetConfigPICO)(
|
||||||
|
XrSession session,
|
||||||
|
enum ConfigsEXT configIndex,
|
||||||
|
float * configData);
|
||||||
|
PFN_xrGetConfigPICO pfnXrGetConfigPICO;
|
||||||
|
|
||||||
|
|
||||||
|
enum ConfigsSetEXT
|
||||||
|
{
|
||||||
|
UNREAL_VERSION = 0,
|
||||||
|
TRACKING_ORIGIN,
|
||||||
|
OPENGL_NOERROR,
|
||||||
|
ENABLE_SIX_DOF,
|
||||||
|
PRESENTATION_FLAG,
|
||||||
|
ENABLE_CPT,
|
||||||
|
PLATFORM,
|
||||||
|
FOVEATION_LEVEL,
|
||||||
|
SET_DISPLAY_RATE = 8,
|
||||||
|
MRC_TEXTURE_ID = 9,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrSetConfigPICO) (
|
||||||
|
XrSession session,
|
||||||
|
enum ConfigsSetEXT configIndex,
|
||||||
|
char * configData);
|
||||||
|
PFN_xrSetConfigPICO pfnXrSetConfigPICO;
|
||||||
|
|
||||||
|
const char* const requiredExtensionNames[] = {
|
||||||
|
XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME,
|
||||||
|
XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME,
|
||||||
|
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
|
||||||
|
XR_PICO_CONFIGS_EXT_EXTENSION_NAME};
|
||||||
|
|
||||||
|
#endif //PICO_XR
|
||||||
|
|
||||||
const uint32_t numRequiredExtensions =
|
const uint32_t numRequiredExtensions =
|
||||||
sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]);
|
sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]);
|
||||||
|
|
||||||
|
@ -972,7 +1036,8 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) {
|
||||||
app->SessionActive = (result == XR_SUCCESS);
|
app->SessionActive = (result == XR_SUCCESS);
|
||||||
|
|
||||||
// Set session state once we have entered VR mode and have a valid session object.
|
// Set session state once we have entered VR mode and have a valid session object.
|
||||||
if (app->SessionActive) {
|
if (app->SessionActive)
|
||||||
|
{
|
||||||
XrPerfSettingsLevelEXT cpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT;
|
XrPerfSettingsLevelEXT cpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT;
|
||||||
XrPerfSettingsLevelEXT gpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT;
|
XrPerfSettingsLevelEXT gpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT;
|
||||||
|
|
||||||
|
@ -980,23 +1045,25 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) {
|
||||||
OXR(xrGetInstanceProcAddr(
|
OXR(xrGetInstanceProcAddr(
|
||||||
app->Instance,
|
app->Instance,
|
||||||
"xrPerfSettingsSetPerformanceLevelEXT",
|
"xrPerfSettingsSetPerformanceLevelEXT",
|
||||||
(PFN_xrVoidFunction*)(&pfnPerfSettingsSetPerformanceLevelEXT)));
|
(PFN_xrVoidFunction * )(&pfnPerfSettingsSetPerformanceLevelEXT)));
|
||||||
|
|
||||||
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
|
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
|
||||||
app->Session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, cpuPerfLevel));
|
app->Session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, cpuPerfLevel));
|
||||||
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
|
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
|
||||||
app->Session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, gpuPerfLevel));
|
app->Session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, gpuPerfLevel));
|
||||||
|
|
||||||
|
#ifdef META_QUEST
|
||||||
PFN_xrSetAndroidApplicationThreadKHR pfnSetAndroidApplicationThreadKHR = NULL;
|
PFN_xrSetAndroidApplicationThreadKHR pfnSetAndroidApplicationThreadKHR = NULL;
|
||||||
OXR(xrGetInstanceProcAddr(
|
OXR(xrGetInstanceProcAddr(
|
||||||
app->Instance,
|
app->Instance,
|
||||||
"xrSetAndroidApplicationThreadKHR",
|
"xrSetAndroidApplicationThreadKHR",
|
||||||
(PFN_xrVoidFunction*)(&pfnSetAndroidApplicationThreadKHR)));
|
(PFN_xrVoidFunction * )(&pfnSetAndroidApplicationThreadKHR)));
|
||||||
|
|
||||||
OXR(pfnSetAndroidApplicationThreadKHR(
|
OXR(pfnSetAndroidApplicationThreadKHR(
|
||||||
app->Session, XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, app->MainThreadTid));
|
app->Session, XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, app->MainThreadTid));
|
||||||
OXR(pfnSetAndroidApplicationThreadKHR(
|
OXR(pfnSetAndroidApplicationThreadKHR(
|
||||||
app->Session, XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, app->RenderThreadTid));
|
app->Session, XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, app->RenderThreadTid));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else if (state == XR_SESSION_STATE_STOPPING) {
|
} else if (state == XR_SESSION_STATE_STOPPING) {
|
||||||
assert(app->SessionActive);
|
assert(app->SessionActive);
|
||||||
|
@ -1045,6 +1112,7 @@ GLboolean ovrApp_HandleXrEvents(ovrApp* app) {
|
||||||
perf_settings_event->fromLevel,
|
perf_settings_event->fromLevel,
|
||||||
perf_settings_event->toLevel);
|
perf_settings_event->toLevel);
|
||||||
} break;
|
} break;
|
||||||
|
#ifdef META_QUEST
|
||||||
case XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB: {
|
case XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB: {
|
||||||
const XrEventDataDisplayRefreshRateChangedFB* refresh_rate_changed_event =
|
const XrEventDataDisplayRefreshRateChangedFB* refresh_rate_changed_event =
|
||||||
(XrEventDataDisplayRefreshRateChangedFB*)(baseEventHeader);
|
(XrEventDataDisplayRefreshRateChangedFB*)(baseEventHeader);
|
||||||
|
@ -1053,6 +1121,7 @@ GLboolean ovrApp_HandleXrEvents(ovrApp* app) {
|
||||||
refresh_rate_changed_event->fromDisplayRefreshRate,
|
refresh_rate_changed_event->fromDisplayRefreshRate,
|
||||||
refresh_rate_changed_event->toDisplayRefreshRate);
|
refresh_rate_changed_event->toDisplayRefreshRate);
|
||||||
} break;
|
} break;
|
||||||
|
#endif
|
||||||
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: {
|
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: {
|
||||||
XrEventDataReferenceSpaceChangePending* ref_space_change_event =
|
XrEventDataReferenceSpaceChangePending* ref_space_change_event =
|
||||||
(XrEventDataReferenceSpaceChangePending*)(baseEventHeader);
|
(XrEventDataReferenceSpaceChangePending*)(baseEventHeader);
|
||||||
|
@ -1606,7 +1675,7 @@ void VR_InitRenderer( ) {
|
||||||
gAppState.Instance, gAppState.SystemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, &gAppState.ViewportConfig));
|
gAppState.Instance, gAppState.SystemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, &gAppState.ViewportConfig));
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef META_QUEST
|
||||||
XrSystemColorSpacePropertiesFB colorSpacePropertiesFB = {};
|
XrSystemColorSpacePropertiesFB colorSpacePropertiesFB = {};
|
||||||
colorSpacePropertiesFB.type = XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB;
|
colorSpacePropertiesFB.type = XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB;
|
||||||
|
|
||||||
|
@ -1688,6 +1757,7 @@ void VR_InitRenderer( ) {
|
||||||
OXR(gAppState.pfnRequestDisplayRefreshRate(gAppState.Session, 0.0f));
|
OXR(gAppState.pfnRequestDisplayRefreshRate(gAppState.Session, 0.0f));
|
||||||
ALOGV("Requesting system default display refresh rate");
|
ALOGV("Requesting system default display refresh rate");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t numOutputSpaces = 0;
|
uint32_t numOutputSpaces = 0;
|
||||||
OXR(xrEnumerateReferenceSpaces(gAppState.Session, 0, &numOutputSpaces, NULL));
|
OXR(xrEnumerateReferenceSpaces(gAppState.Session, 0, &numOutputSpaces, NULL));
|
||||||
|
@ -1717,6 +1787,16 @@ void VR_InitRenderer( ) {
|
||||||
gAppState.Projections[eye].type = XR_TYPE_VIEW;
|
gAppState.Projections[eye].type = XR_TYPE_VIEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PICO_XR
|
||||||
|
xrGetInstanceProcAddr(gAppState.Instance,"xrSetConfigPICO", (PFN_xrVoidFunction*)(&pfnXrSetConfigPICO));
|
||||||
|
xrGetInstanceProcAddr(gAppState.Instance,"xrGetConfigPICO", (PFN_xrVoidFunction*)(&pfnXrGetConfigPICO));
|
||||||
|
|
||||||
|
pfnXrSetConfigPICO(gAppState.Session,TRACKING_ORIGIN,"0");
|
||||||
|
pfnXrSetConfigPICO(gAppState.Session,TRACKING_ORIGIN,"1");
|
||||||
|
|
||||||
|
pfnXrGetConfigPICO(gAppState.Session, GET_DISPLAY_RATE, &gAppState.currentDisplayRefreshRate);
|
||||||
|
#endif
|
||||||
|
|
||||||
ovrRenderer_Create(
|
ovrRenderer_Create(
|
||||||
gAppState.Session,
|
gAppState.Session,
|
||||||
&gAppState.Renderer,
|
&gAppState.Renderer,
|
||||||
|
@ -1740,7 +1820,7 @@ void * AppThreadFunction(void * parm ) {
|
||||||
jclass cls = java.Env->GetObjectClass(java.ActivityObject);
|
jclass cls = java.Env->GetObjectClass(java.ActivityObject);
|
||||||
|
|
||||||
// Note that AttachCurrentThread will reset the thread name.
|
// Note that AttachCurrentThread will reset the thread name.
|
||||||
prctl(PR_SET_NAME, (long) "OVR::Main", 0, 0, 0);
|
prctl(PR_SET_NAME, (long) "AppThreadFunction", 0, 0, 0);
|
||||||
|
|
||||||
openjk_initialised = false;
|
openjk_initialised = false;
|
||||||
vr_screen_dist = NULL;
|
vr_screen_dist = NULL;
|
||||||
|
@ -1748,6 +1828,8 @@ void * AppThreadFunction(void * parm ) {
|
||||||
ovrApp_Clear(&gAppState);
|
ovrApp_Clear(&gAppState);
|
||||||
gAppState.Java = java;
|
gAppState.Java = java;
|
||||||
|
|
||||||
|
ovrEgl_CreateContext(&gAppState.Egl, NULL);
|
||||||
|
EglInitExtensions();
|
||||||
|
|
||||||
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
|
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
|
||||||
xrGetInstanceProcAddr(
|
xrGetInstanceProcAddr(
|
||||||
|
@ -1765,16 +1847,25 @@ void * AppThreadFunction(void * parm ) {
|
||||||
// Create the OpenXR instance.
|
// Create the OpenXR instance.
|
||||||
XrApplicationInfo appInfo;
|
XrApplicationInfo appInfo;
|
||||||
memset(&appInfo, 0, sizeof(appInfo));
|
memset(&appInfo, 0, sizeof(appInfo));
|
||||||
strcpy(appInfo.applicationName, "JKQUest");
|
strcpy(appInfo.applicationName, "JKXR");
|
||||||
appInfo.applicationVersion = 0;
|
appInfo.applicationVersion = 0;
|
||||||
strcpy(appInfo.engineName, "JKQuest");
|
strcpy(appInfo.engineName, "JKXR");
|
||||||
appInfo.engineVersion = 0;
|
appInfo.engineVersion = 0;
|
||||||
appInfo.apiVersion = XR_CURRENT_API_VERSION;
|
appInfo.apiVersion = XR_CURRENT_API_VERSION;
|
||||||
|
|
||||||
XrInstanceCreateInfo instanceCreateInfo;
|
XrInstanceCreateInfo instanceCreateInfo;
|
||||||
memset(&instanceCreateInfo, 0, sizeof(instanceCreateInfo));
|
memset(&instanceCreateInfo, 0, sizeof(instanceCreateInfo));
|
||||||
instanceCreateInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
|
instanceCreateInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
#ifdef META_QUEST
|
||||||
instanceCreateInfo.next = NULL;
|
instanceCreateInfo.next = NULL;
|
||||||
|
#endif
|
||||||
|
#ifdef PICO_XR
|
||||||
|
XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR};
|
||||||
|
instanceCreateInfoAndroid.applicationVM = java.Vm;
|
||||||
|
instanceCreateInfoAndroid.applicationActivity = java.ActivityObject;
|
||||||
|
|
||||||
|
instanceCreateInfo.next = (XrBaseInStructure*)&instanceCreateInfoAndroid;
|
||||||
|
#endif
|
||||||
instanceCreateInfo.createFlags = 0;
|
instanceCreateInfo.createFlags = 0;
|
||||||
instanceCreateInfo.applicationInfo = appInfo;
|
instanceCreateInfo.applicationInfo = appInfo;
|
||||||
instanceCreateInfo.enabledApiLayerCount = 0;
|
instanceCreateInfo.enabledApiLayerCount = 0;
|
||||||
|
@ -1823,6 +1914,7 @@ void * AppThreadFunction(void * parm ) {
|
||||||
graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
|
graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
|
||||||
OXR(pfnGetOpenGLESGraphicsRequirementsKHR(gAppState.Instance, gAppState.SystemId, &graphicsRequirements));
|
OXR(pfnGetOpenGLESGraphicsRequirementsKHR(gAppState.Instance, gAppState.SystemId, &graphicsRequirements));
|
||||||
|
|
||||||
|
#ifdef META_QUEST
|
||||||
XrSystemColorSpacePropertiesFB colorSpacePropertiesFB = {};
|
XrSystemColorSpacePropertiesFB colorSpacePropertiesFB = {};
|
||||||
colorSpacePropertiesFB.type = XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB;
|
colorSpacePropertiesFB.type = XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB;
|
||||||
|
|
||||||
|
@ -1832,7 +1924,7 @@ void * AppThreadFunction(void * parm ) {
|
||||||
OXR(xrGetSystemProperties(gAppState.Instance, gAppState.SystemId, &systemProperties));
|
OXR(xrGetSystemProperties(gAppState.Instance, gAppState.SystemId, &systemProperties));
|
||||||
|
|
||||||
ALOGV("System Color Space Properties: colorspace=%d", colorSpacePropertiesFB.colorSpace);
|
ALOGV("System Color Space Properties: colorspace=%d", colorSpacePropertiesFB.colorSpace);
|
||||||
|
#endif
|
||||||
|
|
||||||
//Set device defaults
|
//Set device defaults
|
||||||
if (SS_MULTIPLIER == 0.0f)
|
if (SS_MULTIPLIER == 0.0f)
|
||||||
|
@ -1851,9 +1943,6 @@ void * AppThreadFunction(void * parm ) {
|
||||||
gAppState.GpuLevel = GPU_LEVEL;
|
gAppState.GpuLevel = GPU_LEVEL;
|
||||||
gAppState.MainThreadTid = gettid();
|
gAppState.MainThreadTid = gettid();
|
||||||
|
|
||||||
ovrEgl_CreateContext(&gAppState.Egl, NULL);
|
|
||||||
|
|
||||||
EglInitExtensions();
|
|
||||||
|
|
||||||
VR_EnterVR();
|
VR_EnterVR();
|
||||||
VR_InitRenderer();
|
VR_InitRenderer();
|
||||||
|
@ -1949,6 +2038,11 @@ void VR_UpdateStageBounds() {
|
||||||
//All the stuff we want to do each frame
|
//All the stuff we want to do each frame
|
||||||
void JKVR_FrameSetup()
|
void JKVR_FrameSetup()
|
||||||
{
|
{
|
||||||
|
if (gAppState.FrameSetup)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GLboolean stageBoundsDirty = GL_TRUE;
|
GLboolean stageBoundsDirty = GL_TRUE;
|
||||||
if (ovrApp_HandleXrEvents(&gAppState)) {
|
if (ovrApp_HandleXrEvents(&gAppState)) {
|
||||||
VR_Recenter();
|
VR_Recenter();
|
||||||
|
@ -1998,6 +2092,8 @@ void JKVR_FrameSetup()
|
||||||
JKVR_getTrackedRemotesOrientation();
|
JKVR_getTrackedRemotesOrientation();
|
||||||
|
|
||||||
JKVR_processHaptics();
|
JKVR_processHaptics();
|
||||||
|
|
||||||
|
gAppState.FrameSetup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetRefresh()
|
int GetRefresh()
|
||||||
|
@ -2021,6 +2117,8 @@ void VR_ClearFrameBuffer( int width, int height)
|
||||||
glScissor( 0, 0, 0, 0 );
|
glScissor( 0, 0, 0, 0 );
|
||||||
glDisable( GL_SCISSOR_TEST );
|
glDisable( GL_SCISSOR_TEST );
|
||||||
|
|
||||||
|
//This is a bit of a hack, but we need to do this to correct for the fact that the engine uses linear RGB colorspace
|
||||||
|
//but openxr uses SRGB (or something, must admit I don't really understand, but adding this works to make it look good again)
|
||||||
glDisable( GL_FRAMEBUFFER_SRGB );
|
glDisable( GL_FRAMEBUFFER_SRGB );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2167,101 +2265,6 @@ void JKVR_HapticEvent(const char* event, int position, int flags, int intensity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKVR_SyncActions( void )
|
|
||||||
{
|
|
||||||
// Attach to session
|
|
||||||
XrSessionActionSetsAttachInfo attachInfo = {};
|
|
||||||
attachInfo.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO;
|
|
||||||
attachInfo.next = NULL;
|
|
||||||
attachInfo.countActionSets = 1;
|
|
||||||
attachInfo.actionSets = &runningActionSet;
|
|
||||||
OXR(xrAttachSessionActionSets(gAppState.Session, &attachInfo));
|
|
||||||
|
|
||||||
// sync action data
|
|
||||||
XrActiveActionSet activeActionSet = {};
|
|
||||||
activeActionSet.actionSet = runningActionSet;
|
|
||||||
activeActionSet.subactionPath = XR_NULL_PATH;
|
|
||||||
|
|
||||||
XrActionsSyncInfo syncInfo = {};
|
|
||||||
syncInfo.type = XR_TYPE_ACTIONS_SYNC_INFO;
|
|
||||||
syncInfo.next = NULL;
|
|
||||||
syncInfo.countActiveActionSets = 1;
|
|
||||||
syncInfo.activeActionSets = &activeActionSet;
|
|
||||||
OXR(xrSyncActions(gAppState.Session, &syncInfo));
|
|
||||||
|
|
||||||
// query input action states
|
|
||||||
XrActionStateGetInfo getInfo = {};
|
|
||||||
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
|
||||||
getInfo.next = NULL;
|
|
||||||
getInfo.subactionPath = XR_NULL_PATH;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JKVR_UpdateControllers( )
|
|
||||||
{
|
|
||||||
JKVR_SyncActions();
|
|
||||||
|
|
||||||
//get controller poses
|
|
||||||
XrAction controller[] = {handPoseLeftAction, handPoseRightAction};
|
|
||||||
XrPath subactionPath[] = {leftHandPath, rightHandPath};
|
|
||||||
XrSpace controllerSpace[] = {leftControllerAimSpace, rightControllerAimSpace};
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
if (ActionPoseIsActive(controller[i], subactionPath[i])) {
|
|
||||||
XrSpaceVelocity vel = {};
|
|
||||||
vel.type = XR_TYPE_SPACE_VELOCITY;
|
|
||||||
XrSpaceLocation loc = {};
|
|
||||||
loc.type = XR_TYPE_SPACE_LOCATION;
|
|
||||||
loc.next = &vel;
|
|
||||||
OXR(xrLocateSpace(controllerSpace[i], gAppState.CurrentSpace, gAppState.PredictedDisplayTime, &loc));
|
|
||||||
|
|
||||||
gAppState.TrackedController[i].Active = (loc.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0;
|
|
||||||
gAppState.TrackedController[i].Pose = loc.pose;
|
|
||||||
gAppState.TrackedController[i].Velocity = vel;
|
|
||||||
|
|
||||||
// apply velocity
|
|
||||||
// float dt = (in_vrEventTime - lastframetime) * 0.001f;
|
|
||||||
// for (int j = 0; j < 3; j++) {
|
|
||||||
// (&gAppState.TrackedController[i].Pose.position.x)[j] += (&vel.linearVelocity.x)[j] * dt;
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
ovrTrackedController_Clear(&gAppState.TrackedController[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
leftRemoteTracking_new = gAppState.TrackedController[0];
|
|
||||||
rightRemoteTracking_new = gAppState.TrackedController[1];
|
|
||||||
|
|
||||||
|
|
||||||
memset(&leftTrackedRemoteState_new, 0, sizeof leftTrackedRemoteState_new);
|
|
||||||
memset(&rightTrackedRemoteState_new, 0, sizeof rightTrackedRemoteState_new);
|
|
||||||
|
|
||||||
//button mapping
|
|
||||||
if (GetActionStateBoolean(menuAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Enter;
|
|
||||||
if (GetActionStateBoolean(buttonXAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_X;
|
|
||||||
if (GetActionStateBoolean(buttonYAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Y;
|
|
||||||
leftTrackedRemoteState_new.GripTrigger = GetActionStateFloat(gripLeftAction).currentState;
|
|
||||||
if (leftTrackedRemoteState_new.GripTrigger > 0.5f) leftTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
|
|
||||||
if (GetActionStateBoolean(thumbstickLeftClickAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_LThumb;
|
|
||||||
|
|
||||||
if (GetActionStateBoolean(buttonAAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_A;
|
|
||||||
if (GetActionStateBoolean(buttonBAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_B;
|
|
||||||
rightTrackedRemoteState_new.GripTrigger = GetActionStateFloat(gripRightAction).currentState;
|
|
||||||
if (rightTrackedRemoteState_new.GripTrigger > 0.5f) rightTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
|
|
||||||
if (GetActionStateBoolean(thumbstickRightClickAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_RThumb;
|
|
||||||
|
|
||||||
//index finger click
|
|
||||||
if (GetActionStateBoolean(indexLeftAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
|
||||||
if (GetActionStateBoolean(indexRightAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
|
||||||
|
|
||||||
//thumbstick
|
|
||||||
XrActionStateVector2f moveJoystickState;
|
|
||||||
moveJoystickState = GetActionStateVector2(moveOnLeftJoystickAction);
|
|
||||||
leftTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
|
|
||||||
leftTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
|
|
||||||
|
|
||||||
moveJoystickState = GetActionStateVector2(moveOnRightJoystickAction);
|
|
||||||
rightTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
|
|
||||||
rightTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JKVR_getHMDOrientation() {//Get orientation
|
void JKVR_getHMDOrientation() {//Get orientation
|
||||||
|
|
||||||
|
@ -2318,16 +2321,15 @@ void JKVR_getTrackedRemotesOrientation() {//Get info for tracked remotes
|
||||||
&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
|
&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
|
||||||
xrButton_X, xrButton_Y, xrButton_A, xrButton_B);
|
xrButton_X, xrButton_Y, xrButton_A, xrButton_B);
|
||||||
break;
|
break;
|
||||||
/* case WEAPON_ALIGN:
|
case WEAPON_ALIGN:
|
||||||
HandleInput_WeaponAlign(&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
|
HandleInput_WeaponAlign(&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
|
||||||
&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
|
&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
|
||||||
xrButton_A, xrButton_B, xrButton_X, xrButton_Y);
|
xrButton_A, xrButton_B, xrButton_X, xrButton_Y);
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKVR_submitFrame()
|
void JKVR_updateProjections()
|
||||||
{
|
{
|
||||||
XrViewLocateInfo projectionInfo = {};
|
XrViewLocateInfo projectionInfo = {};
|
||||||
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
|
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
|
||||||
|
@ -2347,6 +2349,15 @@ void JKVR_submitFrame()
|
||||||
projectionCapacityInput,
|
projectionCapacityInput,
|
||||||
&projectionCountOutput,
|
&projectionCountOutput,
|
||||||
gAppState.Projections));
|
gAppState.Projections));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_submitFrame()
|
||||||
|
{
|
||||||
|
if (gAppState.SessionActive == GL_FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JKVR_updateProjections();
|
||||||
|
|
||||||
XrFovf fov = {};
|
XrFovf fov = {};
|
||||||
XrPosef viewTransform[2];
|
XrPosef viewTransform[2];
|
||||||
|
@ -2390,7 +2401,7 @@ void JKVR_submitFrame()
|
||||||
|
|
||||||
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
|
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
|
||||||
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
||||||
projection_layer_elements[eye].pose = XrPosef_Inverse(viewTransform[eye]);
|
projection_layer_elements[eye].pose = gAppState.xfStageFromHead;
|
||||||
projection_layer_elements[eye].fov = fov;
|
projection_layer_elements[eye].fov = fov;
|
||||||
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
|
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
|
||||||
projection_layer_elements[eye].subImage.swapchain =
|
projection_layer_elements[eye].subImage.swapchain =
|
||||||
|
@ -2451,6 +2462,8 @@ void JKVR_submitFrame()
|
||||||
endFrameInfo.layers = layers;
|
endFrameInfo.layers = layers;
|
||||||
|
|
||||||
OXR(xrEndFrame(gAppState.Session, &endFrameInfo));
|
OXR(xrEndFrame(gAppState.Session, &endFrameInfo));
|
||||||
|
|
||||||
|
gAppState.FrameSetup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ovrAppThread_Create( ovrAppThread * appThread, JNIEnv * env, jobject activityObject, jclass activityClass )
|
static void ovrAppThread_Create( ovrAppThread * appThread, JNIEnv * env, jobject activityObject, jclass activityClass )
|
||||||
|
|
502
Projects/Android/jni/JKVR/OpenXrInput_MetaQuest.cpp
Normal file
502
Projects/Android/jni/JKVR/OpenXrInput_MetaQuest.cpp
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
#include "VrInput.h"
|
||||||
|
#include "VrCvars.h"
|
||||||
|
|
||||||
|
extern ovrApp gAppState;
|
||||||
|
|
||||||
|
#ifdef META_QUEST
|
||||||
|
|
||||||
|
XrSpace CreateActionSpace(XrAction poseAction, XrPath subactionPath) {
|
||||||
|
XrActionSpaceCreateInfo asci = {};
|
||||||
|
asci.type = XR_TYPE_ACTION_SPACE_CREATE_INFO;
|
||||||
|
asci.action = poseAction;
|
||||||
|
asci.poseInActionSpace.orientation.w = 1.0f;
|
||||||
|
asci.subactionPath = subactionPath;
|
||||||
|
XrSpace actionSpace = XR_NULL_HANDLE;
|
||||||
|
OXR(xrCreateActionSpace(gAppState.Session, &asci, &actionSpace));
|
||||||
|
return actionSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrActionSuggestedBinding ActionSuggestedBinding(XrAction action, const char* bindingString) {
|
||||||
|
XrActionSuggestedBinding asb;
|
||||||
|
asb.action = action;
|
||||||
|
XrPath bindingPath;
|
||||||
|
OXR(xrStringToPath(gAppState.Instance, bindingString, &bindingPath));
|
||||||
|
asb.binding = bindingPath;
|
||||||
|
return asb;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrActionSet CreateActionSet(int priority, const char* name, const char* localizedName) {
|
||||||
|
XrActionSetCreateInfo asci = {};
|
||||||
|
asci.type = XR_TYPE_ACTION_SET_CREATE_INFO;
|
||||||
|
asci.next = NULL;
|
||||||
|
asci.priority = priority;
|
||||||
|
strcpy(asci.actionSetName, name);
|
||||||
|
strcpy(asci.localizedActionSetName, localizedName);
|
||||||
|
XrActionSet actionSet = XR_NULL_HANDLE;
|
||||||
|
OXR(xrCreateActionSet(gAppState.Instance, &asci, &actionSet));
|
||||||
|
return actionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrAction CreateAction(
|
||||||
|
XrActionSet actionSet,
|
||||||
|
XrActionType type,
|
||||||
|
const char* actionName,
|
||||||
|
const char* localizedName,
|
||||||
|
int countSubactionPaths,
|
||||||
|
XrPath* subactionPaths) {
|
||||||
|
ALOGV("CreateAction %s, %" PRIi32, 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);
|
||||||
|
XrAction action = XR_NULL_HANDLE;
|
||||||
|
OXR(xrCreateAction(actionSet, &aci, &action));
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ActionPoseIsActive(XrAction action, XrPath subactionPath) {
|
||||||
|
XrActionStateGetInfo getInfo = {};
|
||||||
|
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
||||||
|
getInfo.action = action;
|
||||||
|
getInfo.subactionPath = subactionPath;
|
||||||
|
|
||||||
|
XrActionStatePose state = {};
|
||||||
|
state.type = XR_TYPE_ACTION_STATE_POSE;
|
||||||
|
OXR(xrGetActionStatePose(gAppState.Session, &getInfo, &state));
|
||||||
|
return state.isActive != XR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrActionStateFloat GetActionStateFloat(XrAction action) {
|
||||||
|
XrActionStateGetInfo getInfo = {};
|
||||||
|
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
||||||
|
getInfo.action = action;
|
||||||
|
|
||||||
|
XrActionStateFloat state = {};
|
||||||
|
state.type = XR_TYPE_ACTION_STATE_FLOAT;
|
||||||
|
|
||||||
|
OXR(xrGetActionStateFloat(gAppState.Session, &getInfo, &state));
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrActionStateBoolean GetActionStateBoolean(XrAction action) {
|
||||||
|
XrActionStateGetInfo getInfo = {};
|
||||||
|
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
||||||
|
getInfo.action = action;
|
||||||
|
|
||||||
|
XrActionStateBoolean state = {};
|
||||||
|
state.type = XR_TYPE_ACTION_STATE_BOOLEAN;
|
||||||
|
|
||||||
|
OXR(xrGetActionStateBoolean(gAppState.Session, &getInfo, &state));
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrActionStateVector2f GetActionStateVector2(XrAction action) {
|
||||||
|
XrActionStateGetInfo getInfo = {};
|
||||||
|
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
||||||
|
getInfo.action = action;
|
||||||
|
|
||||||
|
XrActionStateVector2f state = {};
|
||||||
|
state.type = XR_TYPE_ACTION_STATE_VECTOR2F;
|
||||||
|
|
||||||
|
OXR(xrGetActionStateVector2f(gAppState.Session, &getInfo, &state));
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//OpenXR
|
||||||
|
XrPath leftHandPath;
|
||||||
|
XrPath rightHandPath;
|
||||||
|
XrAction handPoseLeftAction;
|
||||||
|
XrAction handPoseRightAction;
|
||||||
|
XrAction indexLeftAction;
|
||||||
|
XrAction indexRightAction;
|
||||||
|
XrAction menuAction;
|
||||||
|
XrAction buttonAAction;
|
||||||
|
XrAction buttonBAction;
|
||||||
|
XrAction buttonXAction;
|
||||||
|
XrAction buttonYAction;
|
||||||
|
XrAction gripLeftAction;
|
||||||
|
XrAction gripRightAction;
|
||||||
|
XrAction moveOnLeftJoystickAction;
|
||||||
|
XrAction moveOnRightJoystickAction;
|
||||||
|
XrAction thumbstickLeftClickAction;
|
||||||
|
XrAction thumbstickRightClickAction;
|
||||||
|
XrAction vibrateLeftFeedback;
|
||||||
|
XrAction vibrateRightFeedback;
|
||||||
|
XrActionSet runningActionSet;
|
||||||
|
XrSpace leftControllerAimSpace = XR_NULL_HANDLE;
|
||||||
|
XrSpace rightControllerAimSpace = XR_NULL_HANDLE;
|
||||||
|
qboolean inputInitialized = qfalse;
|
||||||
|
qboolean useSimpleProfile = qfalse;
|
||||||
|
|
||||||
|
|
||||||
|
//0 = left, 1 = right
|
||||||
|
float vibration_channel_duration[2] = {0.0f, 0.0f};
|
||||||
|
float vibration_channel_intensity[2] = {0.0f, 0.0f};
|
||||||
|
|
||||||
|
void JKVR_InitActions( void )
|
||||||
|
{
|
||||||
|
// Actions
|
||||||
|
runningActionSet = CreateActionSet(1, "running_action_set", "Action Set used on main loop");
|
||||||
|
indexLeftAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "index_left", "Index left", 0, NULL);
|
||||||
|
indexRightAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "index_right", "Index right", 0, NULL);
|
||||||
|
menuAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "menu_action", "Menu", 0, NULL);
|
||||||
|
buttonAAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_a", "Button A", 0, NULL);
|
||||||
|
buttonBAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_b", "Button B", 0, NULL);
|
||||||
|
buttonXAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_x", "Button X", 0, NULL);
|
||||||
|
buttonYAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_y", "Button Y", 0, NULL);
|
||||||
|
gripLeftAction = CreateAction(runningActionSet, XR_ACTION_TYPE_FLOAT_INPUT, "grip_left", "Grip left", 0, NULL);
|
||||||
|
gripRightAction = CreateAction(runningActionSet, XR_ACTION_TYPE_FLOAT_INPUT, "grip_right", "Grip right", 0, NULL);
|
||||||
|
moveOnLeftJoystickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_VECTOR2F_INPUT, "move_on_left_joy", "Move on left Joy", 0, NULL);
|
||||||
|
moveOnRightJoystickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_VECTOR2F_INPUT, "move_on_right_joy", "Move on right Joy", 0, NULL);
|
||||||
|
thumbstickLeftClickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbstick_left", "Thumbstick left", 0, NULL);
|
||||||
|
thumbstickRightClickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbstick_right", "Thumbstick right", 0, NULL);
|
||||||
|
vibrateLeftFeedback = CreateAction(runningActionSet, XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_left_feedback", "Vibrate Left Controller Feedback", 0, NULL);
|
||||||
|
vibrateRightFeedback = CreateAction(runningActionSet, XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_right_feedback", "Vibrate Right Controller Feedback", 0, NULL);
|
||||||
|
|
||||||
|
OXR(xrStringToPath(gAppState.Instance, "/user/hand/left", &leftHandPath));
|
||||||
|
OXR(xrStringToPath(gAppState.Instance, "/user/hand/right", &rightHandPath));
|
||||||
|
handPoseLeftAction = CreateAction(runningActionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose_left", NULL, 1, &leftHandPath);
|
||||||
|
handPoseRightAction = CreateAction(runningActionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose_right", NULL, 1, &rightHandPath);
|
||||||
|
|
||||||
|
if (leftControllerAimSpace == XR_NULL_HANDLE) {
|
||||||
|
leftControllerAimSpace = CreateActionSpace(handPoseLeftAction, leftHandPath);
|
||||||
|
}
|
||||||
|
if (rightControllerAimSpace == XR_NULL_HANDLE) {
|
||||||
|
rightControllerAimSpace = CreateActionSpace(handPoseRightAction, rightHandPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrPath interactionProfilePath = XR_NULL_PATH;
|
||||||
|
XrPath interactionProfilePathTouch = XR_NULL_PATH;
|
||||||
|
XrPath interactionProfilePathKHRSimple = XR_NULL_PATH;
|
||||||
|
|
||||||
|
OXR(xrStringToPath(gAppState.Instance, "/interaction_profiles/oculus/touch_controller", &interactionProfilePathTouch));
|
||||||
|
OXR(xrStringToPath(gAppState.Instance, "/interaction_profiles/khr/simple_controller", &interactionProfilePathKHRSimple));
|
||||||
|
|
||||||
|
// Toggle this to force simple as a first choice, otherwise use it as a last resort
|
||||||
|
if (useSimpleProfile) {
|
||||||
|
ALOGV("xrSuggestInteractionProfileBindings found bindings for Khronos SIMPLE controller");
|
||||||
|
interactionProfilePath = interactionProfilePathKHRSimple;
|
||||||
|
} else {
|
||||||
|
// Query Set
|
||||||
|
XrActionSet queryActionSet = CreateActionSet(1, "query_action_set", "Action Set used to query device caps");
|
||||||
|
XrAction dummyAction = CreateAction(queryActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "dummy_action", "Dummy Action", 0, NULL);
|
||||||
|
|
||||||
|
// Map bindings
|
||||||
|
XrActionSuggestedBinding bindings[1];
|
||||||
|
int currBinding = 0;
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(dummyAction, "/user/hand/right/input/system/click");
|
||||||
|
|
||||||
|
XrInteractionProfileSuggestedBinding suggestedBindings = {};
|
||||||
|
suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
|
||||||
|
suggestedBindings.next = NULL;
|
||||||
|
suggestedBindings.suggestedBindings = bindings;
|
||||||
|
suggestedBindings.countSuggestedBindings = currBinding;
|
||||||
|
|
||||||
|
// Try all
|
||||||
|
suggestedBindings.interactionProfile = interactionProfilePathTouch;
|
||||||
|
XrResult suggestTouchResult = xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings);
|
||||||
|
OXR(suggestTouchResult);
|
||||||
|
|
||||||
|
if (XR_SUCCESS == suggestTouchResult) {
|
||||||
|
ALOGV("xrSuggestInteractionProfileBindings found bindings for QUEST controller");
|
||||||
|
interactionProfilePath = interactionProfilePathTouch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactionProfilePath == XR_NULL_PATH) {
|
||||||
|
// Simple as a fallback
|
||||||
|
bindings[0] = ActionSuggestedBinding(dummyAction, "/user/hand/right/input/select/click");
|
||||||
|
suggestedBindings.interactionProfile = interactionProfilePathKHRSimple;
|
||||||
|
XrResult suggestKHRSimpleResult = xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings);
|
||||||
|
OXR(suggestKHRSimpleResult);
|
||||||
|
if (XR_SUCCESS == suggestKHRSimpleResult) {
|
||||||
|
ALOGV("xrSuggestInteractionProfileBindings found bindings for Khronos SIMPLE controller");
|
||||||
|
interactionProfilePath = interactionProfilePathKHRSimple;
|
||||||
|
} else {
|
||||||
|
ALOGE("xrSuggestInteractionProfileBindings did NOT find any bindings.");
|
||||||
|
assert(qfalse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action creation
|
||||||
|
{
|
||||||
|
// Map bindings
|
||||||
|
XrActionSuggestedBinding bindings[32]; // large enough for all profiles
|
||||||
|
int currBinding = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
if (interactionProfilePath == interactionProfilePathTouch) {
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(indexLeftAction, "/user/hand/left/input/trigger");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(indexRightAction, "/user/hand/right/input/trigger");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(menuAction, "/user/hand/left/input/menu/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(buttonXAction, "/user/hand/left/input/x/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(buttonYAction, "/user/hand/left/input/y/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(buttonAAction, "/user/hand/right/input/a/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(buttonBAction, "/user/hand/right/input/b/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(gripLeftAction, "/user/hand/left/input/squeeze/value");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(gripRightAction, "/user/hand/right/input/squeeze/value");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(moveOnLeftJoystickAction, "/user/hand/left/input/thumbstick");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(moveOnRightJoystickAction, "/user/hand/right/input/thumbstick");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(thumbstickLeftClickAction, "/user/hand/left/input/thumbstick/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(thumbstickRightClickAction, "/user/hand/right/input/thumbstick/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(vibrateLeftFeedback, "/user/hand/left/output/haptic");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(vibrateRightFeedback, "/user/hand/right/output/haptic");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(handPoseLeftAction, "/user/hand/left/input/aim/pose");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(handPoseRightAction, "/user/hand/right/input/aim/pose");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactionProfilePath == interactionProfilePathKHRSimple) {
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(indexLeftAction, "/user/hand/left/input/select/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(indexRightAction, "/user/hand/right/input/select/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(buttonAAction, "/user/hand/left/input/menu/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(buttonXAction, "/user/hand/right/input/menu/click");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(vibrateLeftFeedback, "/user/hand/left/output/haptic");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(vibrateRightFeedback, "/user/hand/right/output/haptic");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(handPoseLeftAction, "/user/hand/left/input/aim/pose");
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(handPoseRightAction, "/user/hand/right/input/aim/pose");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrInteractionProfileSuggestedBinding suggestedBindings = {};
|
||||||
|
suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
|
||||||
|
suggestedBindings.next = NULL;
|
||||||
|
suggestedBindings.interactionProfile = interactionProfilePath;
|
||||||
|
suggestedBindings.suggestedBindings = bindings;
|
||||||
|
suggestedBindings.countSuggestedBindings = currBinding;
|
||||||
|
OXR(xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings));
|
||||||
|
|
||||||
|
// Enumerate actions
|
||||||
|
XrPath actionPathsBuffer[32];
|
||||||
|
char stringBuffer[256];
|
||||||
|
XrAction actionsToEnumerate[] = {
|
||||||
|
indexLeftAction,
|
||||||
|
indexRightAction,
|
||||||
|
menuAction,
|
||||||
|
buttonAAction,
|
||||||
|
buttonBAction,
|
||||||
|
buttonXAction,
|
||||||
|
buttonYAction,
|
||||||
|
gripLeftAction,
|
||||||
|
gripRightAction,
|
||||||
|
moveOnLeftJoystickAction,
|
||||||
|
moveOnRightJoystickAction,
|
||||||
|
thumbstickLeftClickAction,
|
||||||
|
thumbstickRightClickAction,
|
||||||
|
vibrateLeftFeedback,
|
||||||
|
vibrateRightFeedback,
|
||||||
|
handPoseLeftAction,
|
||||||
|
handPoseRightAction
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < sizeof(actionsToEnumerate) / sizeof(actionsToEnumerate[0]); ++i) {
|
||||||
|
XrBoundSourcesForActionEnumerateInfo enumerateInfo = {};
|
||||||
|
enumerateInfo.type = XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO;
|
||||||
|
enumerateInfo.next = NULL;
|
||||||
|
enumerateInfo.action = actionsToEnumerate[i];
|
||||||
|
|
||||||
|
// Get Count
|
||||||
|
uint32_t countOutput = 0;
|
||||||
|
OXR(xrEnumerateBoundSourcesForAction(
|
||||||
|
gAppState.Session, &enumerateInfo, 0 /* request size */, &countOutput, NULL));
|
||||||
|
ALOGV(
|
||||||
|
"xrEnumerateBoundSourcesForAction action=%lld count=%u",
|
||||||
|
(long long)enumerateInfo.action,
|
||||||
|
countOutput);
|
||||||
|
|
||||||
|
if (countOutput < 32) {
|
||||||
|
OXR(xrEnumerateBoundSourcesForAction(
|
||||||
|
gAppState.Session, &enumerateInfo, 32, &countOutput, actionPathsBuffer));
|
||||||
|
for (uint32_t a = 0; a < countOutput; ++a) {
|
||||||
|
XrInputSourceLocalizedNameGetInfo nameGetInfo = {};
|
||||||
|
nameGetInfo.type = XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO;
|
||||||
|
nameGetInfo.next = NULL;
|
||||||
|
nameGetInfo.sourcePath = actionPathsBuffer[a];
|
||||||
|
nameGetInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
|
||||||
|
XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT |
|
||||||
|
XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
|
||||||
|
|
||||||
|
uint32_t stringCount = 0u;
|
||||||
|
OXR(xrGetInputSourceLocalizedName(
|
||||||
|
gAppState.Session, &nameGetInfo, 0, &stringCount, NULL));
|
||||||
|
if (stringCount < 256) {
|
||||||
|
OXR(xrGetInputSourceLocalizedName(
|
||||||
|
gAppState.Session, &nameGetInfo, 256, &stringCount, stringBuffer));
|
||||||
|
char pathStr[256];
|
||||||
|
uint32_t strLen = 0;
|
||||||
|
OXR(xrPathToString(
|
||||||
|
gAppState.Instance,
|
||||||
|
actionPathsBuffer[a],
|
||||||
|
(uint32_t)sizeof(pathStr),
|
||||||
|
&strLen,
|
||||||
|
pathStr));
|
||||||
|
ALOGV(
|
||||||
|
" -> path = %lld `%s` -> `%s`",
|
||||||
|
(long long)actionPathsBuffer[a],
|
||||||
|
pathStr,
|
||||||
|
stringBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputInitialized = qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_SyncActions( void )
|
||||||
|
{
|
||||||
|
// Attach to session
|
||||||
|
XrSessionActionSetsAttachInfo attachInfo = {};
|
||||||
|
attachInfo.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO;
|
||||||
|
attachInfo.next = NULL;
|
||||||
|
attachInfo.countActionSets = 1;
|
||||||
|
attachInfo.actionSets = &runningActionSet;
|
||||||
|
OXR(xrAttachSessionActionSets(gAppState.Session, &attachInfo));
|
||||||
|
|
||||||
|
// sync action data
|
||||||
|
XrActiveActionSet activeActionSet = {};
|
||||||
|
activeActionSet.actionSet = runningActionSet;
|
||||||
|
activeActionSet.subactionPath = XR_NULL_PATH;
|
||||||
|
|
||||||
|
XrActionsSyncInfo syncInfo = {};
|
||||||
|
syncInfo.type = XR_TYPE_ACTIONS_SYNC_INFO;
|
||||||
|
syncInfo.next = NULL;
|
||||||
|
syncInfo.countActiveActionSets = 1;
|
||||||
|
syncInfo.activeActionSets = &activeActionSet;
|
||||||
|
OXR(xrSyncActions(gAppState.Session, &syncInfo));
|
||||||
|
|
||||||
|
// query input action states
|
||||||
|
XrActionStateGetInfo getInfo = {};
|
||||||
|
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
||||||
|
getInfo.next = NULL;
|
||||||
|
getInfo.subactionPath = XR_NULL_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_UpdateControllers( )
|
||||||
|
{
|
||||||
|
JKVR_SyncActions();
|
||||||
|
|
||||||
|
//get controller poses
|
||||||
|
XrAction controller[] = {handPoseLeftAction, handPoseRightAction};
|
||||||
|
XrPath subactionPath[] = {leftHandPath, rightHandPath};
|
||||||
|
XrSpace controllerSpace[] = {leftControllerAimSpace, rightControllerAimSpace};
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (ActionPoseIsActive(controller[i], subactionPath[i])) {
|
||||||
|
XrSpaceVelocity vel = {};
|
||||||
|
vel.type = XR_TYPE_SPACE_VELOCITY;
|
||||||
|
XrSpaceLocation loc = {};
|
||||||
|
loc.type = XR_TYPE_SPACE_LOCATION;
|
||||||
|
loc.next = &vel;
|
||||||
|
OXR(xrLocateSpace(controllerSpace[i], gAppState.CurrentSpace, gAppState.PredictedDisplayTime, &loc));
|
||||||
|
|
||||||
|
gAppState.TrackedController[i].Active = (loc.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0;
|
||||||
|
gAppState.TrackedController[i].Pose = loc.pose;
|
||||||
|
gAppState.TrackedController[i].Velocity = vel;
|
||||||
|
} else {
|
||||||
|
ovrTrackedController_Clear(&gAppState.TrackedController[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leftRemoteTracking_new = gAppState.TrackedController[0];
|
||||||
|
rightRemoteTracking_new = gAppState.TrackedController[1];
|
||||||
|
|
||||||
|
|
||||||
|
memset(&leftTrackedRemoteState_new, 0, sizeof leftTrackedRemoteState_new);
|
||||||
|
memset(&rightTrackedRemoteState_new, 0, sizeof rightTrackedRemoteState_new);
|
||||||
|
|
||||||
|
//button mapping
|
||||||
|
if (GetActionStateBoolean(menuAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Enter;
|
||||||
|
if (GetActionStateBoolean(buttonXAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_X;
|
||||||
|
if (GetActionStateBoolean(buttonYAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Y;
|
||||||
|
leftTrackedRemoteState_new.GripTrigger = GetActionStateFloat(gripLeftAction).currentState;
|
||||||
|
if (leftTrackedRemoteState_new.GripTrigger > 0.5f) leftTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
|
||||||
|
if (GetActionStateBoolean(thumbstickLeftClickAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_LThumb;
|
||||||
|
|
||||||
|
if (GetActionStateBoolean(buttonAAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_A;
|
||||||
|
if (GetActionStateBoolean(buttonBAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_B;
|
||||||
|
rightTrackedRemoteState_new.GripTrigger = GetActionStateFloat(gripRightAction).currentState;
|
||||||
|
if (rightTrackedRemoteState_new.GripTrigger > 0.5f) rightTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
|
||||||
|
if (GetActionStateBoolean(thumbstickRightClickAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_RThumb;
|
||||||
|
|
||||||
|
//index finger click
|
||||||
|
if (GetActionStateBoolean(indexLeftAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||||
|
if (GetActionStateBoolean(indexRightAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||||
|
|
||||||
|
//thumbstick
|
||||||
|
XrActionStateVector2f moveJoystickState;
|
||||||
|
moveJoystickState = GetActionStateVector2(moveOnLeftJoystickAction);
|
||||||
|
leftTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
|
||||||
|
leftTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
|
||||||
|
|
||||||
|
moveJoystickState = GetActionStateVector2(moveOnRightJoystickAction);
|
||||||
|
rightTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
|
||||||
|
rightTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_Vibrate( int duration, int chan, float intensity )
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
int channel = (i + 1) & chan;
|
||||||
|
if (channel)
|
||||||
|
{
|
||||||
|
if (vibration_channel_duration[i] > 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vibration_channel_duration[i] == -1.0f && duration != 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vibration_channel_duration[i] = duration;
|
||||||
|
vibration_channel_intensity[i] = intensity * vr_haptic_intensity->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_processHaptics() {
|
||||||
|
static float lastFrameTime = 0.0f;
|
||||||
|
float timestamp = (float)(Sys_Milliseconds( ));
|
||||||
|
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 = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback;
|
||||||
|
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 = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback;
|
||||||
|
OXR(xrStopHapticFeedback(gAppState.Session, &hapticActionInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
641
Projects/Android/jni/JKVR/OpenXrInput_PicoXR.cpp
Normal file
641
Projects/Android/jni/JKVR/OpenXrInput_PicoXR.cpp
Normal file
|
@ -0,0 +1,641 @@
|
||||||
|
#include "VrInput.h"
|
||||||
|
#include "VrCvars.h"
|
||||||
|
|
||||||
|
extern ovrApp gAppState;
|
||||||
|
|
||||||
|
//#ifdef PICO_XR
|
||||||
|
|
||||||
|
XrResult CheckXrResult(XrResult res, const char* originator) {
|
||||||
|
if (XR_FAILED(res)) {
|
||||||
|
Com_Printf("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;
|
||||||
|
XrAction grabAction;
|
||||||
|
XrAction poseAction;
|
||||||
|
XrAction vibrateAction;
|
||||||
|
XrAction quitAction;
|
||||||
|
/*************************pico******************/
|
||||||
|
XrAction touchpadAction;
|
||||||
|
XrAction AXAction;
|
||||||
|
XrAction homeAction;
|
||||||
|
XrAction BYAction;
|
||||||
|
XrAction backAction;
|
||||||
|
XrAction sideAction;
|
||||||
|
XrAction triggerAction;
|
||||||
|
XrAction joystickAction;
|
||||||
|
XrAction batteryAction;
|
||||||
|
//---add new----------
|
||||||
|
XrAction AXTouchAction;
|
||||||
|
XrAction BYTouchAction;
|
||||||
|
XrAction RockerTouchAction;
|
||||||
|
XrAction TriggerTouchAction;
|
||||||
|
XrAction ThumbrestTouchAction;
|
||||||
|
XrAction GripAction;
|
||||||
|
//---add new----------zgt
|
||||||
|
XrAction AAction;
|
||||||
|
XrAction BAction;
|
||||||
|
XrAction XAction;
|
||||||
|
XrAction YAction;
|
||||||
|
XrAction ATouchAction;
|
||||||
|
XrAction BTouchAction;
|
||||||
|
XrAction XTouchAction;
|
||||||
|
XrAction YTouchAction;
|
||||||
|
XrAction aimAction;
|
||||||
|
/*************************pico******************/
|
||||||
|
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;
|
||||||
|
if (hand >= 0)
|
||||||
|
getInfo.subactionPath = handSubactionPath[hand];
|
||||||
|
|
||||||
|
XrActionStateBoolean state = {};
|
||||||
|
state.type = XR_TYPE_ACTION_STATE_BOOLEAN;
|
||||||
|
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;
|
||||||
|
if (hand >= 0)
|
||||||
|
getInfo.subactionPath = handSubactionPath[hand];
|
||||||
|
|
||||||
|
XrActionStateFloat state = {};
|
||||||
|
state.type = XR_TYPE_ACTION_STATE_FLOAT;
|
||||||
|
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;
|
||||||
|
if (hand >= 0)
|
||||||
|
getInfo.subactionPath = handSubactionPath[hand];
|
||||||
|
|
||||||
|
XrActionStateVector2f state = {};
|
||||||
|
state.type = XR_TYPE_ACTION_STATE_VECTOR2F;
|
||||||
|
CHECK_XRCMD(xrGetActionStateVector2f(gAppState.Session, &getInfo, &state));
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_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;
|
||||||
|
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.
|
||||||
|
XrActionCreateInfo actionInfo = {};
|
||||||
|
actionInfo.type = XR_TYPE_ACTION_CREATE_INFO;
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_FLOAT_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "grab_object");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Grab Object");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &grabAction));
|
||||||
|
|
||||||
|
// Create an input action getting the left and right hand poses.
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_POSE_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "hand_pose");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Hand Pose");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &poseAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_POSE_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "aim_pose");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Aim Pose");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &aimAction));
|
||||||
|
|
||||||
|
// Create output actions for vibrating the left and right controller.
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_VIBRATION_OUTPUT;
|
||||||
|
strcpy(actionInfo.actionName, "vibrate_hand");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Vibrate Hand");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &vibrateAction));
|
||||||
|
|
||||||
|
// Create input actions for quitting the session using the left and right controller.
|
||||||
|
// Since it doesn't matter which hand did this, we do not specify subaction paths for it.
|
||||||
|
// We will just suggest bindings for both hands, where possible.
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "quit_session");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Quit Session");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &quitAction));
|
||||||
|
/**********************************pico***************************************/
|
||||||
|
// Create input actions for toucpad key using the left and right controller.
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "touchpad");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Touchpad");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &touchpadAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "axkey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "AXkey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &AXAction));
|
||||||
|
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "homekey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Homekey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &homeAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "bykey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "BYkey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &BYAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "backkey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Backkey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &backAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "sidekey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Sidekey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &sideAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_FLOAT_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "trigger");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Trigger");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &triggerAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_VECTOR2F_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "joystick");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Joystick");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &joystickAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_FLOAT_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "battery");
|
||||||
|
strcpy(actionInfo.localizedActionName, "battery");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &batteryAction));
|
||||||
|
//------------------------add new---------------------------------
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "axtouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "AXtouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &AXTouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "bytouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "BYtouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &BYTouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "rockertouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Rockertouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &RockerTouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "triggertouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Triggertouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &TriggerTouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "thumbresttouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Thumbresttouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &ThumbrestTouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_FLOAT_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "gripvalue");
|
||||||
|
strcpy(actionInfo.localizedActionName, "GripValue");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &GripAction));
|
||||||
|
|
||||||
|
//--------------add new----------zgt
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "akey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Akey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &AAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "bkey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Bkey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &BAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "xkey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Xkey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &XAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "ykey");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Ykey");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &YAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "atouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Atouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &ATouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "btouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Btouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &BTouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "xtouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Xtouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &XTouchAction));
|
||||||
|
|
||||||
|
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
|
||||||
|
strcpy(actionInfo.actionName, "ytouch");
|
||||||
|
strcpy(actionInfo.localizedActionName, "Ytouch");
|
||||||
|
actionInfo.countSubactionPaths = SIDE_COUNT;
|
||||||
|
actionInfo.subactionPaths = handSubactionPath;
|
||||||
|
CHECK_XRCMD(xrCreateAction(actionSet, &actionInfo, &YTouchAction));
|
||||||
|
/**********************************pico***************************************/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
/**************************pico************************************/
|
||||||
|
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];
|
||||||
|
//--------------add new----------
|
||||||
|
XrPath GripPath[SIDE_COUNT];
|
||||||
|
XrPath AXTouchPath[SIDE_COUNT];
|
||||||
|
XrPath BYTouchPath[SIDE_COUNT];
|
||||||
|
XrPath RockerTouchPath[SIDE_COUNT];
|
||||||
|
XrPath TriggerTouchPath[SIDE_COUNT];
|
||||||
|
XrPath ThumbresetTouchPath[SIDE_COUNT];
|
||||||
|
//--------------add new----------zgt
|
||||||
|
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];
|
||||||
|
/**************************pico************************************/
|
||||||
|
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]));
|
||||||
|
|
||||||
|
/**************************pico************************************/
|
||||||
|
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]));
|
||||||
|
/**************************pico************************************/
|
||||||
|
XrActionSuggestedBinding bindings[128];
|
||||||
|
int currBinding = 0;
|
||||||
|
|
||||||
|
// Suggest bindings for the Pico Neo 3 controller
|
||||||
|
{
|
||||||
|
XrPath picoMixedRealityInteractionProfilePath;
|
||||||
|
CHECK_XRCMD(xrStringToPath(gAppState.Instance, "/interaction_profiles/pico/neo3_controller",
|
||||||
|
&picoMixedRealityInteractionProfilePath));
|
||||||
|
|
||||||
|
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(RockerTouchAction, thumbstickTouchPath[SIDE_LEFT]);
|
||||||
|
bindings[currBinding++] = ActionSuggestedBinding(RockerTouchAction, 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;
|
||||||
|
CHECK_XRCMD(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];
|
||||||
|
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;
|
||||||
|
CHECK_XRCMD(xrAttachSessionActionSets(gAppState.Session, &attachInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_SyncActions( void )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
CHECK_XRCMD(xrSyncActions(gAppState.Session, &syncInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_UpdateControllers( )
|
||||||
|
{
|
||||||
|
JKVR_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.PredictedDisplayTime, &loc);
|
||||||
|
if (res != XR_SUCCESS) {
|
||||||
|
Com_Printf("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;
|
||||||
|
if (GetActionStateBoolean(backAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Enter;
|
||||||
|
if (GetActionStateBoolean(XAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_X;
|
||||||
|
if (GetActionStateBoolean(YAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Y;
|
||||||
|
if (GetActionStateBoolean(sideAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
|
||||||
|
if (GetActionStateBoolean(touchpadAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_LThumb;
|
||||||
|
if (GetActionStateFloat(triggerAction, SIDE_LEFT).currentState > 0.5f) leftTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||||
|
|
||||||
|
rightTrackedRemoteState_new.Buttons = 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(BAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_B;
|
||||||
|
if (GetActionStateBoolean(sideAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_GripTrigger;
|
||||||
|
if (GetActionStateBoolean(touchpadAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_RThumb;
|
||||||
|
if (GetActionStateFloat(triggerAction, SIDE_RIGHT).currentState > 0.5f) rightTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||||
|
|
||||||
|
//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 JKVR_Vibrate( int duration, int chan, float intensity )
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
int channel = (i + 1) & chan;
|
||||||
|
if (channel)
|
||||||
|
{
|
||||||
|
if (vibration_channel_duration[i] > 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vibration_channel_duration[i] == -1.0f && duration != 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vibration_channel_duration[i] = duration;
|
||||||
|
vibration_channel_intensity[i] = intensity * vr_haptic_intensity->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKVR_processHaptics() {
|
||||||
|
static float lastFrameTime = 0.0f;
|
||||||
|
float timestamp = (float)(Sys_Milliseconds( ));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endif
|
|
@ -11,7 +11,6 @@
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <openxr/openxr.h>
|
#include <openxr/openxr.h>
|
||||||
#include <openxr/openxr_platform.h>
|
#include <openxr/openxr_platform.h>
|
||||||
#include <openxr/openxr_oculus.h>
|
|
||||||
#include <openxr/openxr_oculus_helpers.h>
|
#include <openxr/openxr_oculus_helpers.h>
|
||||||
|
|
||||||
#include <android/native_window_jni.h>
|
#include <android/native_window_jni.h>
|
||||||
|
@ -36,31 +35,6 @@
|
||||||
#define ALOGV(...)
|
#define ALOGV(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern XrPath leftHandPath;
|
|
||||||
extern XrPath rightHandPath;
|
|
||||||
extern XrAction handPoseLeftAction;
|
|
||||||
extern XrAction handPoseRightAction;
|
|
||||||
extern XrAction indexLeftAction;
|
|
||||||
extern XrAction indexRightAction;
|
|
||||||
extern XrAction menuAction;
|
|
||||||
extern XrAction buttonAAction;
|
|
||||||
extern XrAction buttonBAction;
|
|
||||||
extern XrAction buttonXAction;
|
|
||||||
extern XrAction buttonYAction;
|
|
||||||
extern XrAction gripLeftAction;
|
|
||||||
extern XrAction gripRightAction;
|
|
||||||
extern XrAction moveOnLeftJoystickAction;
|
|
||||||
extern XrAction moveOnRightJoystickAction;
|
|
||||||
extern XrAction thumbstickLeftClickAction;
|
|
||||||
extern XrAction thumbstickRightClickAction;
|
|
||||||
extern XrAction vibrateLeftFeedback;
|
|
||||||
extern XrAction vibrateRightFeedback;
|
|
||||||
extern XrActionSet runningActionSet;
|
|
||||||
extern XrSpace leftControllerAimSpace;
|
|
||||||
extern XrSpace rightControllerAimSpace;
|
|
||||||
extern qboolean inputInitialized;
|
|
||||||
extern qboolean useSimpleProfile;
|
|
||||||
|
|
||||||
enum { ovrMaxLayerCount = 1 };
|
enum { ovrMaxLayerCount = 1 };
|
||||||
enum { ovrMaxNumEyes = 2 };
|
enum { ovrMaxNumEyes = 2 };
|
||||||
|
|
||||||
|
@ -206,6 +180,7 @@ typedef struct
|
||||||
ANativeWindow* NativeWindow;
|
ANativeWindow* NativeWindow;
|
||||||
bool Resumed;
|
bool Resumed;
|
||||||
bool Focused;
|
bool Focused;
|
||||||
|
bool FrameSetup;
|
||||||
|
|
||||||
XrInstance Instance;
|
XrInstance Instance;
|
||||||
XrSession Session;
|
XrSession Session;
|
||||||
|
@ -274,13 +249,6 @@ void handleTrackedControllerButton(ovrInputStateTrackedRemote * trackedRemoteSta
|
||||||
void interactWithTouchScreen(bool reset, ovrInputStateTrackedRemote *newState, ovrInputStateTrackedRemote *oldState);
|
void interactWithTouchScreen(bool reset, ovrInputStateTrackedRemote *newState, ovrInputStateTrackedRemote *oldState);
|
||||||
int GetRefresh();
|
int GetRefresh();
|
||||||
|
|
||||||
//XrAction stuff
|
|
||||||
bool ActionPoseIsActive(XrAction action, XrPath subactionPath);
|
|
||||||
XrActionStateBoolean GetActionStateBoolean(XrAction action);
|
|
||||||
XrActionStateFloat GetActionStateFloat(XrAction action);
|
|
||||||
XrActionStateVector2f GetActionStateVector2(XrAction action);
|
|
||||||
|
|
||||||
|
|
||||||
void VR_Recenter();
|
void VR_Recenter();
|
||||||
|
|
||||||
//Called from engine code
|
//Called from engine code
|
||||||
|
@ -297,17 +265,15 @@ void JKVR_HapticEnable();
|
||||||
void JKVR_HapticDisable();
|
void JKVR_HapticDisable();
|
||||||
void JKVR_processMessageQueue();
|
void JKVR_processMessageQueue();
|
||||||
void JKVR_FrameSetup();
|
void JKVR_FrameSetup();
|
||||||
void JKVR_setUseScreenLayer(bool use);
|
|
||||||
void JKVR_processHaptics();
|
void JKVR_processHaptics();
|
||||||
void JKVR_getHMDOrientation( );
|
void JKVR_getHMDOrientation( );
|
||||||
void JKVR_getTrackedRemotesOrientation();
|
void JKVR_getTrackedRemotesOrientation();
|
||||||
|
void JKVR_updateProjections();
|
||||||
|
void JKVR_UpdateControllers( );
|
||||||
|
|
||||||
bool JKVR_useScreenLayer();
|
bool JKVR_useScreenLayer();
|
||||||
void JKVR_prepareEyeBuffer(int eye );
|
void JKVR_prepareEyeBuffer(int eye );
|
||||||
void JKVR_finishEyeBuffer(int eye );
|
void JKVR_finishEyeBuffer(int eye );
|
||||||
void JKVR_submitFrame();
|
void JKVR_submitFrame();
|
||||||
|
|
||||||
void GPUDropSync();
|
|
||||||
void GPUWaitSync();
|
|
||||||
|
|
||||||
#endif //vrcommon_h
|
#endif //vrcommon_h
|
|
@ -1,6 +1,5 @@
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
|
|
||||||
Filename : VrInputRight.c
|
|
||||||
Content : Handles common controller input functionality
|
Content : Handles common controller input functionality
|
||||||
Created : September 2019
|
Created : September 2019
|
||||||
Authors : Simon Brown
|
Authors : Simon Brown
|
||||||
|
@ -56,411 +55,6 @@ vr_client_info_t vr;
|
||||||
|
|
||||||
extern ovrApp gAppState;
|
extern ovrApp gAppState;
|
||||||
|
|
||||||
//OpenXR
|
|
||||||
XrPath leftHandPath;
|
|
||||||
XrPath rightHandPath;
|
|
||||||
XrAction handPoseLeftAction;
|
|
||||||
XrAction handPoseRightAction;
|
|
||||||
XrAction indexLeftAction;
|
|
||||||
XrAction indexRightAction;
|
|
||||||
XrAction menuAction;
|
|
||||||
XrAction buttonAAction;
|
|
||||||
XrAction buttonBAction;
|
|
||||||
XrAction buttonXAction;
|
|
||||||
XrAction buttonYAction;
|
|
||||||
XrAction gripLeftAction;
|
|
||||||
XrAction gripRightAction;
|
|
||||||
XrAction moveOnLeftJoystickAction;
|
|
||||||
XrAction moveOnRightJoystickAction;
|
|
||||||
XrAction thumbstickLeftClickAction;
|
|
||||||
XrAction thumbstickRightClickAction;
|
|
||||||
XrAction vibrateLeftFeedback;
|
|
||||||
XrAction vibrateRightFeedback;
|
|
||||||
XrActionSet runningActionSet;
|
|
||||||
XrSpace leftControllerAimSpace = XR_NULL_HANDLE;
|
|
||||||
XrSpace rightControllerAimSpace = XR_NULL_HANDLE;
|
|
||||||
qboolean inputInitialized = qfalse;
|
|
||||||
qboolean useSimpleProfile = qfalse;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
XrSpace CreateActionSpace(XrAction poseAction, XrPath subactionPath) {
|
|
||||||
XrActionSpaceCreateInfo asci = {};
|
|
||||||
asci.type = XR_TYPE_ACTION_SPACE_CREATE_INFO;
|
|
||||||
asci.action = poseAction;
|
|
||||||
asci.poseInActionSpace.orientation.w = 1.0f;
|
|
||||||
asci.subactionPath = subactionPath;
|
|
||||||
XrSpace actionSpace = XR_NULL_HANDLE;
|
|
||||||
OXR(xrCreateActionSpace(gAppState.Session, &asci, &actionSpace));
|
|
||||||
return actionSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrActionSuggestedBinding ActionSuggestedBinding(XrAction action, const char* bindingString) {
|
|
||||||
XrActionSuggestedBinding asb;
|
|
||||||
asb.action = action;
|
|
||||||
XrPath bindingPath;
|
|
||||||
OXR(xrStringToPath(gAppState.Instance, bindingString, &bindingPath));
|
|
||||||
asb.binding = bindingPath;
|
|
||||||
return asb;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrActionSet CreateActionSet(int priority, const char* name, const char* localizedName) {
|
|
||||||
XrActionSetCreateInfo asci = {};
|
|
||||||
asci.type = XR_TYPE_ACTION_SET_CREATE_INFO;
|
|
||||||
asci.next = NULL;
|
|
||||||
asci.priority = priority;
|
|
||||||
strcpy(asci.actionSetName, name);
|
|
||||||
strcpy(asci.localizedActionSetName, localizedName);
|
|
||||||
XrActionSet actionSet = XR_NULL_HANDLE;
|
|
||||||
OXR(xrCreateActionSet(gAppState.Instance, &asci, &actionSet));
|
|
||||||
return actionSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrAction CreateAction(
|
|
||||||
XrActionSet actionSet,
|
|
||||||
XrActionType type,
|
|
||||||
const char* actionName,
|
|
||||||
const char* localizedName,
|
|
||||||
int countSubactionPaths,
|
|
||||||
XrPath* subactionPaths) {
|
|
||||||
ALOGV("CreateAction %s, %" PRIi32, 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);
|
|
||||||
XrAction action = XR_NULL_HANDLE;
|
|
||||||
OXR(xrCreateAction(actionSet, &aci, &action));
|
|
||||||
return action;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ActionPoseIsActive(XrAction action, XrPath subactionPath) {
|
|
||||||
XrActionStateGetInfo getInfo = {};
|
|
||||||
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
|
||||||
getInfo.action = action;
|
|
||||||
getInfo.subactionPath = subactionPath;
|
|
||||||
|
|
||||||
XrActionStatePose state = {};
|
|
||||||
state.type = XR_TYPE_ACTION_STATE_POSE;
|
|
||||||
OXR(xrGetActionStatePose(gAppState.Session, &getInfo, &state));
|
|
||||||
return state.isActive != XR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrActionStateFloat GetActionStateFloat(XrAction action) {
|
|
||||||
XrActionStateGetInfo getInfo = {};
|
|
||||||
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
|
||||||
getInfo.action = action;
|
|
||||||
|
|
||||||
XrActionStateFloat state = {};
|
|
||||||
state.type = XR_TYPE_ACTION_STATE_FLOAT;
|
|
||||||
|
|
||||||
OXR(xrGetActionStateFloat(gAppState.Session, &getInfo, &state));
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrActionStateBoolean GetActionStateBoolean(XrAction action) {
|
|
||||||
XrActionStateGetInfo getInfo = {};
|
|
||||||
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
|
||||||
getInfo.action = action;
|
|
||||||
|
|
||||||
XrActionStateBoolean state = {};
|
|
||||||
state.type = XR_TYPE_ACTION_STATE_BOOLEAN;
|
|
||||||
|
|
||||||
OXR(xrGetActionStateBoolean(gAppState.Session, &getInfo, &state));
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrActionStateVector2f GetActionStateVector2(XrAction action) {
|
|
||||||
XrActionStateGetInfo getInfo = {};
|
|
||||||
getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
|
|
||||||
getInfo.action = action;
|
|
||||||
|
|
||||||
XrActionStateVector2f state = {};
|
|
||||||
state.type = XR_TYPE_ACTION_STATE_VECTOR2F;
|
|
||||||
|
|
||||||
OXR(xrGetActionStateVector2f(gAppState.Session, &getInfo, &state));
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JKVR_InitActions( void )
|
|
||||||
{
|
|
||||||
// Actions
|
|
||||||
runningActionSet = CreateActionSet(1, "running_action_set", "Action Set used on main loop");
|
|
||||||
indexLeftAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "index_left", "Index left", 0, NULL);
|
|
||||||
indexRightAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "index_right", "Index right", 0, NULL);
|
|
||||||
menuAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "menu_action", "Menu", 0, NULL);
|
|
||||||
buttonAAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_a", "Button A", 0, NULL);
|
|
||||||
buttonBAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_b", "Button B", 0, NULL);
|
|
||||||
buttonXAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_x", "Button X", 0, NULL);
|
|
||||||
buttonYAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_y", "Button Y", 0, NULL);
|
|
||||||
gripLeftAction = CreateAction(runningActionSet, XR_ACTION_TYPE_FLOAT_INPUT, "grip_left", "Grip left", 0, NULL);
|
|
||||||
gripRightAction = CreateAction(runningActionSet, XR_ACTION_TYPE_FLOAT_INPUT, "grip_right", "Grip right", 0, NULL);
|
|
||||||
moveOnLeftJoystickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_VECTOR2F_INPUT, "move_on_left_joy", "Move on left Joy", 0, NULL);
|
|
||||||
moveOnRightJoystickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_VECTOR2F_INPUT, "move_on_right_joy", "Move on right Joy", 0, NULL);
|
|
||||||
thumbstickLeftClickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbstick_left", "Thumbstick left", 0, NULL);
|
|
||||||
thumbstickRightClickAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbstick_right", "Thumbstick right", 0, NULL);
|
|
||||||
vibrateLeftFeedback = CreateAction(runningActionSet, XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_left_feedback", "Vibrate Left Controller Feedback", 0, NULL);
|
|
||||||
vibrateRightFeedback = CreateAction(runningActionSet, XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_right_feedback", "Vibrate Right Controller Feedback", 0, NULL);
|
|
||||||
|
|
||||||
OXR(xrStringToPath(gAppState.Instance, "/user/hand/left", &leftHandPath));
|
|
||||||
OXR(xrStringToPath(gAppState.Instance, "/user/hand/right", &rightHandPath));
|
|
||||||
handPoseLeftAction = CreateAction(runningActionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose_left", NULL, 1, &leftHandPath);
|
|
||||||
handPoseRightAction = CreateAction(runningActionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose_right", NULL, 1, &rightHandPath);
|
|
||||||
|
|
||||||
if (leftControllerAimSpace == XR_NULL_HANDLE) {
|
|
||||||
leftControllerAimSpace = CreateActionSpace(handPoseLeftAction, leftHandPath);
|
|
||||||
}
|
|
||||||
if (rightControllerAimSpace == XR_NULL_HANDLE) {
|
|
||||||
rightControllerAimSpace = CreateActionSpace(handPoseRightAction, rightHandPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
XrPath interactionProfilePath = XR_NULL_PATH;
|
|
||||||
XrPath interactionProfilePathTouch = XR_NULL_PATH;
|
|
||||||
XrPath interactionProfilePathKHRSimple = XR_NULL_PATH;
|
|
||||||
|
|
||||||
OXR(xrStringToPath(gAppState.Instance, "/interaction_profiles/oculus/touch_controller", &interactionProfilePathTouch));
|
|
||||||
OXR(xrStringToPath(gAppState.Instance, "/interaction_profiles/khr/simple_controller", &interactionProfilePathKHRSimple));
|
|
||||||
|
|
||||||
// Toggle this to force simple as a first choice, otherwise use it as a last resort
|
|
||||||
if (useSimpleProfile) {
|
|
||||||
ALOGV("xrSuggestInteractionProfileBindings found bindings for Khronos SIMPLE controller");
|
|
||||||
interactionProfilePath = interactionProfilePathKHRSimple;
|
|
||||||
} else {
|
|
||||||
// Query Set
|
|
||||||
XrActionSet queryActionSet = CreateActionSet(1, "query_action_set", "Action Set used to query device caps");
|
|
||||||
XrAction dummyAction = CreateAction(queryActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "dummy_action", "Dummy Action", 0, NULL);
|
|
||||||
|
|
||||||
// Map bindings
|
|
||||||
XrActionSuggestedBinding bindings[1];
|
|
||||||
int currBinding = 0;
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(dummyAction, "/user/hand/right/input/system/click");
|
|
||||||
|
|
||||||
XrInteractionProfileSuggestedBinding suggestedBindings = {};
|
|
||||||
suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
|
|
||||||
suggestedBindings.next = NULL;
|
|
||||||
suggestedBindings.suggestedBindings = bindings;
|
|
||||||
suggestedBindings.countSuggestedBindings = currBinding;
|
|
||||||
|
|
||||||
// Try all
|
|
||||||
suggestedBindings.interactionProfile = interactionProfilePathTouch;
|
|
||||||
XrResult suggestTouchResult = xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings);
|
|
||||||
OXR(suggestTouchResult);
|
|
||||||
|
|
||||||
if (XR_SUCCESS == suggestTouchResult) {
|
|
||||||
ALOGV("xrSuggestInteractionProfileBindings found bindings for QUEST controller");
|
|
||||||
interactionProfilePath = interactionProfilePathTouch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interactionProfilePath == XR_NULL_PATH) {
|
|
||||||
// Simple as a fallback
|
|
||||||
bindings[0] = ActionSuggestedBinding(dummyAction, "/user/hand/right/input/select/click");
|
|
||||||
suggestedBindings.interactionProfile = interactionProfilePathKHRSimple;
|
|
||||||
XrResult suggestKHRSimpleResult = xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings);
|
|
||||||
OXR(suggestKHRSimpleResult);
|
|
||||||
if (XR_SUCCESS == suggestKHRSimpleResult) {
|
|
||||||
ALOGV("xrSuggestInteractionProfileBindings found bindings for Khronos SIMPLE controller");
|
|
||||||
interactionProfilePath = interactionProfilePathKHRSimple;
|
|
||||||
} else {
|
|
||||||
ALOGE("xrSuggestInteractionProfileBindings did NOT find any bindings.");
|
|
||||||
assert(qfalse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Action creation
|
|
||||||
{
|
|
||||||
// Map bindings
|
|
||||||
XrActionSuggestedBinding bindings[32]; // large enough for all profiles
|
|
||||||
int currBinding = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
if (interactionProfilePath == interactionProfilePathTouch) {
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(indexLeftAction, "/user/hand/left/input/trigger");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(indexRightAction, "/user/hand/right/input/trigger");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(menuAction, "/user/hand/left/input/menu/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(buttonXAction, "/user/hand/left/input/x/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(buttonYAction, "/user/hand/left/input/y/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(buttonAAction, "/user/hand/right/input/a/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(buttonBAction, "/user/hand/right/input/b/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(gripLeftAction, "/user/hand/left/input/squeeze/value");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(gripRightAction, "/user/hand/right/input/squeeze/value");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(moveOnLeftJoystickAction, "/user/hand/left/input/thumbstick");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(moveOnRightJoystickAction, "/user/hand/right/input/thumbstick");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(thumbstickLeftClickAction, "/user/hand/left/input/thumbstick/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(thumbstickRightClickAction, "/user/hand/right/input/thumbstick/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(vibrateLeftFeedback, "/user/hand/left/output/haptic");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(vibrateRightFeedback, "/user/hand/right/output/haptic");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(handPoseLeftAction, "/user/hand/left/input/aim/pose");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(handPoseRightAction, "/user/hand/right/input/aim/pose");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interactionProfilePath == interactionProfilePathKHRSimple) {
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(indexLeftAction, "/user/hand/left/input/select/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(indexRightAction, "/user/hand/right/input/select/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(buttonAAction, "/user/hand/left/input/menu/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(buttonXAction, "/user/hand/right/input/menu/click");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(vibrateLeftFeedback, "/user/hand/left/output/haptic");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(vibrateRightFeedback, "/user/hand/right/output/haptic");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(handPoseLeftAction, "/user/hand/left/input/aim/pose");
|
|
||||||
bindings[currBinding++] = ActionSuggestedBinding(handPoseRightAction, "/user/hand/right/input/aim/pose");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XrInteractionProfileSuggestedBinding suggestedBindings = {};
|
|
||||||
suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
|
|
||||||
suggestedBindings.next = NULL;
|
|
||||||
suggestedBindings.interactionProfile = interactionProfilePath;
|
|
||||||
suggestedBindings.suggestedBindings = bindings;
|
|
||||||
suggestedBindings.countSuggestedBindings = currBinding;
|
|
||||||
OXR(xrSuggestInteractionProfileBindings(gAppState.Instance, &suggestedBindings));
|
|
||||||
|
|
||||||
// Enumerate actions
|
|
||||||
XrPath actionPathsBuffer[32];
|
|
||||||
char stringBuffer[256];
|
|
||||||
XrAction actionsToEnumerate[] = {
|
|
||||||
indexLeftAction,
|
|
||||||
indexRightAction,
|
|
||||||
menuAction,
|
|
||||||
buttonAAction,
|
|
||||||
buttonBAction,
|
|
||||||
buttonXAction,
|
|
||||||
buttonYAction,
|
|
||||||
gripLeftAction,
|
|
||||||
gripRightAction,
|
|
||||||
moveOnLeftJoystickAction,
|
|
||||||
moveOnRightJoystickAction,
|
|
||||||
thumbstickLeftClickAction,
|
|
||||||
thumbstickRightClickAction,
|
|
||||||
vibrateLeftFeedback,
|
|
||||||
vibrateRightFeedback,
|
|
||||||
handPoseLeftAction,
|
|
||||||
handPoseRightAction
|
|
||||||
};
|
|
||||||
for (size_t i = 0; i < sizeof(actionsToEnumerate) / sizeof(actionsToEnumerate[0]); ++i) {
|
|
||||||
XrBoundSourcesForActionEnumerateInfo enumerateInfo = {};
|
|
||||||
enumerateInfo.type = XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO;
|
|
||||||
enumerateInfo.next = NULL;
|
|
||||||
enumerateInfo.action = actionsToEnumerate[i];
|
|
||||||
|
|
||||||
// Get Count
|
|
||||||
uint32_t countOutput = 0;
|
|
||||||
OXR(xrEnumerateBoundSourcesForAction(
|
|
||||||
gAppState.Session, &enumerateInfo, 0 /* request size */, &countOutput, NULL));
|
|
||||||
ALOGV(
|
|
||||||
"xrEnumerateBoundSourcesForAction action=%lld count=%u",
|
|
||||||
(long long)enumerateInfo.action,
|
|
||||||
countOutput);
|
|
||||||
|
|
||||||
if (countOutput < 32) {
|
|
||||||
OXR(xrEnumerateBoundSourcesForAction(
|
|
||||||
gAppState.Session, &enumerateInfo, 32, &countOutput, actionPathsBuffer));
|
|
||||||
for (uint32_t a = 0; a < countOutput; ++a) {
|
|
||||||
XrInputSourceLocalizedNameGetInfo nameGetInfo = {};
|
|
||||||
nameGetInfo.type = XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO;
|
|
||||||
nameGetInfo.next = NULL;
|
|
||||||
nameGetInfo.sourcePath = actionPathsBuffer[a];
|
|
||||||
nameGetInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
|
|
||||||
XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT |
|
|
||||||
XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
|
|
||||||
|
|
||||||
uint32_t stringCount = 0u;
|
|
||||||
OXR(xrGetInputSourceLocalizedName(
|
|
||||||
gAppState.Session, &nameGetInfo, 0, &stringCount, NULL));
|
|
||||||
if (stringCount < 256) {
|
|
||||||
OXR(xrGetInputSourceLocalizedName(
|
|
||||||
gAppState.Session, &nameGetInfo, 256, &stringCount, stringBuffer));
|
|
||||||
char pathStr[256];
|
|
||||||
uint32_t strLen = 0;
|
|
||||||
OXR(xrPathToString(
|
|
||||||
gAppState.Instance,
|
|
||||||
actionPathsBuffer[a],
|
|
||||||
(uint32_t)sizeof(pathStr),
|
|
||||||
&strLen,
|
|
||||||
pathStr));
|
|
||||||
ALOGV(
|
|
||||||
" -> path = %lld `%s` -> `%s`",
|
|
||||||
(long long)actionPathsBuffer[a],
|
|
||||||
pathStr,
|
|
||||||
stringBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inputInitialized = qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//0 = left, 1 = right
|
|
||||||
float vibration_channel_duration[2] = {0.0f, 0.0f};
|
|
||||||
float vibration_channel_intensity[2] = {0.0f, 0.0f};
|
|
||||||
|
|
||||||
void JKVR_Vibrate( int duration, int chan, float intensity )
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
int channel = (i + 1) & chan;
|
|
||||||
if (channel)
|
|
||||||
{
|
|
||||||
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 * vr_haptic_intensity->value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JKVR_processHaptics() {
|
|
||||||
static float lastFrameTime = 0.0f;
|
|
||||||
float timestamp = (float)(Sys_Milliseconds( ));
|
|
||||||
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 = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback;
|
|
||||||
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 = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback;
|
|
||||||
OXR(xrStopHapticFeedback(gAppState.Session, &hapticActionInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//keys.h
|
//keys.h
|
||||||
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
|
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
|
||||||
|
|
|
@ -214,17 +214,18 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
|
||||||
if (vr.item_selector) {
|
if (vr.item_selector) {
|
||||||
static bool itemSwitched = false;
|
static bool itemSwitched = false;
|
||||||
if (between(-0.2f, pPrimaryJoystick->y, 0.2f) &&
|
if (between(-0.2f, pPrimaryJoystick->y, 0.2f) &&
|
||||||
(between(0.8f, primaryJoystickX, 1.0f) ||
|
(primaryJoystickX > 0.8f || primaryJoystickX < -0.8f)) {
|
||||||
between(-1.0f, primaryJoystickX, -0.8f))) {
|
|
||||||
if (!itemSwitched) {
|
if (!itemSwitched) {
|
||||||
if (between(0.8f, primaryJoystickX, 1.0f)) {
|
if (primaryJoystickX > 0.8f) {
|
||||||
sendButtonActionSimple("itemselectornext");
|
sendButtonActionSimple("itemselectornext");
|
||||||
} else {
|
itemSwitched = true;
|
||||||
|
} else if (primaryJoystickX < -0.8f) {
|
||||||
sendButtonActionSimple("itemselectorprev");
|
sendButtonActionSimple("itemselectorprev");
|
||||||
|
itemSwitched = true;
|
||||||
}
|
}
|
||||||
itemSwitched = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else if (between(-0.4f, primaryJoystickX, 0.4f)) {
|
||||||
itemSwitched = false;
|
itemSwitched = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,12 +250,12 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
|
||||||
if (between(-0.2f, primaryJoystickX, 0.2f)) {
|
if (between(-0.2f, primaryJoystickX, 0.2f)) {
|
||||||
if (cl.frame.ps.weapon == WP_DISRUPTOR)
|
if (cl.frame.ps.weapon == WP_DISRUPTOR)
|
||||||
{
|
{
|
||||||
sendButtonAction("+altattack", between(0.8f, pPrimaryJoystick->y, 1.0f));
|
sendButtonAction("+altattack", pPrimaryJoystick->y > 0.8f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sendButtonAction("+attack", between(0.8f, pPrimaryJoystick->y, 1.0f));
|
sendButtonAction("+attack", pPrimaryJoystick->y > 0.8f);
|
||||||
sendButtonAction("+altattack", between(-1.0f, pPrimaryJoystick->y, -0.8f));
|
sendButtonAction("+altattack", pPrimaryJoystick->y < -0.8f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,6 @@ Authors : Simon Brown
|
||||||
|
|
||||||
*************************************************************************************/
|
*************************************************************************************/
|
||||||
|
|
||||||
#include <VrApi.h>
|
|
||||||
#include <VrApi_Helpers.h>
|
|
||||||
#include <VrApi_SystemUtils.h>
|
|
||||||
#include <VrApi_Input.h>
|
|
||||||
#include <VrApi_Types.h>
|
|
||||||
#include <android/keycodes.h>
|
#include <android/keycodes.h>
|
||||||
|
|
||||||
#include "VrInput.h"
|
#include "VrInput.h"
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
|
||||||
JK3_BASE_CFLAGS = -DHAVE_GLES -DFINAL_BUILD -fexceptions -Wall -Wno-write-strings -Wno-comment -fno-caller-saves -fno-tree-vectorize -Wno-unused-but-set-variable -fvisibility=hidden
|
# Uncomment for the correct headset - slight changes required in OpenXR implementation
|
||||||
|
#OPENXR_HMD = -DMETA_QUEST
|
||||||
|
OPENXR_HMD = -DPICO_XR
|
||||||
|
|
||||||
|
JK3_BASE_CFLAGS = $(OPENXR_HMD) -DHAVE_GLES -DFINAL_BUILD -fexceptions -Wall -Wno-write-strings -Wno-comment -fno-caller-saves -fno-tree-vectorize -Wno-unused-but-set-variable -fvisibility=hidden
|
||||||
JK3_BASE_CPPFLAGS = -fvisibility-inlines-hidden -Wno-invalid-offsetof -fvisibility=hidden
|
JK3_BASE_CPPFLAGS = -fvisibility-inlines-hidden -Wno-invalid-offsetof -fvisibility=hidden
|
||||||
|
|
||||||
JK3_BASE_LDLIBS =
|
JK3_BASE_LDLIBS =
|
||||||
|
@ -11,7 +15,6 @@ JK3_BASE_LDLIBS =
|
||||||
JK3_BASE_LDLIBS += -Wl
|
JK3_BASE_LDLIBS += -Wl
|
||||||
|
|
||||||
JK3_BASE_C_INCLUDES := $(OPENJK_PATH)/lib $(JK3_CODE_PATH)/client $(JK3_CODE_PATH)/server $(JK3_CODE_PATH)/libs/freetype2/include $(JK3_CODE_PATH)/common $(JK3_CODE_PATH)/gl
|
JK3_BASE_C_INCLUDES := $(OPENJK_PATH)/lib $(JK3_CODE_PATH)/client $(JK3_CODE_PATH)/server $(JK3_CODE_PATH)/libs/freetype2/include $(JK3_CODE_PATH)/common $(JK3_CODE_PATH)/gl
|
||||||
JK3_BASE_C_INCLUDES += $(LOCAL_PATH)/../../../../../../OpenXR/Include
|
|
||||||
JK3_BASE_C_INCLUDES += $(LOCAL_PATH)/../../../../../../3rdParty/khronos/openxr/OpenXR-SDK/include
|
JK3_BASE_C_INCLUDES += $(LOCAL_PATH)/../../../../../../3rdParty/khronos/openxr/OpenXR-SDK/include
|
||||||
JK3_BASE_C_INCLUDES += $(JK3_CODE_PATH)/ $(OPENJK_PATH)/code/ $(OPENJK_PATH)/shared/ $(JK3_CODE_PATH)/ui $(OPENJK_PATH)/lib/gsl-lite/include
|
JK3_BASE_C_INCLUDES += $(JK3_CODE_PATH)/ $(OPENJK_PATH)/code/ $(OPENJK_PATH)/shared/ $(JK3_CODE_PATH)/ui $(OPENJK_PATH)/lib/gsl-lite/include
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,12 @@ JK3_SRC = \
|
||||||
|
|
||||||
|
|
||||||
JKVR_SRC_FILES := ${TOP_DIR}/JKVR/JKVR_SurfaceView.cpp \
|
JKVR_SRC_FILES := ${TOP_DIR}/JKVR/JKVR_SurfaceView.cpp \
|
||||||
${TOP_DIR}/JKVR/VrInputCommon.cpp \
|
${TOP_DIR}/JKVR/VrInputCommon.cpp \
|
||||||
${TOP_DIR}/JKVR/VrInputDefault.cpp \
|
${TOP_DIR}/JKVR/VrInputDefault.cpp \
|
||||||
${TOP_DIR}/JKVR/argtable3.c
|
${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
|
||||||
# ${TOP_DIR}/JKVR/VrCompositor.cpp \
|
${TOP_DIR}/JKVR/argtable3.c \
|
||||||
# ${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
|
${TOP_DIR}/JKVR/OpenXRInput_MetaQuest.cpp \
|
||||||
|
${TOP_DIR}/JKVR/OpenXRInput_PicoXR.cpp
|
||||||
|
|
||||||
LOCAL_SRC_FILES += $(JK3_SRC) $(JKVR_SRC_FILES)
|
LOCAL_SRC_FILES += $(JK3_SRC) $(JKVR_SRC_FILES)
|
||||||
|
|
||||||
|
|
|
@ -126,9 +126,10 @@ JK3_SRC = \
|
||||||
JKVR_SRC_FILES := ${TOP_DIR}/JKVR/JKVR_SurfaceView.cpp \
|
JKVR_SRC_FILES := ${TOP_DIR}/JKVR/JKVR_SurfaceView.cpp \
|
||||||
${TOP_DIR}/JKVR/VrInputCommon.cpp \
|
${TOP_DIR}/JKVR/VrInputCommon.cpp \
|
||||||
${TOP_DIR}/JKVR/VrInputDefault.cpp \
|
${TOP_DIR}/JKVR/VrInputDefault.cpp \
|
||||||
${TOP_DIR}/JKVR/argtable3.c
|
${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
|
||||||
# ${TOP_DIR}/JKVR/VrCompositor.cpp \
|
${TOP_DIR}/JKVR/argtable3.c \
|
||||||
# ${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
|
${TOP_DIR}/JKVR/OpenXRInput_MetaQuest.cpp \
|
||||||
|
${TOP_DIR}/JKVR/OpenXRInput_PicoXR.cpp
|
||||||
|
|
||||||
LOCAL_SRC_FILES += $(JK3_SRC) $(JKVR_SRC_FILES)
|
LOCAL_SRC_FILES += $(JK3_SRC) $(JKVR_SRC_FILES)
|
||||||
|
|
||||||
|
|
|
@ -507,6 +507,7 @@ void SCR_UpdateScreen( void ) {
|
||||||
// that case.
|
// that case.
|
||||||
if ( cls.uiStarted )
|
if ( cls.uiStarted )
|
||||||
{
|
{
|
||||||
|
//Try again here in case we've not done it yet
|
||||||
JKVR_FrameSetup();
|
JKVR_FrameSetup();
|
||||||
|
|
||||||
for (int eye = 0; eye < 2; ++eye)
|
for (int eye = 0; eye < 2; ++eye)
|
||||||
|
|
|
@ -24,6 +24,7 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// common.c -- misc functions used in client and server
|
// common.c -- misc functions used in client and server
|
||||||
|
|
||||||
|
#include <VrCommon.h>
|
||||||
#include "q_shared.h"
|
#include "q_shared.h"
|
||||||
#include "qcommon.h"
|
#include "qcommon.h"
|
||||||
#include "qcommon/q_version.h"
|
#include "qcommon/q_version.h"
|
||||||
|
@ -1363,6 +1364,8 @@ void Com_Frame( void ) {
|
||||||
int timeVal;
|
int timeVal;
|
||||||
static int lastTime = 0, bias = 0;
|
static int lastTime = 0, bias = 0;
|
||||||
|
|
||||||
|
JKVR_FrameSetup();
|
||||||
|
|
||||||
// write config file if anything changed
|
// write config file if anything changed
|
||||||
Com_WriteConfiguration();
|
Com_WriteConfiguration();
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ import java.util.Vector;
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.loadLibrary("openxr_loader");
|
||||||
System.loadLibrary( "openjk_" + game );
|
System.loadLibrary( "openjk_" + game );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue