diff --git a/Projects/Android/AndroidManifest.xml b/Projects/Android/AndroidManifest.xml
index c3928e9..e34a460 100644
--- a/Projects/Android/AndroidManifest.xml
+++ b/Projects/Android/AndroidManifest.xml
@@ -24,9 +24,14 @@
>
+
+
+
+
+
SessionActive = (result == XR_SUCCESS);
// 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 gpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT;
@@ -980,23 +1045,25 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) {
OXR(xrGetInstanceProcAddr(
app->Instance,
"xrPerfSettingsSetPerformanceLevelEXT",
- (PFN_xrVoidFunction*)(&pfnPerfSettingsSetPerformanceLevelEXT)));
+ (PFN_xrVoidFunction * )(&pfnPerfSettingsSetPerformanceLevelEXT)));
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
app->Session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, cpuPerfLevel));
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
app->Session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, gpuPerfLevel));
+#ifdef META_QUEST
PFN_xrSetAndroidApplicationThreadKHR pfnSetAndroidApplicationThreadKHR = NULL;
OXR(xrGetInstanceProcAddr(
app->Instance,
"xrSetAndroidApplicationThreadKHR",
- (PFN_xrVoidFunction*)(&pfnSetAndroidApplicationThreadKHR)));
+ (PFN_xrVoidFunction * )(&pfnSetAndroidApplicationThreadKHR)));
OXR(pfnSetAndroidApplicationThreadKHR(
app->Session, XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, app->MainThreadTid));
OXR(pfnSetAndroidApplicationThreadKHR(
app->Session, XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, app->RenderThreadTid));
+#endif
}
} else if (state == XR_SESSION_STATE_STOPPING) {
assert(app->SessionActive);
@@ -1045,6 +1112,7 @@ GLboolean ovrApp_HandleXrEvents(ovrApp* app) {
perf_settings_event->fromLevel,
perf_settings_event->toLevel);
} break;
+#ifdef META_QUEST
case XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB: {
const XrEventDataDisplayRefreshRateChangedFB* refresh_rate_changed_event =
(XrEventDataDisplayRefreshRateChangedFB*)(baseEventHeader);
@@ -1053,6 +1121,7 @@ GLboolean ovrApp_HandleXrEvents(ovrApp* app) {
refresh_rate_changed_event->fromDisplayRefreshRate,
refresh_rate_changed_event->toDisplayRefreshRate);
} break;
+#endif
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: {
XrEventDataReferenceSpaceChangePending* ref_space_change_event =
(XrEventDataReferenceSpaceChangePending*)(baseEventHeader);
@@ -1606,7 +1675,7 @@ void VR_InitRenderer( ) {
gAppState.Instance, gAppState.SystemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, &gAppState.ViewportConfig));
-
+#ifdef META_QUEST
XrSystemColorSpacePropertiesFB colorSpacePropertiesFB = {};
colorSpacePropertiesFB.type = XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB;
@@ -1688,6 +1757,7 @@ void VR_InitRenderer( ) {
OXR(gAppState.pfnRequestDisplayRefreshRate(gAppState.Session, 0.0f));
ALOGV("Requesting system default display refresh rate");
}
+#endif
uint32_t numOutputSpaces = 0;
OXR(xrEnumerateReferenceSpaces(gAppState.Session, 0, &numOutputSpaces, NULL));
@@ -1717,6 +1787,16 @@ void VR_InitRenderer( ) {
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(
gAppState.Session,
&gAppState.Renderer,
@@ -1740,7 +1820,7 @@ void * AppThreadFunction(void * parm ) {
jclass cls = java.Env->GetObjectClass(java.ActivityObject);
// 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;
vr_screen_dist = NULL;
@@ -1748,6 +1828,8 @@ void * AppThreadFunction(void * parm ) {
ovrApp_Clear(&gAppState);
gAppState.Java = java;
+ ovrEgl_CreateContext(&gAppState.Egl, NULL);
+ EglInitExtensions();
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
xrGetInstanceProcAddr(
@@ -1765,16 +1847,25 @@ void * AppThreadFunction(void * parm ) {
// Create the OpenXR instance.
XrApplicationInfo appInfo;
memset(&appInfo, 0, sizeof(appInfo));
- strcpy(appInfo.applicationName, "JKQUest");
+ strcpy(appInfo.applicationName, "JKXR");
appInfo.applicationVersion = 0;
- strcpy(appInfo.engineName, "JKQuest");
+ strcpy(appInfo.engineName, "JKXR");
appInfo.engineVersion = 0;
appInfo.apiVersion = XR_CURRENT_API_VERSION;
XrInstanceCreateInfo instanceCreateInfo;
memset(&instanceCreateInfo, 0, sizeof(instanceCreateInfo));
instanceCreateInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
+#ifdef META_QUEST
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.applicationInfo = appInfo;
instanceCreateInfo.enabledApiLayerCount = 0;
@@ -1823,6 +1914,7 @@ void * AppThreadFunction(void * parm ) {
graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
OXR(pfnGetOpenGLESGraphicsRequirementsKHR(gAppState.Instance, gAppState.SystemId, &graphicsRequirements));
+#ifdef META_QUEST
XrSystemColorSpacePropertiesFB colorSpacePropertiesFB = {};
colorSpacePropertiesFB.type = XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB;
@@ -1832,7 +1924,7 @@ void * AppThreadFunction(void * parm ) {
OXR(xrGetSystemProperties(gAppState.Instance, gAppState.SystemId, &systemProperties));
ALOGV("System Color Space Properties: colorspace=%d", colorSpacePropertiesFB.colorSpace);
-
+#endif
//Set device defaults
if (SS_MULTIPLIER == 0.0f)
@@ -1851,9 +1943,6 @@ void * AppThreadFunction(void * parm ) {
gAppState.GpuLevel = GPU_LEVEL;
gAppState.MainThreadTid = gettid();
- ovrEgl_CreateContext(&gAppState.Egl, NULL);
-
- EglInitExtensions();
VR_EnterVR();
VR_InitRenderer();
@@ -1949,6 +2038,11 @@ void VR_UpdateStageBounds() {
//All the stuff we want to do each frame
void JKVR_FrameSetup()
{
+ if (gAppState.FrameSetup)
+ {
+ return;
+ }
+
GLboolean stageBoundsDirty = GL_TRUE;
if (ovrApp_HandleXrEvents(&gAppState)) {
VR_Recenter();
@@ -1998,6 +2092,8 @@ void JKVR_FrameSetup()
JKVR_getTrackedRemotesOrientation();
JKVR_processHaptics();
+
+ gAppState.FrameSetup = true;
}
int GetRefresh()
@@ -2021,6 +2117,8 @@ void VR_ClearFrameBuffer( int width, int height)
glScissor( 0, 0, 0, 0 );
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 );
}
@@ -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
@@ -2318,16 +2321,15 @@ void JKVR_getTrackedRemotesOrientation() {//Get info for tracked remotes
&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
xrButton_X, xrButton_Y, xrButton_A, xrButton_B);
break;
-/* case WEAPON_ALIGN:
+ case WEAPON_ALIGN:
HandleInput_WeaponAlign(&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
xrButton_A, xrButton_B, xrButton_X, xrButton_Y);
break;
- */
}
}
-void JKVR_submitFrame()
+void JKVR_updateProjections()
{
XrViewLocateInfo projectionInfo = {};
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
@@ -2347,6 +2349,15 @@ void JKVR_submitFrame()
projectionCapacityInput,
&projectionCountOutput,
gAppState.Projections));
+}
+
+void JKVR_submitFrame()
+{
+ if (gAppState.SessionActive == GL_FALSE) {
+ return;
+ }
+
+ JKVR_updateProjections();
XrFovf fov = {};
XrPosef viewTransform[2];
@@ -2390,7 +2401,7 @@ void JKVR_submitFrame()
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
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;
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
projection_layer_elements[eye].subImage.swapchain =
@@ -2451,6 +2462,8 @@ void JKVR_submitFrame()
endFrameInfo.layers = layers;
OXR(xrEndFrame(gAppState.Session, &endFrameInfo));
+
+ gAppState.FrameSetup = false;
}
static void ovrAppThread_Create( ovrAppThread * appThread, JNIEnv * env, jobject activityObject, jclass activityClass )
diff --git a/Projects/Android/jni/JKVR/OpenXrInput_MetaQuest.cpp b/Projects/Android/jni/JKVR/OpenXrInput_MetaQuest.cpp
new file mode 100644
index 0000000..3608393
--- /dev/null
+++ b/Projects/Android/jni/JKVR/OpenXrInput_MetaQuest.cpp
@@ -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
diff --git a/Projects/Android/jni/JKVR/OpenXrInput_PicoXR.cpp b/Projects/Android/jni/JKVR/OpenXrInput_PicoXR.cpp
new file mode 100644
index 0000000..e6ab62a
--- /dev/null
+++ b/Projects/Android/jni/JKVR/OpenXrInput_PicoXR.cpp
@@ -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
diff --git a/Projects/Android/jni/JKVR/VrCommon.h b/Projects/Android/jni/JKVR/VrCommon.h
index a3ec196..f4a6dbf 100644
--- a/Projects/Android/jni/JKVR/VrCommon.h
+++ b/Projects/Android/jni/JKVR/VrCommon.h
@@ -11,7 +11,6 @@
#include
#include
#include
-#include
#include
#include
@@ -36,31 +35,6 @@
#define ALOGV(...)
#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 { ovrMaxNumEyes = 2 };
@@ -206,6 +180,7 @@ typedef struct
ANativeWindow* NativeWindow;
bool Resumed;
bool Focused;
+ bool FrameSetup;
XrInstance Instance;
XrSession Session;
@@ -274,13 +249,6 @@ void handleTrackedControllerButton(ovrInputStateTrackedRemote * trackedRemoteSta
void interactWithTouchScreen(bool reset, ovrInputStateTrackedRemote *newState, ovrInputStateTrackedRemote *oldState);
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();
//Called from engine code
@@ -297,17 +265,15 @@ void JKVR_HapticEnable();
void JKVR_HapticDisable();
void JKVR_processMessageQueue();
void JKVR_FrameSetup();
-void JKVR_setUseScreenLayer(bool use);
void JKVR_processHaptics();
void JKVR_getHMDOrientation( );
void JKVR_getTrackedRemotesOrientation();
+void JKVR_updateProjections();
+void JKVR_UpdateControllers( );
bool JKVR_useScreenLayer();
void JKVR_prepareEyeBuffer(int eye );
void JKVR_finishEyeBuffer(int eye );
void JKVR_submitFrame();
-void GPUDropSync();
-void GPUWaitSync();
-
#endif //vrcommon_h
\ No newline at end of file
diff --git a/Projects/Android/jni/JKVR/VrInputCommon.cpp b/Projects/Android/jni/JKVR/VrInputCommon.cpp
index 84082ff..8f59aa6 100644
--- a/Projects/Android/jni/JKVR/VrInputCommon.cpp
+++ b/Projects/Android/jni/JKVR/VrInputCommon.cpp
@@ -1,6 +1,5 @@
/************************************************************************************
-Filename : VrInputRight.c
Content : Handles common controller input functionality
Created : September 2019
Authors : Simon Brown
@@ -56,411 +55,6 @@ vr_client_info_t vr;
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
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
diff --git a/Projects/Android/jni/JKVR/VrInputDefault.cpp b/Projects/Android/jni/JKVR/VrInputDefault.cpp
index 587d213..626f960 100644
--- a/Projects/Android/jni/JKVR/VrInputDefault.cpp
+++ b/Projects/Android/jni/JKVR/VrInputDefault.cpp
@@ -214,17 +214,18 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
if (vr.item_selector) {
static bool itemSwitched = false;
if (between(-0.2f, pPrimaryJoystick->y, 0.2f) &&
- (between(0.8f, primaryJoystickX, 1.0f) ||
- between(-1.0f, primaryJoystickX, -0.8f))) {
+ (primaryJoystickX > 0.8f || primaryJoystickX < -0.8f)) {
+
if (!itemSwitched) {
- if (between(0.8f, primaryJoystickX, 1.0f)) {
+ if (primaryJoystickX > 0.8f) {
sendButtonActionSimple("itemselectornext");
- } else {
+ itemSwitched = true;
+ } else if (primaryJoystickX < -0.8f) {
sendButtonActionSimple("itemselectorprev");
+ itemSwitched = true;
}
- itemSwitched = true;
}
- } else {
+ } else if (between(-0.4f, primaryJoystickX, 0.4f)) {
itemSwitched = false;
}
}
@@ -249,12 +250,12 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
if (between(-0.2f, primaryJoystickX, 0.2f)) {
if (cl.frame.ps.weapon == WP_DISRUPTOR)
{
- sendButtonAction("+altattack", between(0.8f, pPrimaryJoystick->y, 1.0f));
+ sendButtonAction("+altattack", pPrimaryJoystick->y > 0.8f);
}
else
{
- sendButtonAction("+attack", between(0.8f, pPrimaryJoystick->y, 1.0f));
- sendButtonAction("+altattack", between(-1.0f, pPrimaryJoystick->y, -0.8f));
+ sendButtonAction("+attack", pPrimaryJoystick->y > 0.8f);
+ sendButtonAction("+altattack", pPrimaryJoystick->y < -0.8f);
}
}
}
diff --git a/Projects/Android/jni/JKVR/VrInputWeaponAlign.cpp b/Projects/Android/jni/JKVR/VrInputWeaponAlign.cpp
index c83dd67..dab17bc 100644
--- a/Projects/Android/jni/JKVR/VrInputWeaponAlign.cpp
+++ b/Projects/Android/jni/JKVR/VrInputWeaponAlign.cpp
@@ -7,11 +7,6 @@ Authors : Simon Brown
*************************************************************************************/
-#include
-#include
-#include
-#include
-#include
#include
#include "VrInput.h"
diff --git a/Projects/Android/jni/OpenJK/Android.mk b/Projects/Android/jni/OpenJK/Android.mk
index 63d4fef..a8ccc2a 100644
--- a/Projects/Android/jni/OpenJK/Android.mk
+++ b/Projects/Android/jni/OpenJK/Android.mk
@@ -1,7 +1,11 @@
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_LDLIBS =
@@ -11,7 +15,6 @@ JK3_BASE_LDLIBS =
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 += $(LOCAL_PATH)/../../../../../../OpenXR/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
diff --git a/Projects/Android/jni/OpenJK/Android_client_ja.mk b/Projects/Android/jni/OpenJK/Android_client_ja.mk
index 3a8ad59..9eace92 100644
--- a/Projects/Android/jni/OpenJK/Android_client_ja.mk
+++ b/Projects/Android/jni/OpenJK/Android_client_ja.mk
@@ -124,11 +124,12 @@ JK3_SRC = \
JKVR_SRC_FILES := ${TOP_DIR}/JKVR/JKVR_SurfaceView.cpp \
- ${TOP_DIR}/JKVR/VrInputCommon.cpp \
- ${TOP_DIR}/JKVR/VrInputDefault.cpp \
- ${TOP_DIR}/JKVR/argtable3.c
-# ${TOP_DIR}/JKVR/VrCompositor.cpp \
-# ${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
+ ${TOP_DIR}/JKVR/VrInputCommon.cpp \
+ ${TOP_DIR}/JKVR/VrInputDefault.cpp \
+ ${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
+ ${TOP_DIR}/JKVR/argtable3.c \
+ ${TOP_DIR}/JKVR/OpenXRInput_MetaQuest.cpp \
+ ${TOP_DIR}/JKVR/OpenXRInput_PicoXR.cpp
LOCAL_SRC_FILES += $(JK3_SRC) $(JKVR_SRC_FILES)
diff --git a/Projects/Android/jni/OpenJK/Android_client_jo.mk b/Projects/Android/jni/OpenJK/Android_client_jo.mk
index cc3aae5..f5215cf 100644
--- a/Projects/Android/jni/OpenJK/Android_client_jo.mk
+++ b/Projects/Android/jni/OpenJK/Android_client_jo.mk
@@ -126,9 +126,10 @@ JK3_SRC = \
JKVR_SRC_FILES := ${TOP_DIR}/JKVR/JKVR_SurfaceView.cpp \
${TOP_DIR}/JKVR/VrInputCommon.cpp \
${TOP_DIR}/JKVR/VrInputDefault.cpp \
- ${TOP_DIR}/JKVR/argtable3.c
-# ${TOP_DIR}/JKVR/VrCompositor.cpp \
-# ${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
+ ${TOP_DIR}/JKVR/VrInputWeaponAlign.cpp \
+ ${TOP_DIR}/JKVR/argtable3.c \
+ ${TOP_DIR}/JKVR/OpenXRInput_MetaQuest.cpp \
+ ${TOP_DIR}/JKVR/OpenXRInput_PicoXR.cpp
LOCAL_SRC_FILES += $(JK3_SRC) $(JKVR_SRC_FILES)
diff --git a/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp b/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp
index 7e9f61a..0ffb4dc 100644
--- a/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp
+++ b/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp
@@ -507,6 +507,7 @@ void SCR_UpdateScreen( void ) {
// that case.
if ( cls.uiStarted )
{
+ //Try again here in case we've not done it yet
JKVR_FrameSetup();
for (int eye = 0; eye < 2; ++eye)
diff --git a/Projects/Android/jni/OpenJK/code/qcommon/common.cpp b/Projects/Android/jni/OpenJK/code/qcommon/common.cpp
index 0b7d230..7200f4e 100644
--- a/Projects/Android/jni/OpenJK/code/qcommon/common.cpp
+++ b/Projects/Android/jni/OpenJK/code/qcommon/common.cpp
@@ -24,6 +24,7 @@ along with this program; if not, see .
// common.c -- misc functions used in client and server
+#include
#include "q_shared.h"
#include "qcommon.h"
#include "qcommon/q_version.h"
@@ -1363,6 +1364,8 @@ void Com_Frame( void ) {
int timeVal;
static int lastTime = 0, bias = 0;
+ JKVR_FrameSetup();
+
// write config file if anything changed
Com_WriteConfiguration();
diff --git a/java/com/drbeef/jkquest/GLES3JNIActivity.java b/java/com/drbeef/jkquest/GLES3JNIActivity.java
index 1454fd7..22594d3 100644
--- a/java/com/drbeef/jkquest/GLES3JNIActivity.java
+++ b/java/com/drbeef/jkquest/GLES3JNIActivity.java
@@ -65,6 +65,7 @@ import java.util.Vector;
e.printStackTrace();
}
+ System.loadLibrary("openxr_loader");
System.loadLibrary( "openjk_" + game );
}