mirror of
https://github.com/DrBeef/QuestZDoom.git
synced 2025-04-24 10:08:52 +00:00
Merge branch 'origin/OpenXR'
This commit is contained in:
commit
8c179fad17
18 changed files with 4484 additions and 1129 deletions
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.drbeef.questzdoom"
|
||||
android:versionCode="31"
|
||||
android:versionName="1.5.0" android:installLocation="auto" >
|
||||
android:versionCode="34"
|
||||
android:versionName="1.6.0" android:installLocation="auto" >
|
||||
|
||||
<!-- Tell the system this app requires OpenGL ES 3.1. -->
|
||||
<uses-feature android:glEsVersion="0x00030001" android:required="true"/>
|
||||
|
@ -17,9 +17,17 @@
|
|||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application android:allowBackup="false" android:icon="@drawable/ic_qquest" android:label="@string/qzdoom">
|
||||
|
||||
|
||||
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
||||
|
||||
<!-- META QUEST -->
|
||||
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
|
||||
<meta-data android:name="com.oculus.ossplash" android:value="true"/>
|
||||
|
||||
<!-- PICO XR -->
|
||||
<meta-data android:name="pvr.app.type" android:value="vr" />
|
||||
|
||||
<!-- The activity is the built-in NativeActivity framework class. -->
|
||||
<!-- launchMode is set to singleTask because there should never be multiple copies of the app running. -->
|
||||
<!-- Theme.Black.NoTitleBar.Fullscreen gives solid black instead of a (bad stereoscopic) gradient on app transition. -->
|
||||
|
|
511
Projects/Android/jni/QzDoom/OpenXrInput_MetaQuest.cpp
Normal file
511
Projects/Android/jni/QzDoom/OpenXrInput_MetaQuest.cpp
Normal file
|
@ -0,0 +1,511 @@
|
|||
#ifdef META_QUEST
|
||||
|
||||
#include "VrInput.h"
|
||||
|
||||
extern ovrApp gAppState;
|
||||
|
||||
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 thumbrestLeftTouchAction;
|
||||
XrAction thumbrestRightTouchAction;
|
||||
XrAction vibrateLeftFeedback;
|
||||
XrAction vibrateRightFeedback;
|
||||
XrActionSet runningActionSet;
|
||||
XrSpace leftControllerAimSpace = XR_NULL_HANDLE;
|
||||
XrSpace rightControllerAimSpace = XR_NULL_HANDLE;
|
||||
bool inputInitialized = false;
|
||||
bool useSimpleProfile = false;
|
||||
|
||||
void TBXR_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);
|
||||
thumbrestLeftTouchAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbrest_left", "Thumbrest left", 0, NULL);
|
||||
thumbrestRightTouchAction = CreateAction(runningActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbrest_right", "Thumbrest 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(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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(thumbrestLeftTouchAction, "/user/hand/left/input/thumbrest/touch");
|
||||
bindings[currBinding++] = ActionSuggestedBinding(thumbrestRightTouchAction, "/user/hand/right/input/thumbrest/touch");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
inputInitialized = true;
|
||||
}
|
||||
|
||||
void TBXR_SyncActions( void )
|
||||
{
|
||||
// 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 TBXR_UpdateControllers( )
|
||||
{
|
||||
TBXR_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_Joystick;
|
||||
|
||||
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_Joystick;
|
||||
|
||||
//index finger click
|
||||
if (GetActionStateBoolean(indexLeftAction).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||
if (GetActionStateBoolean(indexRightAction).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||
|
||||
//Thumbrest
|
||||
if (GetActionStateBoolean(thumbrestLeftTouchAction).currentState) leftTrackedRemoteState_new.Touches |= xrButton_ThumbRest;
|
||||
if (GetActionStateBoolean(thumbrestRightTouchAction).currentState) rightTrackedRemoteState_new.Touches |= xrButton_ThumbRest;
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//0 = left, 1 = right
|
||||
float vibration_channel_duration[2] = {0.0f, 0.0f};
|
||||
float vibration_channel_intensity[2] = {0.0f, 0.0f};
|
||||
|
||||
void TBXR_Vibrate( int duration, int chan, float intensity )
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if ((i + 1) & chan)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TBXR_ProcessHaptics() {
|
||||
static float lastFrameTime = 0.0f;
|
||||
float timestamp = (float)(TBXR_GetTimeInMilliSeconds( ));
|
||||
float frametime = timestamp - lastFrameTime;
|
||||
lastFrameTime = timestamp;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (vibration_channel_duration[i] > 0.0f ||
|
||||
vibration_channel_duration[i] == -1.0f) {
|
||||
|
||||
// fire haptics using output action
|
||||
XrHapticVibration vibration = {};
|
||||
vibration.type = XR_TYPE_HAPTIC_VIBRATION;
|
||||
vibration.next = NULL;
|
||||
vibration.amplitude = vibration_channel_intensity[i];
|
||||
vibration.duration = ToXrTime(vibration_channel_duration[i]);
|
||||
vibration.frequency = 3000;
|
||||
XrHapticActionInfo hapticActionInfo = {};
|
||||
hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO;
|
||||
hapticActionInfo.next = NULL;
|
||||
hapticActionInfo.action = 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
|
645
Projects/Android/jni/QzDoom/OpenXrInput_PicoXR.cpp
Normal file
645
Projects/Android/jni/QzDoom/OpenXrInput_PicoXR.cpp
Normal file
|
@ -0,0 +1,645 @@
|
|||
#ifdef PICO_XR
|
||||
|
||||
#include "VrInput.h"
|
||||
|
||||
extern ovrApp gAppState;
|
||||
|
||||
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 TBXR_InitActions( void )
|
||||
{
|
||||
// Create an action set.
|
||||
{
|
||||
XrActionSetCreateInfo actionSetInfo = {};
|
||||
actionSetInfo.type = XR_TYPE_ACTION_SET_CREATE_INFO;
|
||||
strcpy(actionSetInfo.actionSetName, "gameplay");
|
||||
strcpy(actionSetInfo.localizedActionSetName, "Gameplay");
|
||||
actionSetInfo.priority = 0;
|
||||
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 TBXR_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 TBXR_UpdateControllers( )
|
||||
{
|
||||
TBXR_SyncActions();
|
||||
|
||||
//get controller poses
|
||||
for (int i = 0; i < 2; i++) {
|
||||
XrSpaceVelocity vel = {};
|
||||
vel.type = XR_TYPE_SPACE_VELOCITY;
|
||||
XrSpaceLocation loc = {};
|
||||
loc.type = XR_TYPE_SPACE_LOCATION;
|
||||
loc.next = &vel;
|
||||
XrResult res = xrLocateSpace(aimSpace[i], gAppState.CurrentSpace, gAppState.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;
|
||||
leftTrackedRemoteState_new.Touches = 0;
|
||||
if (GetActionStateBoolean(backAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_Enter;
|
||||
if (GetActionStateBoolean(XAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Buttons |= xrButton_X;
|
||||
if (GetActionStateBoolean(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_Joystick;
|
||||
if (GetActionStateFloat(triggerAction, SIDE_LEFT).currentState > 0.5f) leftTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||
|
||||
if (GetActionStateBoolean(ThumbrestTouchAction, SIDE_LEFT).currentState) leftTrackedRemoteState_new.Touches |= xrButton_ThumbRest;
|
||||
|
||||
rightTrackedRemoteState_new.Buttons = 0;
|
||||
rightTrackedRemoteState_new.Touches = 0;
|
||||
if (GetActionStateBoolean(backAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_Enter;
|
||||
if (GetActionStateBoolean(AAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Buttons |= xrButton_A;
|
||||
if (GetActionStateBoolean(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_Joystick;
|
||||
if (GetActionStateFloat(triggerAction, SIDE_RIGHT).currentState > 0.5f) rightTrackedRemoteState_new.Buttons |= xrButton_Trigger;
|
||||
|
||||
if (GetActionStateBoolean(ThumbrestTouchAction, SIDE_RIGHT).currentState) rightTrackedRemoteState_new.Touches |= xrButton_ThumbRest;
|
||||
|
||||
//thumbstick
|
||||
XrActionStateVector2f moveJoystickState;
|
||||
moveJoystickState = GetActionStateVector2(joystickAction, SIDE_LEFT);
|
||||
leftTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
|
||||
leftTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
|
||||
|
||||
moveJoystickState = GetActionStateVector2(joystickAction, SIDE_RIGHT);
|
||||
rightTrackedRemoteState_new.Joystick.x = moveJoystickState.currentState.x;
|
||||
rightTrackedRemoteState_new.Joystick.y = moveJoystickState.currentState.y;
|
||||
}
|
||||
|
||||
|
||||
//0 = left, 1 = right
|
||||
float vibration_channel_duration[2] = {0.0f, 0.0f};
|
||||
float vibration_channel_intensity[2] = {0.0f, 0.0f};
|
||||
|
||||
void TBXR_Vibrate( int duration, int chan, float intensity )
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if ((i + 1) & chan)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TBXR_ProcessHaptics() {
|
||||
static float lastFrameTime = 0.0f;
|
||||
float timestamp = (float)(TBXR_GetTimeInMilliSeconds( ));
|
||||
float frametime = timestamp - lastFrameTime;
|
||||
lastFrameTime = timestamp;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (vibration_channel_duration[i] > 0.0f ||
|
||||
vibration_channel_duration[i] == -1.0f) {
|
||||
|
||||
// fire haptics using output action
|
||||
XrHapticVibration vibration = {};
|
||||
vibration.type = XR_TYPE_HAPTIC_VIBRATION;
|
||||
vibration.next = NULL;
|
||||
vibration.amplitude = vibration_channel_intensity[i];
|
||||
vibration.duration = ToXrTime(vibration_channel_duration[i]);
|
||||
vibration.frequency = 3000;
|
||||
XrHapticActionInfo hapticActionInfo = {};
|
||||
hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO;
|
||||
hapticActionInfo.next = NULL;
|
||||
hapticActionInfo.action = vibrateAction;
|
||||
hapticActionInfo.subactionPath = handSubactionPath[i];
|
||||
OXR(xrApplyHapticFeedback(gAppState.Session, &hapticActionInfo, (const XrHapticBaseHeader*)&vibration));
|
||||
|
||||
if (vibration_channel_duration[i] != -1.0f) {
|
||||
vibration_channel_duration[i] -= frametime;
|
||||
|
||||
if (vibration_channel_duration[i] < 0.0f) {
|
||||
vibration_channel_duration[i] = 0.0f;
|
||||
vibration_channel_intensity[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Stop haptics
|
||||
XrHapticActionInfo hapticActionInfo = {};
|
||||
hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO;
|
||||
hapticActionInfo.next = NULL;
|
||||
hapticActionInfo.action = vibrateAction;
|
||||
hapticActionInfo.subactionPath = handSubactionPath[i];
|
||||
OXR(xrStopHapticFeedback(gAppState.Session, &hapticActionInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //PICO_XR
|
724
Projects/Android/jni/QzDoom/QzDoom_OpenXR.cpp
Normal file
724
Projects/Android/jni/QzDoom/QzDoom_OpenXR.cpp
Normal file
|
@ -0,0 +1,724 @@
|
|||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/prctl.h> // for prctl( PR_SET_NAME )
|
||||
#include <android/log.h>
|
||||
#include <android/native_window_jni.h> // for native window JNI
|
||||
#include <android/input.h>
|
||||
|
||||
#include "argtable3.h"
|
||||
#include "VrInput.h"
|
||||
|
||||
|
||||
//#define ENABLE_GL_DEBUG
|
||||
#define ENABLE_GL_DEBUG_VERBOSE 1
|
||||
|
||||
//Let's go to the maximum!
|
||||
extern int NUM_MULTI_SAMPLES;
|
||||
extern int REFRESH ;
|
||||
extern float SS_MULTIPLIER ;
|
||||
|
||||
|
||||
/* global arg_xxx structs */
|
||||
struct arg_dbl *ss;
|
||||
struct arg_int *cpu;
|
||||
struct arg_int *gpu;
|
||||
struct arg_int *msaa;
|
||||
struct arg_int *refresh;
|
||||
struct arg_end *end;
|
||||
|
||||
char **argv;
|
||||
int argc=0;
|
||||
|
||||
|
||||
//Define all variables here that were externs in the VrCommon.h
|
||||
bool qzdoom_initialised;
|
||||
long long global_time;
|
||||
float playerYaw;
|
||||
bool resetDoomYaw;
|
||||
bool resetPreviousPitch;
|
||||
float doomYaw;
|
||||
float previousPitch;
|
||||
float vrFOV;
|
||||
vec3_t worldPosition;
|
||||
vec3_t hmdPosition;
|
||||
vec3_t hmdorientation;
|
||||
vec3_t positionDeltaThisFrame;
|
||||
vec3_t weaponangles;
|
||||
vec3_t weaponoffset;
|
||||
bool weaponStabilised;
|
||||
|
||||
vec3_t offhandangles;
|
||||
vec3_t offhandoffset;
|
||||
bool player_moving;
|
||||
bool shutdown;
|
||||
bool ready_teleport;
|
||||
bool trigger_teleport;
|
||||
bool cinemamode;
|
||||
|
||||
//This is now controlled by the engine
|
||||
static bool useVirtualScreen = true;
|
||||
|
||||
static bool hasIWADs = false;
|
||||
static bool hasLauncher = false;
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
QuestZDoom Stuff
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
void QzDoom_setUseScreenLayer(bool use)
|
||||
{
|
||||
useVirtualScreen = use;
|
||||
}
|
||||
|
||||
int QzDoom_SetRefreshRate(int refreshRate)
|
||||
{
|
||||
#ifdef META_QUEST
|
||||
OXR(gAppState.pfnRequestDisplayRefreshRate(gAppState.Session, (float)refreshRate));
|
||||
return refreshRate;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QzDoom_GetScreenRes(uint32_t *width, uint32_t *height)
|
||||
{
|
||||
int iWidth, iHeight;
|
||||
TBXR_GetScreenRes(&iWidth, &iHeight);
|
||||
*width = iWidth;
|
||||
*height = iHeight;
|
||||
}
|
||||
|
||||
bool VR_UseScreenLayer()
|
||||
{
|
||||
return useVirtualScreen || cinemamode;
|
||||
}
|
||||
|
||||
float VR_GetScreenLayerDistance()
|
||||
{
|
||||
return 4.0f;
|
||||
}
|
||||
|
||||
static void UnEscapeQuotes( char *arg )
|
||||
{
|
||||
char *last = NULL;
|
||||
while( *arg ) {
|
||||
if( *arg == '"' && *last == '\\' ) {
|
||||
char *c_curr = arg;
|
||||
char *c_last = last;
|
||||
while( *c_curr ) {
|
||||
*c_last = *c_curr;
|
||||
c_last = c_curr;
|
||||
c_curr++;
|
||||
}
|
||||
*c_last = '\0';
|
||||
}
|
||||
last = arg;
|
||||
arg++;
|
||||
}
|
||||
}
|
||||
|
||||
static int ParseCommandLine(char *cmdline, char **argv)
|
||||
{
|
||||
char *bufp;
|
||||
char *lastp = NULL;
|
||||
int argc, last_argc;
|
||||
argc = last_argc = 0;
|
||||
for ( bufp = cmdline; *bufp; ) {
|
||||
while ( isspace(*bufp) ) {
|
||||
++bufp;
|
||||
}
|
||||
if ( *bufp == '"' ) {
|
||||
++bufp;
|
||||
if ( *bufp ) {
|
||||
if ( argv ) {
|
||||
argv[argc] = bufp;
|
||||
}
|
||||
++argc;
|
||||
}
|
||||
while ( *bufp && ( *bufp != '"' || *lastp == '\\' ) ) {
|
||||
lastp = bufp;
|
||||
++bufp;
|
||||
}
|
||||
} else {
|
||||
if ( *bufp ) {
|
||||
if ( argv ) {
|
||||
argv[argc] = bufp;
|
||||
}
|
||||
++argc;
|
||||
}
|
||||
while ( *bufp && ! isspace(*bufp) ) {
|
||||
++bufp;
|
||||
}
|
||||
}
|
||||
if ( *bufp ) {
|
||||
if ( argv ) {
|
||||
*bufp = '\0';
|
||||
}
|
||||
++bufp;
|
||||
}
|
||||
if( argv && last_argc != argc ) {
|
||||
UnEscapeQuotes( argv[last_argc] );
|
||||
}
|
||||
last_argc = argc;
|
||||
}
|
||||
if ( argv ) {
|
||||
argv[argc] = NULL;
|
||||
}
|
||||
return(argc);
|
||||
}
|
||||
|
||||
|
||||
void VR_SetHMDOrientation(float pitch, float yaw, float roll)
|
||||
{
|
||||
VectorSet(hmdorientation, pitch, yaw, roll);
|
||||
|
||||
if (!VR_UseScreenLayer())
|
||||
{
|
||||
playerYaw = yaw;
|
||||
}
|
||||
}
|
||||
|
||||
void VR_SetHMDPosition(float x, float y, float z )
|
||||
{
|
||||
VectorSet(hmdPosition, x, y, z);
|
||||
|
||||
positionDeltaThisFrame[0] = (worldPosition[0] - x);
|
||||
positionDeltaThisFrame[1] = (worldPosition[1] - y);
|
||||
positionDeltaThisFrame[2] = (worldPosition[2] - z);
|
||||
|
||||
worldPosition[0] = x;
|
||||
worldPosition[1] = y;
|
||||
worldPosition[2] = z;
|
||||
}
|
||||
|
||||
void VR_GetMove(float *joy_forward, float *joy_side, float *hmd_forward, float *hmd_side, float *up,
|
||||
float *yaw, float *pitch, float *roll)
|
||||
{
|
||||
*joy_forward = remote_movementForward;
|
||||
*hmd_forward = positional_movementForward;
|
||||
*up = remote_movementUp;
|
||||
*joy_side = remote_movementSideways;
|
||||
*hmd_side = positional_movementSideways;
|
||||
*yaw = cinemamode ? cinemamodeYaw : hmdorientation[YAW] + snapTurn;
|
||||
*pitch = cinemamode ? cinemamodePitch : hmdorientation[PITCH];
|
||||
*roll = cinemamode ? 0.0f : hmdorientation[ROLL];
|
||||
}
|
||||
|
||||
void VR_DoomMain(int argc, char** argv);
|
||||
|
||||
void VR_Init()
|
||||
{
|
||||
//Initialise all our variables
|
||||
playerYaw = 0.0f;
|
||||
resetDoomYaw = true;
|
||||
resetPreviousPitch = true;
|
||||
remote_movementSideways = 0.0f;
|
||||
remote_movementForward = 0.0f;
|
||||
remote_movementUp = 0.0f;
|
||||
positional_movementSideways = 0.0f;
|
||||
positional_movementForward = 0.0f;
|
||||
snapTurn = 0.0f;
|
||||
cinemamodeYaw = 0.0f;
|
||||
cinemamodePitch = 0.0f;
|
||||
|
||||
//init randomiser
|
||||
srand(time(NULL));
|
||||
|
||||
shutdown = false;
|
||||
ready_teleport = false;
|
||||
trigger_teleport = false;
|
||||
|
||||
cinemamode = false;
|
||||
|
||||
chdir("/sdcard/QuestZDoom");
|
||||
}
|
||||
|
||||
int VR_main( int argc, char* argv[] );
|
||||
|
||||
void * AppThreadFunction(void * parm ) {
|
||||
gAppThread = (ovrAppThread *) parm;
|
||||
|
||||
java.Vm = gAppThread->JavaVm;
|
||||
java.Vm->AttachCurrentThread(&java.Env, NULL);
|
||||
java.ActivityObject = gAppThread->ActivityObject;
|
||||
|
||||
jclass cls = java.Env->GetObjectClass(java.ActivityObject);
|
||||
|
||||
// Note that AttachCurrentThread will reset the thread name.
|
||||
prctl(PR_SET_NAME, (long) "AppThreadFunction", 0, 0, 0);
|
||||
|
||||
//Set device defaults
|
||||
if (SS_MULTIPLIER == 0.0f)
|
||||
{
|
||||
//GB Override as refresh is now 72 by default as we decided a higher res is better as 90hz has stutters
|
||||
SS_MULTIPLIER = 1.25f;
|
||||
}
|
||||
else if (SS_MULTIPLIER > 1.5f)
|
||||
{
|
||||
SS_MULTIPLIER = 1.5f;
|
||||
}
|
||||
|
||||
gAppState.MainThreadTid = gettid();
|
||||
|
||||
VR_Init();
|
||||
|
||||
TBXR_InitialiseOpenXR();
|
||||
|
||||
TBXR_EnterVR();
|
||||
TBXR_InitRenderer();
|
||||
TBXR_InitActions();
|
||||
|
||||
TBXR_WaitForSessionActive();
|
||||
|
||||
if (REFRESH != 0)
|
||||
{
|
||||
QzDoom_SetRefreshRate(REFRESH);
|
||||
}
|
||||
|
||||
if (hasIWADs)// && hasLauncher)
|
||||
{
|
||||
//Should now be all set up and ready - start the Doom main loop
|
||||
VR_DoomMain(argc, argv);
|
||||
}
|
||||
|
||||
TBXR_LeaveVR();
|
||||
|
||||
//Ask Java to shut down
|
||||
jni_shutdown();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//All the stuff we want to do each frame specifically for this game
|
||||
void VR_FrameSetup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool VR_GetVRProjection(int eye, float zNear, float zFar, float* projection)
|
||||
{
|
||||
#ifdef PICO_XR
|
||||
XrMatrix4x4f_CreateProjectionFov(
|
||||
&(gAppState.ProjectionMatrices[eye]), GRAPHICS_OPENGL_ES,
|
||||
gAppState.Projections[eye].fov, zNear, zFar);
|
||||
#endif
|
||||
|
||||
#ifdef META_QUEST
|
||||
XrFovf fov = {};
|
||||
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||
fov.angleLeft += gAppState.Projections[eye].fov.angleLeft / 2.0f;
|
||||
fov.angleRight += gAppState.Projections[eye].fov.angleRight / 2.0f;
|
||||
fov.angleUp += gAppState.Projections[eye].fov.angleUp / 2.0f;
|
||||
fov.angleDown += gAppState.Projections[eye].fov.angleDown / 2.0f;
|
||||
}
|
||||
XrMatrix4x4f_CreateProjectionFov(
|
||||
&(gAppState.ProjectionMatrices[eye]), GRAPHICS_OPENGL_ES,
|
||||
fov, zNear, zFar);
|
||||
#endif
|
||||
|
||||
memcpy(projection, gAppState.ProjectionMatrices[eye].m, 16 * sizeof(float));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
void jni_haptic_event(const char *event, int position, int intensity, float angle, float yHeight);
|
||||
void jni_haptic_updateevent(const char *event, int intensity, float angle);
|
||||
void jni_haptic_stopevent(const char *event);
|
||||
void jni_haptic_endframe();
|
||||
void jni_haptic_enable();
|
||||
void jni_haptic_disable();
|
||||
};
|
||||
|
||||
void VR_ExternalHapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight )
|
||||
{
|
||||
jni_haptic_event(event, position, intensity, angle, yHeight);
|
||||
}
|
||||
|
||||
void VR_HapticStopEvent(const char* event)
|
||||
{
|
||||
jni_haptic_stopevent(event);
|
||||
}
|
||||
|
||||
void VR_HapticEnable()
|
||||
{
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
jni_haptic_enable();
|
||||
firstTime = false;
|
||||
jni_haptic_event("fire_pistol", 0, 100, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void VR_HapticDisable()
|
||||
{
|
||||
jni_haptic_disable();
|
||||
}
|
||||
|
||||
void VR_HapticEvent(const char* event, int position, int intensity, float angle, float yHeight )
|
||||
{
|
||||
static char buffer[256];
|
||||
|
||||
memset(buffer, 0, 256);
|
||||
for(int i = 0; event[i]; i++)
|
||||
{
|
||||
buffer[i] = tolower(event[i]);
|
||||
}
|
||||
|
||||
jni_haptic_event(buffer, position, intensity, angle, yHeight);
|
||||
}
|
||||
|
||||
void QzDoom_Vibrate(float duration, int channel, float intensity )
|
||||
{
|
||||
TBXR_Vibrate(duration, channel+1, intensity);
|
||||
}
|
||||
|
||||
void VR_HandleControllerInput() {
|
||||
TBXR_UpdateControllers();
|
||||
|
||||
//Call additional control schemes here
|
||||
switch (vr_control_scheme)
|
||||
{
|
||||
case RIGHT_HANDED_DEFAULT:
|
||||
HandleInput_Default(vr_control_scheme,
|
||||
&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
|
||||
&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
|
||||
xrButton_A, xrButton_B, xrButton_X, xrButton_Y);
|
||||
break;
|
||||
case LEFT_HANDED_DEFAULT:
|
||||
case LEFT_HANDED_ALT:
|
||||
HandleInput_Default(vr_control_scheme,
|
||||
&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
|
||||
&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
|
||||
xrButton_X, xrButton_Y, xrButton_A, xrButton_B);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
Activity lifecycle
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
jmethodID android_shutdown;
|
||||
static JavaVM *jVM;
|
||||
static jobject jniCallbackObj=0;
|
||||
|
||||
void jni_shutdown()
|
||||
{
|
||||
ALOGV("Calling: jni_shutdown");
|
||||
JNIEnv *env;
|
||||
jobject tmp;
|
||||
if ((jVM->GetEnv((void**) &env, JNI_VERSION_1_4))<0)
|
||||
{
|
||||
jVM->AttachCurrentThread(&env, NULL);
|
||||
}
|
||||
return env->CallVoidMethod(jniCallbackObj, android_shutdown);
|
||||
}
|
||||
|
||||
void VR_Shutdown()
|
||||
{
|
||||
jni_shutdown();
|
||||
}
|
||||
|
||||
jmethodID android_haptic_event;
|
||||
jmethodID android_haptic_stopevent;
|
||||
jmethodID android_haptic_enable;
|
||||
jmethodID android_haptic_disable;
|
||||
|
||||
void jni_haptic_event(const char* event, int position, int intensity, float angle, float yHeight)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jobject tmp;
|
||||
if ((jVM->GetEnv((void**) &env, JNI_VERSION_1_4))<0)
|
||||
{
|
||||
jVM->AttachCurrentThread(&env, NULL);
|
||||
}
|
||||
|
||||
jstring StringArg1 = env->NewStringUTF(event);
|
||||
|
||||
return env->CallVoidMethod(jniCallbackObj, android_haptic_event, StringArg1, position, intensity, angle, yHeight);
|
||||
}
|
||||
|
||||
void jni_haptic_stopevent(const char* event)
|
||||
{
|
||||
ALOGV("Calling: jni_haptic_stopevent");
|
||||
JNIEnv *env;
|
||||
jobject tmp;
|
||||
if ((jVM->GetEnv((void**) &env, JNI_VERSION_1_4))<0)
|
||||
{
|
||||
jVM->AttachCurrentThread(&env, NULL);
|
||||
}
|
||||
|
||||
jstring StringArg1 = env->NewStringUTF(event);
|
||||
|
||||
return env->CallVoidMethod(jniCallbackObj, android_haptic_stopevent, StringArg1);
|
||||
}
|
||||
|
||||
|
||||
void jni_haptic_enable()
|
||||
{
|
||||
ALOGV("Calling: jni_haptic_enable");
|
||||
JNIEnv *env;
|
||||
jobject tmp;
|
||||
if ((jVM->GetEnv((void**) &env, JNI_VERSION_1_4))<0)
|
||||
{
|
||||
jVM->AttachCurrentThread(&env, NULL);
|
||||
}
|
||||
|
||||
return env->CallVoidMethod(jniCallbackObj, android_haptic_enable);
|
||||
}
|
||||
|
||||
void jni_haptic_disable()
|
||||
{
|
||||
ALOGV("Calling: jni_haptic_disable");
|
||||
JNIEnv *env;
|
||||
jobject tmp;
|
||||
if ((jVM->GetEnv((void**) &env, JNI_VERSION_1_4))<0)
|
||||
{
|
||||
jVM->AttachCurrentThread(&env, NULL);
|
||||
}
|
||||
|
||||
return env->CallVoidMethod(jniCallbackObj, android_haptic_disable);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
int JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jVM = vm;
|
||||
if(vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
|
||||
{
|
||||
ALOGE("Failed JNI_OnLoad");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onCreate( JNIEnv * env, jclass activityClass, jobject activity,
|
||||
jstring commandLineParams, jboolean jHasIWADs, jboolean jHasLauncher)
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onCreate()" );
|
||||
|
||||
/* the global arg_xxx structs are initialised within the argtable */
|
||||
void *argtable[] = {
|
||||
ss = arg_dbl0("s", "supersampling", "<double>", "super sampling value (default: Q1: 1.2, Q2: 1.35)"),
|
||||
cpu = arg_int0("c", "cpu", "<int>", "CPU perf index 1-4 (default: 2)"),
|
||||
gpu = arg_int0("g", "gpu", "<int>", "GPU perf index 1-4 (default: 3)"),
|
||||
msaa = arg_int0("m", "msaa", "<int>", "MSAA (default: 1)"),
|
||||
refresh = arg_int0("r", "refresh", "<int>", "Refresh Rate (default: Q1: 72, Q2: 72)"),
|
||||
end = arg_end(20)
|
||||
};
|
||||
|
||||
hasIWADs = jHasIWADs != 0;
|
||||
hasLauncher = jHasLauncher != 0;
|
||||
|
||||
jboolean iscopy;
|
||||
const char *arg = env->GetStringUTFChars(commandLineParams, &iscopy);
|
||||
|
||||
char *cmdLine = NULL;
|
||||
if (arg && strlen(arg))
|
||||
{
|
||||
cmdLine = strdup(arg);
|
||||
}
|
||||
|
||||
env->ReleaseStringUTFChars(commandLineParams, arg);
|
||||
|
||||
ALOGV("Command line %s", cmdLine);
|
||||
argv = (char**)malloc(sizeof(char*) * 255);
|
||||
argc = ParseCommandLine(strdup(cmdLine), argv);
|
||||
|
||||
/* verify the argtable[] entries were allocated sucessfully */
|
||||
if (arg_nullcheck(argtable) == 0) {
|
||||
/* Parse the command line as defined by argtable[] */
|
||||
arg_parse(argc, argv, argtable);
|
||||
|
||||
if (ss->count > 0 && ss->dval[0] > 0.0)
|
||||
{
|
||||
SS_MULTIPLIER = ss->dval[0];
|
||||
}
|
||||
|
||||
if (msaa->count > 0 && msaa->ival[0] > 0 && msaa->ival[0] < 10)
|
||||
{
|
||||
NUM_MULTI_SAMPLES = msaa->ival[0];
|
||||
}
|
||||
|
||||
if (refresh->count > 0 && refresh->ival[0] > 0 && refresh->ival[0] <= 120)
|
||||
{
|
||||
REFRESH = refresh->ival[0];
|
||||
}
|
||||
}
|
||||
|
||||
ovrAppThread * appThread = (ovrAppThread *) malloc( sizeof( ovrAppThread ) );
|
||||
ovrAppThread_Create( appThread, env, activity, activityClass );
|
||||
|
||||
surfaceMessageQueue_Enable(&appThread->MessageQueue, true);
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_CREATE, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
|
||||
return (jlong)((size_t)appThread);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onStart( JNIEnv * env, jobject obj, jlong handle, jobject obj1)
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onStart()" );
|
||||
|
||||
|
||||
jniCallbackObj = (jobject)env->NewGlobalRef( obj1);
|
||||
jclass callbackClass = env->GetObjectClass( jniCallbackObj);
|
||||
|
||||
android_shutdown = env->GetMethodID(callbackClass,"shutdown","()V");
|
||||
|
||||
android_haptic_event = env->GetMethodID(callbackClass, "haptic_event", "(Ljava/lang/String;IIFF)V");
|
||||
android_haptic_stopevent = env->GetMethodID(callbackClass, "haptic_stopevent", "(Ljava/lang/String;)V");
|
||||
android_haptic_enable = env->GetMethodID(callbackClass, "haptic_enable", "()V");
|
||||
android_haptic_disable = env->GetMethodID(callbackClass, "haptic_disable", "()V");
|
||||
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_START, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onResume( JNIEnv * env, jobject obj, jlong handle )
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onResume()" );
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_RESUME, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onPause( JNIEnv * env, jobject obj, jlong handle )
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onPause()" );
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_PAUSE, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onStop( JNIEnv * env, jobject obj, jlong handle )
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onStop()" );
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_STOP, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onDestroy( JNIEnv * env, jobject obj, jlong handle )
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onDestroy()" );
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_DESTROY, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
surfaceMessageQueue_Enable(&appThread->MessageQueue, false);
|
||||
|
||||
ovrAppThread_Destroy( appThread, env );
|
||||
free( appThread );
|
||||
}
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
Surface lifecycle
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onSurfaceCreated( JNIEnv * env, jobject obj, jlong handle, jobject surface )
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onSurfaceCreated()" );
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
|
||||
ANativeWindow * newNativeWindow = ANativeWindow_fromSurface( env, surface );
|
||||
if ( ANativeWindow_getWidth( newNativeWindow ) < ANativeWindow_getHeight( newNativeWindow ) )
|
||||
{
|
||||
// An app that is relaunched after pressing the home button gets an initial surface with
|
||||
// the wrong orientation even though android:screenOrientation="landscape" is set in the
|
||||
// manifest. The choreographer callback will also never be called for this surface because
|
||||
// the surface is immediately replaced with a new surface with the correct orientation.
|
||||
ALOGE( " Surface not in landscape mode!" );
|
||||
}
|
||||
|
||||
ALOGV( " NativeWindow = ANativeWindow_fromSurface( env, surface )" );
|
||||
appThread->NativeWindow = newNativeWindow;
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_SURFACE_CREATED, MQ_WAIT_PROCESSED);
|
||||
surfaceMessage_SetPointerParm(&message, 0, appThread->NativeWindow);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onSurfaceChanged( JNIEnv * env, jobject obj, jlong handle, jobject surface )
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onSurfaceChanged()" );
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
|
||||
ANativeWindow * newNativeWindow = ANativeWindow_fromSurface( env, surface );
|
||||
if ( ANativeWindow_getWidth( newNativeWindow ) < ANativeWindow_getHeight( newNativeWindow ) )
|
||||
{
|
||||
// An app that is relaunched after pressing the home button gets an initial surface with
|
||||
// the wrong orientation even though android:screenOrientation="landscape" is set in the
|
||||
// manifest. The choreographer callback will also never be called for this surface because
|
||||
// the surface is immediately replaced with a new surface with the correct orientation.
|
||||
ALOGE( " Surface not in landscape mode!" );
|
||||
}
|
||||
|
||||
if ( newNativeWindow != appThread->NativeWindow )
|
||||
{
|
||||
if ( appThread->NativeWindow != NULL )
|
||||
{
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_SURFACE_DESTROYED, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
ALOGV( " ANativeWindow_release( NativeWindow )" );
|
||||
ANativeWindow_release( appThread->NativeWindow );
|
||||
appThread->NativeWindow = NULL;
|
||||
}
|
||||
if ( newNativeWindow != NULL )
|
||||
{
|
||||
ALOGV( " NativeWindow = ANativeWindow_fromSurface( env, surface )" );
|
||||
appThread->NativeWindow = newNativeWindow;
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_SURFACE_CREATED, MQ_WAIT_PROCESSED);
|
||||
surfaceMessage_SetPointerParm(&message, 0, appThread->NativeWindow);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
}
|
||||
}
|
||||
else if ( newNativeWindow != NULL )
|
||||
{
|
||||
ANativeWindow_release( newNativeWindow );
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_drbeef_questzdoom_GLES3JNILib_onSurfaceDestroyed( JNIEnv * env, jobject obj, jlong handle )
|
||||
{
|
||||
ALOGV( " GLES3JNILib::onSurfaceDestroyed()" );
|
||||
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
|
||||
srufaceMessage message;
|
||||
surfaceMessage_Init(&message, MESSAGE_ON_SURFACE_DESTROYED, MQ_WAIT_PROCESSED);
|
||||
surfaceMessageQueue_PostMessage(&appThread->MessageQueue, &message);
|
||||
ALOGV( " ANativeWindow_release( NativeWindow )" );
|
||||
ANativeWindow_release( appThread->NativeWindow );
|
||||
appThread->NativeWindow = NULL;
|
||||
}
|
||||
|
||||
}
|
2027
Projects/Android/jni/QzDoom/TBXR_Common.cpp
Normal file
2027
Projects/Android/jni/QzDoom/TBXR_Common.cpp
Normal file
File diff suppressed because it is too large
Load diff
337
Projects/Android/jni/QzDoom/TBXR_Common.h
Normal file
337
Projects/Android/jni/QzDoom/TBXR_Common.h
Normal file
|
@ -0,0 +1,337 @@
|
|||
#if !defined(tbxr_common_h)
|
||||
#define tbxr_common_h
|
||||
|
||||
//OpenXR
|
||||
#define XR_USE_GRAPHICS_API_OPENGL_ES 1
|
||||
#define XR_USE_PLATFORM_ANDROID 1
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES3/gl3ext.h>
|
||||
#include <jni.h>
|
||||
#include <openxr/openxr.h>
|
||||
#include <openxr/openxr_platform.h>
|
||||
#include <openxr/openxr_oculus_helpers.h>
|
||||
|
||||
#include <android/native_window_jni.h>
|
||||
#include <android/log.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define DEBUG 1
|
||||
#endif
|
||||
|
||||
#define LOG_TAG "TBXR"
|
||||
|
||||
|
||||
#define ALOGE(...) __android_log_print( ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__ )
|
||||
|
||||
#if DEBUG
|
||||
#define ALOGV(...) __android_log_print( ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__ )
|
||||
#else
|
||||
#define ALOGV(...)
|
||||
#endif
|
||||
|
||||
enum { ovrMaxLayerCount = 1 };
|
||||
enum { ovrMaxNumEyes = 2 };
|
||||
|
||||
typedef enum xrButton_ {
|
||||
xrButton_A = 0x00000001,
|
||||
xrButton_B = 0x00000002,
|
||||
xrButton_RThumb = 0x00000004,
|
||||
xrButton_RShoulder = 0x00000008,
|
||||
xrButton_X = 0x00000100,
|
||||
xrButton_Y = 0x00000200,
|
||||
xrButton_LThumb = 0x00000400,
|
||||
xrButton_LShoulder = 0x00000800,
|
||||
xrButton_Up = 0x00010000,
|
||||
xrButton_Down = 0x00020000,
|
||||
xrButton_Left = 0x00040000,
|
||||
xrButton_Right = 0x00080000,
|
||||
xrButton_Enter = 0x00100000,
|
||||
xrButton_Back = 0x00200000,
|
||||
xrButton_GripTrigger = 0x04000000,
|
||||
xrButton_Trigger = 0x20000000,
|
||||
xrButton_Joystick = 0x80000000,
|
||||
|
||||
//Define additional controller touch points (not button presses)
|
||||
xrButton_ThumbRest = 0x00000010,
|
||||
|
||||
xrButton_EnumSize = 0x7fffffff
|
||||
} xrButton;
|
||||
|
||||
typedef struct {
|
||||
uint32_t Buttons;
|
||||
uint32_t Touches;
|
||||
float IndexTrigger;
|
||||
float GripTrigger;
|
||||
XrVector2f Joystick;
|
||||
} ovrInputStateTrackedRemote;
|
||||
|
||||
typedef struct {
|
||||
GLboolean Active;
|
||||
XrPosef Pose;
|
||||
XrSpaceVelocity Velocity;
|
||||
} ovrTrackedController;
|
||||
|
||||
typedef enum control_scheme {
|
||||
RIGHT_HANDED_DEFAULT = 0,
|
||||
LEFT_HANDED_DEFAULT = 10,
|
||||
LEFT_HANDED_ALT = 11
|
||||
} control_scheme_t;
|
||||
|
||||
typedef struct {
|
||||
float M[4][4];
|
||||
} ovrMatrix4f;
|
||||
|
||||
|
||||
typedef struct {
|
||||
XrSwapchain Handle;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
} ovrSwapChain;
|
||||
|
||||
typedef struct {
|
||||
int Width;
|
||||
int Height;
|
||||
int Multisamples;
|
||||
uint32_t TextureSwapChainLength;
|
||||
uint32_t TextureSwapChainIndex;
|
||||
ovrSwapChain ColorSwapChain;
|
||||
XrSwapchainImageOpenGLESKHR* ColorSwapChainImage;
|
||||
GLuint* DepthBuffers;
|
||||
GLuint* FrameBuffers;
|
||||
} ovrFramebuffer;
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrRenderer
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ovrFramebuffer FrameBuffer[ovrMaxNumEyes];
|
||||
} ovrRenderer;
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrApp
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MQ_WAIT_NONE, // don't wait
|
||||
MQ_WAIT_RECEIVED, // wait until the consumer thread has received the message
|
||||
MQ_WAIT_PROCESSED // wait until the consumer thread has processed the message
|
||||
} ovrMQWait;
|
||||
|
||||
#define MAX_MESSAGE_PARMS 8
|
||||
#define MAX_MESSAGES 1024
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Id;
|
||||
ovrMQWait Wait;
|
||||
long long Parms[MAX_MESSAGE_PARMS];
|
||||
} srufaceMessage;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
srufaceMessage Messages[MAX_MESSAGES];
|
||||
volatile int Head; // dequeue at the head
|
||||
volatile int Tail; // enqueue at the tail
|
||||
ovrMQWait Wait;
|
||||
volatile bool EnabledFlag;
|
||||
volatile bool PostedFlag;
|
||||
volatile bool ReceivedFlag;
|
||||
volatile bool ProcessedFlag;
|
||||
pthread_mutex_t Mutex;
|
||||
pthread_cond_t PostedCondition;
|
||||
pthread_cond_t ReceivedCondition;
|
||||
pthread_cond_t ProcessedCondition;
|
||||
} surfaceMessageQueue;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
JavaVM * JavaVm;
|
||||
jobject ActivityObject;
|
||||
jclass ActivityClass;
|
||||
pthread_t Thread;
|
||||
surfaceMessageQueue MessageQueue;
|
||||
ANativeWindow * NativeWindow;
|
||||
} ovrAppThread;
|
||||
|
||||
|
||||
typedef union {
|
||||
XrCompositionLayerProjection Projection;
|
||||
XrCompositionLayerQuad Quad;
|
||||
} xrCompositorLayer_Union;
|
||||
|
||||
#define GL(func) func;
|
||||
|
||||
// Forward declarations
|
||||
XrInstance TBXR_GetXrInstance();
|
||||
|
||||
#if defined(DEBUG)
|
||||
static void
|
||||
OXR_CheckErrors(XrInstance instance, XrResult result, const char* function, bool failOnError) {
|
||||
if (XR_FAILED(result)) {
|
||||
char errorBuffer[XR_MAX_RESULT_STRING_SIZE];
|
||||
xrResultToString(instance, result, errorBuffer);
|
||||
if (failOnError) {
|
||||
ALOGE("OpenXR error: %s: %s\n", function, errorBuffer);
|
||||
} else {
|
||||
ALOGV("OpenXR error: %s: %s\n", function, errorBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
#define OXR(func) OXR_CheckErrors(TBXR_GetXrInstance(), func, #func, true);
|
||||
#else
|
||||
#define OXR(func) func;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
EGLint MajorVersion;
|
||||
EGLint MinorVersion;
|
||||
EGLDisplay Display;
|
||||
EGLConfig Config;
|
||||
EGLSurface TinySurface;
|
||||
EGLSurface MainSurface;
|
||||
EGLContext Context;
|
||||
} ovrEgl;
|
||||
|
||||
/// Java details about an activity
|
||||
typedef struct ovrJava_ {
|
||||
JavaVM* Vm; //< Java Virtual Machine
|
||||
JNIEnv* Env; //< Thread specific environment
|
||||
jobject ActivityObject; //< Java activity object
|
||||
} ovrJava;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ovrJava Java;
|
||||
ovrEgl Egl;
|
||||
ANativeWindow* NativeWindow;
|
||||
bool Resumed;
|
||||
bool Focused;
|
||||
int FrameSetupRefCount;
|
||||
|
||||
float Width;
|
||||
float Height;
|
||||
|
||||
XrInstance Instance;
|
||||
XrSession Session;
|
||||
XrViewConfigurationProperties ViewportConfig;
|
||||
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
|
||||
XrSystemId SystemId;
|
||||
XrSpace HeadSpace;
|
||||
XrSpace StageSpace;
|
||||
XrSpace FakeStageSpace;
|
||||
XrSpace CurrentSpace;
|
||||
GLboolean SessionActive;
|
||||
XrPosef xfStageFromHead;
|
||||
XrView* Projections;
|
||||
XrMatrix4x4f ProjectionMatrices[2];
|
||||
|
||||
|
||||
float currentDisplayRefreshRate;
|
||||
float* SupportedDisplayRefreshRates;
|
||||
uint32_t RequestedDisplayRefreshRateIndex;
|
||||
uint32_t NumSupportedDisplayRefreshRates;
|
||||
PFN_xrGetDisplayRefreshRateFB pfnGetDisplayRefreshRate;
|
||||
PFN_xrRequestDisplayRefreshRateFB pfnRequestDisplayRefreshRate;
|
||||
|
||||
XrTime PredictedDisplayTime;
|
||||
int SwapInterval;
|
||||
int MainThreadTid;
|
||||
int RenderThreadTid;
|
||||
xrCompositorLayer_Union Layers[ovrMaxLayerCount];
|
||||
int LayerCount;
|
||||
ovrRenderer Renderer;
|
||||
ovrTrackedController TrackedController[2];
|
||||
} ovrApp;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
MESSAGE_ON_CREATE,
|
||||
MESSAGE_ON_START,
|
||||
MESSAGE_ON_RESUME,
|
||||
MESSAGE_ON_PAUSE,
|
||||
MESSAGE_ON_STOP,
|
||||
MESSAGE_ON_DESTROY,
|
||||
MESSAGE_ON_SURFACE_CREATED,
|
||||
MESSAGE_ON_SURFACE_DESTROYED
|
||||
};
|
||||
|
||||
extern ovrAppThread * gAppThread;
|
||||
extern ovrApp gAppState;
|
||||
extern ovrJava java;
|
||||
|
||||
|
||||
void ovrTrackedController_Clear(ovrTrackedController* controller);
|
||||
|
||||
void * AppThreadFunction(void * parm );
|
||||
|
||||
void ovrAppThread_Create( ovrAppThread * appThread, JNIEnv * env, jobject activityObject, jclass activityClass );
|
||||
void ovrAppThread_Destroy( ovrAppThread * appThread, JNIEnv * env );
|
||||
|
||||
/*
|
||||
* Surface Lifecycle Message Queue
|
||||
*/
|
||||
void surfaceMessage_Init(srufaceMessage * message, const int id, const int wait );
|
||||
void * surfaceMessage_GetPointerParm(srufaceMessage * message, int index );
|
||||
void surfaceMessage_SetPointerParm(srufaceMessage * message, int index, void * ptr );
|
||||
|
||||
void surfaceMessageQueue_Create(surfaceMessageQueue * messageQueue );
|
||||
void surfaceMessageQueue_Destroy(surfaceMessageQueue * messageQueue );
|
||||
void surfaceMessageQueue_Enable(surfaceMessageQueue * messageQueue, const bool set );
|
||||
void surfaceMessageQueue_PostMessage(surfaceMessageQueue * messageQueue, const srufaceMessage * message );
|
||||
|
||||
//Functions that need to be implemented by the game specific code
|
||||
void VR_FrameSetup();
|
||||
bool VR_UseScreenLayer();
|
||||
float VR_GetScreenLayerDistance();
|
||||
bool VR_GetVRProjection(int eye, float zNear, float zFar, float* projection);
|
||||
void VR_HandleControllerInput();
|
||||
void VR_SetHMDOrientation(float pitch, float yaw, float roll );
|
||||
void VR_SetHMDPosition(float x, float y, float z );
|
||||
void VR_HapticEvent(const char* event, int position, int intensity, float angle, float yHeight );
|
||||
void VR_HapticUpdateEvent(const char* event, int intensity, float angle );
|
||||
void VR_HapticEndFrame();
|
||||
void VR_HapticStopEvent(const char* event);
|
||||
void VR_HapticEnable();
|
||||
void VR_HapticDisable();
|
||||
extern "C" void VR_Shutdown();
|
||||
|
||||
|
||||
//Reusable Team Beef OpenXR stuff (in TBXR_Common.cpp)
|
||||
double TBXR_GetTimeInMilliSeconds();
|
||||
int TBXR_GetRefresh();
|
||||
void TBXR_Recenter();
|
||||
void TBXR_InitialiseOpenXR();
|
||||
void TBXR_WaitForSessionActive();
|
||||
void TBXR_InitRenderer();
|
||||
void TBXR_EnterVR();
|
||||
void TBXR_LeaveVR( );
|
||||
void TBXR_GetScreenRes(int *width, int *height);
|
||||
void TBXR_InitActions( void );
|
||||
void TBXR_Vibrate(int duration, int channel, float intensity );
|
||||
void TBXR_ProcessHaptics();
|
||||
void TBXR_FrameSetup();
|
||||
void TBXR_updateProjections();
|
||||
void TBXR_UpdateControllers( );
|
||||
void TBXR_prepareEyeBuffer(int eye );
|
||||
void TBXR_finishEyeBuffer(int eye );
|
||||
void TBXR_submitFrame();
|
||||
|
||||
#endif //vrcommon_h
|
|
@ -1,13 +1,25 @@
|
|||
#if !defined(vrcommon_h)
|
||||
#define vrcommon_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include "TBXR_Common.h"
|
||||
|
||||
#include "c_cvars.h"
|
||||
|
||||
EXTERN_CVAR(Int, vr_control_scheme)
|
||||
EXTERN_CVAR(Bool, vr_move_use_offhand)
|
||||
EXTERN_CVAR(Float, vr_weaponRotate);
|
||||
EXTERN_CVAR(Float, vr_snapTurn);
|
||||
EXTERN_CVAR(Float, vr_ipd);
|
||||
EXTERN_CVAR(Float, vr_weaponScale);
|
||||
EXTERN_CVAR(Bool, vr_teleport);
|
||||
EXTERN_CVAR(Bool, vr_switch_sticks);
|
||||
EXTERN_CVAR(Bool, vr_secondary_button_mappings);
|
||||
EXTERN_CVAR(Bool, vr_two_handed_weapons);
|
||||
EXTERN_CVAR(Bool, vr_crouch_use_button);
|
||||
EXTERN_CVAR(Float, vr_weaponOffsetX);
|
||||
EXTERN_CVAR(Float, vr_weaponOffsetY);
|
||||
EXTERN_CVAR(Float, vr_weaponOffsetZ);
|
||||
|
||||
//#include <VrApi_Ext.h>
|
||||
#include <VrApi_Input.h>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
|
@ -50,19 +62,6 @@ extern vec3_t positionDeltaThisFrame;
|
|||
extern vec3_t weaponangles;
|
||||
extern vec3_t weaponoffset;
|
||||
|
||||
extern bool weaponStabilised;
|
||||
extern float vr_weapon_pitchadjust;
|
||||
extern float vr_weapon_offset_x;
|
||||
extern float vr_weapon_offset_y;
|
||||
extern float vr_weapon_offset_z;
|
||||
extern bool vr_moveuseoffhand;
|
||||
extern bool vr_switchsticks;
|
||||
extern bool vr_secondarybuttonmappings;
|
||||
extern bool vr_twohandedweapons;
|
||||
extern float vr_snapturn_angle;
|
||||
extern float vr_use_teleport;
|
||||
|
||||
|
||||
extern vec3_t offhandangles;
|
||||
extern vec3_t offhandoffset;
|
||||
|
||||
|
@ -74,42 +73,17 @@ extern bool trigger_teleport;
|
|||
extern bool shutdown;
|
||||
void shutdownVR();
|
||||
|
||||
float radians(float deg);
|
||||
float degrees(float rad);
|
||||
bool isMultiplayer();
|
||||
double GetTimeInMilliSeconds();
|
||||
float length(float x, float y);
|
||||
float nonLinearFilter(float in);
|
||||
bool between(float min, float val, float max);
|
||||
void rotateAboutOrigin(float v1, float v2, float rotation, vec2_t out);
|
||||
void QuatToYawPitchRoll(ovrQuatf q, vec3_t rotation, vec3_t out);
|
||||
void handleTrackedControllerButton(ovrInputStateTrackedRemote * trackedRemoteState, ovrInputStateTrackedRemote * prevTrackedRemoteState, uint32_t button, int key);
|
||||
void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out);
|
||||
|
||||
//Called from engine code
|
||||
bool QzDoom_useScreenLayer();
|
||||
void QzDoom_GetScreenRes(uint32_t *width, uint32_t *height);
|
||||
void QzDoom_Vibrate(float duration, int channel, float intensity );
|
||||
void QzDoom_processMessageQueue();
|
||||
void QzDoom_FrameSetup();
|
||||
void QzDoom_setUseScreenLayer(bool use);
|
||||
void QzDoom_processHaptics();
|
||||
void QzDoom_getHMDOrientation(ovrTracking2 *tracking);
|
||||
void QzDoom_getTrackedRemotesOrientation(int vr_control_scheme);
|
||||
int QzDoom_SetRefreshRate(int refreshRate);
|
||||
void QzDoom_Restart();
|
||||
void jni_shutdown();
|
||||
|
||||
void QzDoom_HapticEvent(const char* event, int position, int intensity, float angle, float yHeight );
|
||||
void QzDoom_HapticEnable();
|
||||
void QzDoom_HapticDisable();
|
||||
|
||||
void incrementFrameIndex();
|
||||
|
||||
void QzDoom_prepareEyeBuffer(int eye );
|
||||
void QzDoom_finishEyeBuffer(int eye );
|
||||
void QzDoom_submitFrame(ovrTracking2 *tracking);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //vrcommon_h
|
|
@ -1,595 +0,0 @@
|
|||
/************************************************************************************
|
||||
|
||||
Filename : VrCompositor.c
|
||||
|
||||
*************************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/prctl.h> // for prctl( PR_SET_NAME )
|
||||
#include <android/log.h>
|
||||
#include <android/window.h> // for AWINDOW_FLAG_KEEP_SCREEN_ON
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES3/gl3ext.h>
|
||||
|
||||
|
||||
|
||||
#include <VrApi.h>
|
||||
#include <VrApi_Helpers.h>
|
||||
|
||||
#include "VrCompositor.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
renderState
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
|
||||
void getCurrentRenderState( renderState * state)
|
||||
{
|
||||
state->VertexBuffer = 0;
|
||||
state->IndexBuffer = 0;
|
||||
state->VertexArrayObject = 0;
|
||||
state->Program = 0;
|
||||
|
||||
glGetIntegerv(GL_ARRAY_BUFFER, &state->VertexBuffer );
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER, &state->IndexBuffer );
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &state->VertexArrayObject );
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &state->Program );
|
||||
}
|
||||
|
||||
void restoreRenderState( renderState * state )
|
||||
{
|
||||
GL( glUseProgram( state->Program ) );
|
||||
GL( glBindVertexArray( state->VertexArrayObject ) );
|
||||
GL( glBindBuffer( GL_ARRAY_BUFFER, state->VertexBuffer ) );
|
||||
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, state->IndexBuffer ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrGeometry
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
enum VertexAttributeLocation
|
||||
{
|
||||
VERTEX_ATTRIBUTE_LOCATION_POSITION,
|
||||
VERTEX_ATTRIBUTE_LOCATION_COLOR,
|
||||
VERTEX_ATTRIBUTE_LOCATION_UV,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
enum VertexAttributeLocation location;
|
||||
const char * name;
|
||||
} ovrVertexAttribute;
|
||||
|
||||
static ovrVertexAttribute ProgramVertexAttributes[] =
|
||||
{
|
||||
{ VERTEX_ATTRIBUTE_LOCATION_POSITION, "vertexPosition" },
|
||||
{ VERTEX_ATTRIBUTE_LOCATION_COLOR, "vertexColor" },
|
||||
{ VERTEX_ATTRIBUTE_LOCATION_UV, "vertexUv" },
|
||||
};
|
||||
|
||||
static void ovrGeometry_Clear( ovrGeometry * geometry )
|
||||
{
|
||||
geometry->VertexBuffer = 0;
|
||||
geometry->IndexBuffer = 0;
|
||||
geometry->VertexArrayObject = 0;
|
||||
geometry->VertexCount = 0;
|
||||
geometry->IndexCount = 0;
|
||||
for ( int i = 0; i < MAX_VERTEX_ATTRIB_POINTERS; i++ )
|
||||
{
|
||||
memset( &geometry->VertexAttribs[i], 0, sizeof( geometry->VertexAttribs[i] ) );
|
||||
geometry->VertexAttribs[i].Index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void ovrGeometry_CreateGroundPlane( ovrGeometry * geometry )
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
float positions[4][4];
|
||||
unsigned char colors[4][4];
|
||||
} ovrCubeVertices;
|
||||
|
||||
static const ovrCubeVertices cubeVertices =
|
||||
{
|
||||
// positions
|
||||
{
|
||||
{ 4.5f, -1.2f, 4.5f, 1.0f },
|
||||
{ 4.5f, -1.2f, -4.5f, 1.0f },
|
||||
{ -4.5f, -1.2f, -4.5f, 1.0f },
|
||||
{ -4.5f, -1.2f, 4.5f, 1.0f }
|
||||
},
|
||||
// colors
|
||||
{
|
||||
{ 255, 0, 0, 255 },
|
||||
{ 0, 255, 0, 255 },
|
||||
{ 0, 0, 255, 255 },
|
||||
{ 255, 255, 0, 255 },
|
||||
},
|
||||
};
|
||||
|
||||
static const unsigned short cubeIndices[6] =
|
||||
{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
};
|
||||
|
||||
geometry->VertexCount = 4;
|
||||
geometry->IndexCount = 6;
|
||||
|
||||
geometry->VertexAttribs[0].Index = VERTEX_ATTRIBUTE_LOCATION_POSITION;
|
||||
geometry->VertexAttribs[0].Size = 4;
|
||||
geometry->VertexAttribs[0].Type = GL_FLOAT;
|
||||
geometry->VertexAttribs[0].Normalized = false;
|
||||
geometry->VertexAttribs[0].Stride = sizeof( cubeVertices.positions[0] );
|
||||
geometry->VertexAttribs[0].Pointer = (const GLvoid *)offsetof( ovrCubeVertices, positions );
|
||||
|
||||
geometry->VertexAttribs[1].Index = VERTEX_ATTRIBUTE_LOCATION_COLOR;
|
||||
geometry->VertexAttribs[1].Size = 4;
|
||||
geometry->VertexAttribs[1].Type = GL_UNSIGNED_BYTE;
|
||||
geometry->VertexAttribs[1].Normalized = true;
|
||||
geometry->VertexAttribs[1].Stride = sizeof( cubeVertices.colors[0] );
|
||||
geometry->VertexAttribs[1].Pointer = (const GLvoid *)offsetof( ovrCubeVertices, colors );
|
||||
|
||||
renderState state;
|
||||
getCurrentRenderState(&state);
|
||||
|
||||
GL( glGenBuffers( 1, &geometry->VertexBuffer ) );
|
||||
GL( glBindBuffer( GL_ARRAY_BUFFER, geometry->VertexBuffer ) );
|
||||
GL( glBufferData( GL_ARRAY_BUFFER, sizeof( cubeVertices ), &cubeVertices, GL_STATIC_DRAW ) );
|
||||
|
||||
GL( glGenBuffers( 1, &geometry->IndexBuffer ) );
|
||||
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, geometry->IndexBuffer ) );
|
||||
GL( glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( cubeIndices ), cubeIndices, GL_STATIC_DRAW ) );
|
||||
|
||||
restoreRenderState(&state);
|
||||
}
|
||||
|
||||
static void ovrGeometry_Destroy( ovrGeometry * geometry )
|
||||
{
|
||||
GL( glDeleteBuffers( 1, &geometry->IndexBuffer ) );
|
||||
GL( glDeleteBuffers( 1, &geometry->VertexBuffer ) );
|
||||
|
||||
ovrGeometry_Clear( geometry );
|
||||
}
|
||||
|
||||
static void ovrGeometry_CreateVAO( ovrGeometry * geometry )
|
||||
{
|
||||
renderState state;
|
||||
getCurrentRenderState(&state);
|
||||
|
||||
GL( glGenVertexArrays( 1, &geometry->VertexArrayObject ) );
|
||||
GL( glBindVertexArray( geometry->VertexArrayObject ) );
|
||||
|
||||
GL( glBindBuffer( GL_ARRAY_BUFFER, geometry->VertexBuffer ) );
|
||||
|
||||
for ( int i = 0; i < MAX_VERTEX_ATTRIB_POINTERS; i++ )
|
||||
{
|
||||
if ( geometry->VertexAttribs[i].Index != -1 )
|
||||
{
|
||||
GL( glEnableVertexAttribArray( geometry->VertexAttribs[i].Index ) );
|
||||
GL( glVertexAttribPointer( geometry->VertexAttribs[i].Index, geometry->VertexAttribs[i].Size,
|
||||
geometry->VertexAttribs[i].Type, geometry->VertexAttribs[i].Normalized,
|
||||
geometry->VertexAttribs[i].Stride, geometry->VertexAttribs[i].Pointer ) );
|
||||
}
|
||||
}
|
||||
|
||||
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, geometry->IndexBuffer ) );
|
||||
|
||||
restoreRenderState(&state);
|
||||
}
|
||||
|
||||
static void ovrGeometry_DestroyVAO( ovrGeometry * geometry )
|
||||
{
|
||||
GL( glDeleteVertexArrays( 1, &geometry->VertexArrayObject ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrProgram
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
enum
|
||||
{
|
||||
UNIFORM_VIEW_PROJ_MATRIX,
|
||||
} index;
|
||||
enum
|
||||
{
|
||||
UNIFORM_TYPE_VECTOR4,
|
||||
UNIFORM_TYPE_MATRIX4X4,
|
||||
UNIFORM_TYPE_INT,
|
||||
UNIFORM_TYPE_BUFFER,
|
||||
} type;
|
||||
const char * name;
|
||||
} ovrUniform;
|
||||
|
||||
static ovrUniform ProgramUniforms[] =
|
||||
{
|
||||
{ UNIFORM_VIEW_PROJ_MATRIX, UNIFORM_TYPE_MATRIX4X4, "viewProjectionMatrix" },
|
||||
};
|
||||
|
||||
static void ovrProgram_Clear( ovrProgram * program )
|
||||
{
|
||||
program->Program = 0;
|
||||
program->VertexShader = 0;
|
||||
program->FragmentShader = 0;
|
||||
memset( program->UniformLocation, 0, sizeof( program->UniformLocation ) );
|
||||
memset( program->UniformBinding, 0, sizeof( program->UniformBinding ) );
|
||||
memset( program->Textures, 0, sizeof( program->Textures ) );
|
||||
}
|
||||
|
||||
static bool ovrProgram_Create( ovrProgram * program, const char * vertexSource, const char * fragmentSource )
|
||||
{
|
||||
GLint r;
|
||||
|
||||
GL( program->VertexShader = glCreateShader( GL_VERTEX_SHADER ) );
|
||||
|
||||
GL( glShaderSource( program->VertexShader, 1, &vertexSource, 0 ) );
|
||||
GL( glCompileShader( program->VertexShader ) );
|
||||
GL( glGetShaderiv( program->VertexShader, GL_COMPILE_STATUS, &r ) );
|
||||
if ( r == GL_FALSE )
|
||||
{
|
||||
GLchar msg[4096];
|
||||
GL( glGetShaderInfoLog( program->VertexShader, sizeof( msg ), 0, msg ) );
|
||||
ALOGE( "%s\n%s\n", vertexSource, msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
GL( program->FragmentShader = glCreateShader( GL_FRAGMENT_SHADER ) );
|
||||
GL( glShaderSource( program->FragmentShader, 1, &fragmentSource, 0 ) );
|
||||
GL( glCompileShader( program->FragmentShader ) );
|
||||
GL( glGetShaderiv( program->FragmentShader, GL_COMPILE_STATUS, &r ) );
|
||||
if ( r == GL_FALSE )
|
||||
{
|
||||
GLchar msg[4096];
|
||||
GL( glGetShaderInfoLog( program->FragmentShader, sizeof( msg ), 0, msg ) );
|
||||
ALOGE( "%s\n%s\n", fragmentSource, msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
GL( program->Program = glCreateProgram() );
|
||||
GL( glAttachShader( program->Program, program->VertexShader ) );
|
||||
GL( glAttachShader( program->Program, program->FragmentShader ) );
|
||||
|
||||
// Bind the vertex attribute locations.
|
||||
for ( int i = 0; i < sizeof( ProgramVertexAttributes ) / sizeof( ProgramVertexAttributes[0] ); i++ )
|
||||
{
|
||||
GL( glBindAttribLocation( program->Program, ProgramVertexAttributes[i].location, ProgramVertexAttributes[i].name ) );
|
||||
}
|
||||
|
||||
GL( glLinkProgram( program->Program ) );
|
||||
GL( glGetProgramiv( program->Program, GL_LINK_STATUS, &r ) );
|
||||
if ( r == GL_FALSE )
|
||||
{
|
||||
GLchar msg[4096];
|
||||
GL( glGetProgramInfoLog( program->Program, sizeof( msg ), 0, msg ) );
|
||||
ALOGE( "Linking program failed: %s\n", msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
int numBufferBindings = 0;
|
||||
|
||||
// Get the uniform locations.
|
||||
memset( program->UniformLocation, -1, sizeof( program->UniformLocation ) );
|
||||
for ( int i = 0; i < sizeof( ProgramUniforms ) / sizeof( ProgramUniforms[0] ); i++ )
|
||||
{
|
||||
const int uniformIndex = ProgramUniforms[i].index;
|
||||
if ( ProgramUniforms[i].type == UNIFORM_TYPE_BUFFER )
|
||||
{
|
||||
GL( program->UniformLocation[uniformIndex] = glGetUniformBlockIndex( program->Program, ProgramUniforms[i].name ) );
|
||||
program->UniformBinding[uniformIndex] = numBufferBindings++;
|
||||
GL( glUniformBlockBinding( program->Program, program->UniformLocation[uniformIndex], program->UniformBinding[uniformIndex] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
GL( program->UniformLocation[uniformIndex] = glGetUniformLocation( program->Program, ProgramUniforms[i].name ) );
|
||||
program->UniformBinding[uniformIndex] = program->UniformLocation[uniformIndex];
|
||||
}
|
||||
}
|
||||
|
||||
renderState state;
|
||||
getCurrentRenderState(&state);
|
||||
|
||||
GL( glUseProgram( program->Program ) );
|
||||
|
||||
// Get the texture locations.
|
||||
for ( int i = 0; i < MAX_PROGRAM_TEXTURES; i++ )
|
||||
{
|
||||
char name[32];
|
||||
sprintf( name, "Texture%i", i );
|
||||
program->Textures[i] = glGetUniformLocation( program->Program, name );
|
||||
if ( program->Textures[i] != -1 )
|
||||
{
|
||||
GL( glUniform1i( program->Textures[i], i ) );
|
||||
}
|
||||
}
|
||||
|
||||
restoreRenderState(&state);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ovrProgram_Destroy( ovrProgram * program )
|
||||
{
|
||||
if ( program->Program != 0 )
|
||||
{
|
||||
GL( glDeleteProgram( program->Program ) );
|
||||
program->Program = 0;
|
||||
}
|
||||
if ( program->VertexShader != 0 )
|
||||
{
|
||||
GL( glDeleteShader( program->VertexShader ) );
|
||||
program->VertexShader = 0;
|
||||
}
|
||||
if ( program->FragmentShader != 0 )
|
||||
{
|
||||
GL( glDeleteShader( program->FragmentShader ) );
|
||||
program->FragmentShader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const char VERTEX_SHADER[] =
|
||||
"#version 300 es\n"
|
||||
"in vec3 vertexPosition;\n"
|
||||
"in vec4 vertexColor;\n"
|
||||
"uniform mat4 viewProjectionMatrix;\n"
|
||||
"out vec4 fragmentColor;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = viewProjectionMatrix * vec4( vertexPosition, 1.0 );\n"
|
||||
" fragmentColor = vertexColor;\n"
|
||||
"}\n";
|
||||
|
||||
static const char FRAGMENT_SHADER[] =
|
||||
"#version 300 es\n"
|
||||
"in lowp vec4 fragmentColor;\n"
|
||||
"out lowp vec4 outColor;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" outColor = fragmentColor;\n"
|
||||
"}\n";
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrScene
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
void ovrScene_Clear( ovrScene * scene )
|
||||
{
|
||||
scene->CreatedScene = false;
|
||||
scene->CreatedVAOs = false;
|
||||
ovrProgram_Clear( &scene->Program );
|
||||
ovrGeometry_Clear( &scene->GroundPlane );
|
||||
ovrRenderer_Clear( &scene->CylinderRenderer );
|
||||
|
||||
scene->CylinderWidth = 0;
|
||||
scene->CylinderHeight = 0;
|
||||
}
|
||||
|
||||
bool ovrScene_IsCreated( ovrScene * scene )
|
||||
{
|
||||
return scene->CreatedScene;
|
||||
}
|
||||
|
||||
void ovrScene_CreateVAOs( ovrScene * scene )
|
||||
{
|
||||
if ( !scene->CreatedVAOs )
|
||||
{
|
||||
ovrGeometry_CreateVAO( &scene->GroundPlane );
|
||||
scene->CreatedVAOs = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ovrScene_DestroyVAOs( ovrScene * scene )
|
||||
{
|
||||
if ( scene->CreatedVAOs )
|
||||
{
|
||||
ovrGeometry_DestroyVAO( &scene->GroundPlane );
|
||||
scene->CreatedVAOs = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ovrScene_Create( int width, int height, ovrScene * scene, const ovrJava * java )
|
||||
{
|
||||
// Simple ground plane geometry.
|
||||
{
|
||||
ovrProgram_Create( &scene->Program, VERTEX_SHADER, FRAGMENT_SHADER );
|
||||
ovrGeometry_CreateGroundPlane( &scene->GroundPlane );
|
||||
ovrScene_CreateVAOs( scene );
|
||||
}
|
||||
|
||||
// Create Cylinder renderer
|
||||
{
|
||||
scene->CylinderWidth = width;
|
||||
scene->CylinderHeight = height;
|
||||
|
||||
//Create cylinder renderer
|
||||
ovrRenderer_Create( width, height, &scene->CylinderRenderer, java );
|
||||
}
|
||||
|
||||
scene->CreatedScene = true;
|
||||
}
|
||||
|
||||
void ovrScene_Destroy( ovrScene * scene )
|
||||
{
|
||||
ovrScene_DestroyVAOs( scene );
|
||||
ovrProgram_Destroy( &scene->Program );
|
||||
ovrGeometry_Destroy( &scene->GroundPlane );
|
||||
ovrRenderer_Destroy( &scene->CylinderRenderer );
|
||||
|
||||
scene->CreatedScene = false;
|
||||
}
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrRenderer
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
ovrLayerProjection2 ovrRenderer_RenderGroundPlaneToEyeBuffer( ovrRenderer * renderer, const ovrJava * java,
|
||||
const ovrScene * scene, const ovrTracking2 * tracking )
|
||||
{
|
||||
ovrLayerProjection2 layer = vrapi_DefaultLayerProjection2();
|
||||
layer.HeadPose = tracking->HeadPose;
|
||||
for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ )
|
||||
{
|
||||
ovrFramebuffer * frameBuffer = &renderer->FrameBuffer[eye];
|
||||
layer.Textures[eye].ColorSwapChain = frameBuffer->ColorTextureSwapChain;
|
||||
layer.Textures[eye].SwapChainIndex = frameBuffer->ProcessingTextureSwapChainIndex;
|
||||
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection( &tracking->Eye[eye].ProjectionMatrix );
|
||||
}
|
||||
layer.Header.Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION;
|
||||
|
||||
for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ )
|
||||
{
|
||||
ovrFramebuffer * frameBuffer = &renderer->FrameBuffer[eye];
|
||||
ovrFramebuffer_SetCurrent( frameBuffer );
|
||||
|
||||
renderState state;
|
||||
getCurrentRenderState(&state);
|
||||
|
||||
GL( glUseProgram( scene->Program.Program ) );
|
||||
|
||||
ovrMatrix4f viewProjMatrix = ovrMatrix4f_Multiply( &tracking->Eye[eye].ProjectionMatrix, &tracking->Eye[eye].ViewMatrix );
|
||||
glUniformMatrix4fv( scene->Program.UniformLocation[UNIFORM_VIEW_PROJ_MATRIX], 1, GL_TRUE, &viewProjMatrix.M[0][0] );
|
||||
|
||||
GL( glEnable( GL_SCISSOR_TEST ) );
|
||||
GL( glDepthMask( GL_TRUE ) );
|
||||
GL( glEnable( GL_DEPTH_TEST ) );
|
||||
GL( glDepthFunc( GL_LEQUAL ) );
|
||||
GL( glEnable( GL_CULL_FACE ) );
|
||||
GL( glCullFace( GL_BACK ) );
|
||||
GL( glViewport( 0, 0, frameBuffer->Width, frameBuffer->Height ) );
|
||||
GL( glScissor( 0, 0, frameBuffer->Width, frameBuffer->Height ) );
|
||||
GL( glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ) );
|
||||
GL( glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) );
|
||||
|
||||
//bind buffers
|
||||
GL( glBindBuffer( GL_ARRAY_BUFFER, scene->GroundPlane.VertexBuffer ) );
|
||||
GL( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, scene->GroundPlane.IndexBuffer ) );
|
||||
GL( glBindVertexArray( scene->GroundPlane.VertexArrayObject ) );
|
||||
|
||||
GL( glDrawElements( GL_TRIANGLES, scene->GroundPlane.IndexCount, GL_UNSIGNED_SHORT, NULL ) );
|
||||
|
||||
restoreRenderState(&state);
|
||||
|
||||
// Explicitly clear the border texels to black when GL_CLAMP_TO_BORDER is not available.
|
||||
ovrFramebuffer_ClearEdgeTexels( frameBuffer );
|
||||
|
||||
ovrFramebuffer_Resolve( frameBuffer );
|
||||
ovrFramebuffer_Advance( frameBuffer );
|
||||
}
|
||||
|
||||
ovrFramebuffer_SetNone();
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
// Assumes landscape cylinder shape.
|
||||
static ovrMatrix4f CylinderModelMatrix( const int texWidth, const int texHeight,
|
||||
const ovrVector3f translation,
|
||||
const float rotateYaw,
|
||||
const float rotatePitch,
|
||||
const float radius,
|
||||
const float density )
|
||||
{
|
||||
const ovrMatrix4f scaleMatrix = ovrMatrix4f_CreateScale( radius, radius * (float)texHeight * VRAPI_PI / density, radius );
|
||||
const ovrMatrix4f transMatrix = ovrMatrix4f_CreateTranslation( translation.x, translation.y, translation.z );
|
||||
const ovrMatrix4f rotXMatrix = ovrMatrix4f_CreateRotation( rotateYaw, 0.0f, 0.0f );
|
||||
const ovrMatrix4f rotYMatrix = ovrMatrix4f_CreateRotation( 0.0f, rotatePitch, 0.0f );
|
||||
|
||||
const ovrMatrix4f m0 = ovrMatrix4f_Multiply( &transMatrix, &scaleMatrix );
|
||||
const ovrMatrix4f m1 = ovrMatrix4f_Multiply( &rotXMatrix, &m0 );
|
||||
const ovrMatrix4f m2 = ovrMatrix4f_Multiply( &rotYMatrix, &m1 );
|
||||
|
||||
return m2;
|
||||
}
|
||||
|
||||
ovrLayerCylinder2 BuildCylinderLayer( ovrRenderer * cylinderRenderer,
|
||||
const int textureWidth, const int textureHeight,
|
||||
const ovrTracking2 * tracking, float rotatePitch )
|
||||
{
|
||||
ovrLayerCylinder2 layer = vrapi_DefaultLayerCylinder2();
|
||||
|
||||
const float fadeLevel = 1.0f;
|
||||
layer.Header.ColorScale.x =
|
||||
layer.Header.ColorScale.y =
|
||||
layer.Header.ColorScale.z =
|
||||
layer.Header.ColorScale.w = fadeLevel;
|
||||
layer.Header.SrcBlend = VRAPI_FRAME_LAYER_BLEND_SRC_ALPHA;
|
||||
layer.Header.DstBlend = VRAPI_FRAME_LAYER_BLEND_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
//layer.Header.Flags = VRAPI_FRAME_LAYER_FLAG_CLIP_TO_TEXTURE_RECT;
|
||||
|
||||
layer.HeadPose = tracking->HeadPose;
|
||||
|
||||
const float density = 4500.0f;
|
||||
const float rotateYaw = 0.0f;
|
||||
const float radius = 4.0f;
|
||||
const ovrVector3f translation = { 0.0f, 0.0f, -2.5f };
|
||||
|
||||
ovrMatrix4f cylinderTransform =
|
||||
CylinderModelMatrix( textureWidth, textureHeight, translation,
|
||||
rotateYaw, rotatePitch, radius, density );
|
||||
|
||||
const float circScale = density * 0.5f / textureWidth;
|
||||
const float circBias = -circScale * ( 0.5f * ( 1.0f - 1.0f / circScale ) );
|
||||
|
||||
for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ )
|
||||
{
|
||||
ovrFramebuffer * cylinderFrameBuffer = &cylinderRenderer->FrameBuffer[eye];
|
||||
|
||||
ovrMatrix4f modelViewMatrix = ovrMatrix4f_Multiply( &tracking->Eye[eye].ViewMatrix, &cylinderTransform );
|
||||
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_Inverse( &modelViewMatrix );
|
||||
layer.Textures[eye].ColorSwapChain = cylinderFrameBuffer->ColorTextureSwapChain;
|
||||
layer.Textures[eye].SwapChainIndex = cylinderFrameBuffer->ReadyTextureSwapChainIndex;
|
||||
|
||||
// Texcoord scale and bias is just a representation of the aspect ratio. The positioning
|
||||
// of the cylinder is handled entirely by the TexCoordsFromTanAngles matrix.
|
||||
|
||||
const float texScaleX = circScale;
|
||||
const float texBiasX = circBias;
|
||||
const float texScaleY = -0.5f;
|
||||
const float texBiasY = texScaleY * ( 0.5f * ( 1.0f - ( 1.0f / texScaleY ) ) );
|
||||
|
||||
layer.Textures[eye].TextureMatrix.M[0][0] = texScaleX;
|
||||
layer.Textures[eye].TextureMatrix.M[0][2] = texBiasX;
|
||||
layer.Textures[eye].TextureMatrix.M[1][1] = texScaleY;
|
||||
layer.Textures[eye].TextureMatrix.M[1][2] = -texBiasY;
|
||||
|
||||
layer.Textures[eye].TextureRect.width = 1.0f;
|
||||
layer.Textures[eye].TextureRect.height = 1.0f;
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
|
@ -1,217 +0,0 @@
|
|||
/************************************************************************************
|
||||
|
||||
Filename : VrCompositor.h
|
||||
|
||||
*************************************************************************************/
|
||||
|
||||
#include "VrInput.h"
|
||||
|
||||
#define CHECK_GL_ERRORS
|
||||
#ifdef CHECK_GL_ERRORS
|
||||
|
||||
static const char * GlErrorString( GLenum error )
|
||||
{
|
||||
switch ( error )
|
||||
{
|
||||
case GL_NO_ERROR: return "GL_NO_ERROR";
|
||||
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
||||
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
||||
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void GLCheckErrors( int line )
|
||||
{
|
||||
for ( int i = 0; i < 10; i++ )
|
||||
{
|
||||
const GLenum error = glGetError();
|
||||
if ( error == GL_NO_ERROR )
|
||||
{
|
||||
break;
|
||||
}
|
||||
ALOGE( "GL error on line %d: %s", line, GlErrorString( error ) );
|
||||
}
|
||||
}
|
||||
|
||||
#define GL( func ) func; GLCheckErrors( __LINE__ );
|
||||
|
||||
#else // CHECK_GL_ERRORS
|
||||
|
||||
#define GL( func ) func;
|
||||
|
||||
#endif // CHECK_GL_ERRORS
|
||||
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrFramebuffer
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Width;
|
||||
int Height;
|
||||
int Multisamples;
|
||||
int TextureSwapChainLength;
|
||||
int ProcessingTextureSwapChainIndex;
|
||||
int ReadyTextureSwapChainIndex;
|
||||
ovrTextureSwapChain * ColorTextureSwapChain;
|
||||
GLuint * DepthBuffers;
|
||||
GLuint * FrameBuffers;
|
||||
} ovrFramebuffer;
|
||||
|
||||
void ovrFramebuffer_SetCurrent( ovrFramebuffer * frameBuffer );
|
||||
void ovrFramebuffer_Destroy( ovrFramebuffer * frameBuffer );
|
||||
void ovrFramebuffer_SetNone();
|
||||
void ovrFramebuffer_Resolve( ovrFramebuffer * frameBuffer );
|
||||
void ovrFramebuffer_Advance( ovrFramebuffer * frameBuffer );
|
||||
void ovrFramebuffer_ClearEdgeTexels( ovrFramebuffer * frameBuffer );
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrRenderer
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ovrFramebuffer FrameBuffer[VRAPI_FRAME_LAYER_EYE_MAX];
|
||||
int NumBuffers;
|
||||
} ovrRenderer;
|
||||
|
||||
|
||||
void ovrRenderer_Clear( ovrRenderer * renderer );
|
||||
void ovrRenderer_Create( int width, int height, ovrRenderer * renderer, const ovrJava * java );
|
||||
void ovrRenderer_Destroy( ovrRenderer * renderer );
|
||||
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
renderState
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLint VertexBuffer;
|
||||
GLint IndexBuffer;
|
||||
GLint VertexArrayObject;
|
||||
GLint Program;
|
||||
GLint VertexShader;
|
||||
GLint FragmentShader;
|
||||
} renderState;
|
||||
|
||||
void getCurrentRenderState( renderState * state);
|
||||
void restoreRenderState( renderState * state );
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrGeometry
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLint Index;
|
||||
GLint Size;
|
||||
GLenum Type;
|
||||
GLboolean Normalized;
|
||||
GLsizei Stride;
|
||||
const GLvoid * Pointer;
|
||||
} ovrVertexAttribPointer;
|
||||
|
||||
#define MAX_VERTEX_ATTRIB_POINTERS 3
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLuint VertexBuffer;
|
||||
GLuint IndexBuffer;
|
||||
GLuint VertexArrayObject;
|
||||
int VertexCount;
|
||||
int IndexCount;
|
||||
ovrVertexAttribPointer VertexAttribs[MAX_VERTEX_ATTRIB_POINTERS];
|
||||
} ovrGeometry;
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrProgram
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
#define MAX_PROGRAM_UNIFORMS 8
|
||||
#define MAX_PROGRAM_TEXTURES 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLuint Program;
|
||||
GLuint VertexShader;
|
||||
GLuint FragmentShader;
|
||||
// These will be -1 if not used by the program.
|
||||
GLint UniformLocation[MAX_PROGRAM_UNIFORMS]; // ProgramUniforms[].name
|
||||
GLint UniformBinding[MAX_PROGRAM_UNIFORMS]; // ProgramUniforms[].name
|
||||
GLint Textures[MAX_PROGRAM_TEXTURES]; // Texture%i
|
||||
} ovrProgram;
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrScene
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool CreatedScene;
|
||||
bool CreatedVAOs;
|
||||
ovrProgram Program;
|
||||
ovrGeometry GroundPlane;
|
||||
|
||||
//Proper renderer for stereo rendering to the cylinder layer
|
||||
ovrRenderer CylinderRenderer;
|
||||
|
||||
int CylinderWidth;
|
||||
int CylinderHeight;
|
||||
} ovrScene;
|
||||
|
||||
bool ovrScene_IsCreated( ovrScene * scene );
|
||||
void ovrScene_Clear( ovrScene * scene );
|
||||
void ovrScene_Create( int width, int height, ovrScene * scene, const ovrJava * java );
|
||||
void ovrScene_CreateVAOs( ovrScene * scene );
|
||||
void ovrScene_DestroyVAOs( ovrScene * scene );
|
||||
void ovrScene_Destroy( ovrScene * scene );
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
ovrRenderer
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
ovrLayerProjection2 ovrRenderer_RenderGroundPlaneToEyeBuffer( ovrRenderer * renderer, const ovrJava * java,
|
||||
const ovrScene * scene, const ovrTracking2 * tracking );
|
||||
|
||||
ovrLayerProjection2 ovrRenderer_RenderToEyeBuffer( ovrRenderer * renderer, const ovrJava * java,
|
||||
const ovrTracking2 * tracking );
|
||||
|
||||
ovrLayerCylinder2 BuildCylinderLayer( ovrRenderer * cylinderRenderer,
|
||||
const int textureWidth, const int textureHeight,
|
||||
const ovrTracking2 * tracking, float rotateYaw );
|
||||
;
|
||||
|
||||
|
|
@ -5,12 +5,25 @@
|
|||
#include "VrCommon.h"
|
||||
|
||||
|
||||
extern ovrInputStateTrackedRemote leftTrackedRemoteState_old;
|
||||
extern ovrInputStateTrackedRemote leftTrackedRemoteState_new;
|
||||
extern ovrTrackedController leftRemoteTracking_new;
|
||||
|
||||
void acquireTrackedRemotesData(const ovrMobile *Ovr, double displayTime);
|
||||
extern ovrInputStateTrackedRemote rightTrackedRemoteState_old;
|
||||
extern ovrInputStateTrackedRemote rightTrackedRemoteState_new;
|
||||
extern ovrTrackedController rightRemoteTracking_new;
|
||||
|
||||
void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackingNew, ovrInputStateGamepad *pFootTrackingOld, ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
|
||||
ovrInputStateTrackedRemote *pDominantTrackedRemoteOld, ovrTracking* pDominantTracking,
|
||||
ovrInputStateTrackedRemote *pOffTrackedRemoteNew, ovrInputStateTrackedRemote *pOffTrackedRemoteOld, ovrTracking* pOffTracking,
|
||||
extern float remote_movementSideways;
|
||||
extern float remote_movementForward;
|
||||
extern float remote_movementUp;
|
||||
extern float positional_movementSideways;
|
||||
extern float positional_movementForward;
|
||||
extern float snapTurn;
|
||||
|
||||
|
||||
void HandleInput_Default( int control_scheme, ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
|
||||
ovrInputStateTrackedRemote *pDominantTrackedRemoteOld, ovrTrackedController* pDominantTracking,
|
||||
ovrInputStateTrackedRemote *pOffTrackedRemoteNew, ovrInputStateTrackedRemote *pOffTrackedRemoteOld, ovrTrackedController* pOffTracking,
|
||||
int domButton1, int domButton2, int offButton1, int offButton2 );
|
||||
|
||||
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
/************************************************************************************
|
||||
|
||||
Filename : VrInputRight.c
|
||||
Content : Handles common controller input functionality
|
||||
Created : September 2019
|
||||
Authors : Simon Brown
|
||||
|
||||
*************************************************************************************/
|
||||
|
||||
#include <VrApi.h>
|
||||
#include <VrApi_Helpers.h>
|
||||
#include <VrApi_SystemUtils.h>
|
||||
#include <VrApi_Input.h>
|
||||
#include <VrApi_Types.h>
|
||||
|
||||
#include "VrInput.h"
|
||||
|
||||
ovrInputStateTrackedRemote leftTrackedRemoteState_old;
|
||||
ovrInputStateTrackedRemote leftTrackedRemoteState_new;
|
||||
ovrTracking leftRemoteTracking_new;
|
||||
|
||||
ovrInputStateTrackedRemote rightTrackedRemoteState_old;
|
||||
ovrInputStateTrackedRemote rightTrackedRemoteState_new;
|
||||
ovrTracking rightRemoteTracking_new;
|
||||
|
||||
ovrInputStateGamepad footTrackedRemoteState_old;
|
||||
ovrInputStateGamepad footTrackedRemoteState_new;
|
||||
|
||||
|
||||
ovrDeviceID controllerIDs[2];
|
||||
|
||||
float remote_movementSideways;
|
||||
float remote_movementForward;
|
||||
float remote_movementUp;
|
||||
float positional_movementSideways;
|
||||
float positional_movementForward;
|
||||
float snapTurn;
|
||||
|
||||
float cinemamodeYaw;
|
||||
float cinemamodePitch;
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
|
||||
|
||||
void handleTrackedControllerButton(ovrInputStateTrackedRemote * trackedRemoteState, ovrInputStateTrackedRemote * prevTrackedRemoteState, uint32_t button, int key)
|
||||
{
|
||||
Joy_GenerateButtonEvents(prevTrackedRemoteState->Buttons & button ? 1 : 0, trackedRemoteState->Buttons & button ? 1 : 0, 1, key);
|
||||
}
|
||||
|
||||
static void Matrix4x4_Transform (const matrix4x4 *in, const float v[3], float out[3])
|
||||
{
|
||||
out[0] = v[0] * (*in)[0][0] + v[1] * (*in)[0][1] + v[2] * (*in)[0][2] + (*in)[0][3];
|
||||
out[1] = v[0] * (*in)[1][0] + v[1] * (*in)[1][1] + v[2] * (*in)[1][2] + (*in)[1][3];
|
||||
out[2] = v[0] * (*in)[2][0] + v[1] * (*in)[2][1] + v[2] * (*in)[2][2] + (*in)[2][3];
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale );
|
||||
|
||||
void rotateAboutOrigin(float v1, float v2, float rotation, vec2_t out)
|
||||
{
|
||||
vec3_t temp = {0.0f, 0.0f, 0.0f};
|
||||
temp[0] = v1;
|
||||
temp[1] = v2;
|
||||
|
||||
vec3_t v = {0.0f, 0.0f, 0.0f};
|
||||
matrix4x4 matrix;
|
||||
vec3_t angles = {0.0f, rotation, 0.0f};
|
||||
vec3_t origin = {0.0f, 0.0f, 0.0f};
|
||||
Matrix4x4_CreateFromEntity(matrix, angles, origin, 1.0f);
|
||||
Matrix4x4_Transform(&matrix, temp, v);
|
||||
|
||||
out[0] = v[0];
|
||||
out[1] = v[1];
|
||||
}
|
||||
|
||||
float length(float x, float y)
|
||||
{
|
||||
return sqrtf(powf(x, 2.0f) + powf(y, 2.0f));
|
||||
}
|
||||
|
||||
#define NLF_DEADZONE 0.1
|
||||
#define NLF_POWER 2.2
|
||||
|
||||
float nonLinearFilter(float in)
|
||||
{
|
||||
float val = 0.0f;
|
||||
if (in > NLF_DEADZONE)
|
||||
{
|
||||
val = in;
|
||||
val -= NLF_DEADZONE;
|
||||
val /= (1.0f - NLF_DEADZONE);
|
||||
val = powf(val, NLF_POWER);
|
||||
}
|
||||
else if (in < -NLF_DEADZONE)
|
||||
{
|
||||
val = in;
|
||||
val += NLF_DEADZONE;
|
||||
val /= (1.0f - NLF_DEADZONE);
|
||||
val = -powf(fabsf(val), NLF_POWER);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool between(float min, float val, float max)
|
||||
{
|
||||
return (min < val) && (val < max);
|
||||
}
|
||||
|
||||
void acquireTrackedRemotesData(const ovrMobile *Ovr, double displayTime) {//The amount of yaw changed by controller
|
||||
for ( int i = 0; ; i++ ) {
|
||||
ovrInputCapabilityHeader capsHeader;
|
||||
ovrResult result = vrapi_EnumerateInputDevices(Ovr, i, &capsHeader);
|
||||
if (result < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (capsHeader.Type == ovrControllerType_Gamepad) {
|
||||
|
||||
ovrInputGamepadCapabilities remoteCaps;
|
||||
remoteCaps.Header = capsHeader;
|
||||
if (vrapi_GetInputDeviceCapabilities(Ovr, &remoteCaps.Header) >= 0) {
|
||||
// remote is connected
|
||||
ovrInputStateGamepad remoteState;
|
||||
remoteState.Header.ControllerType = ovrControllerType_Gamepad;
|
||||
if ( vrapi_GetCurrentInputState( Ovr, capsHeader.DeviceID, &remoteState.Header ) >= 0 )
|
||||
{
|
||||
// act on device state returned in remoteState
|
||||
footTrackedRemoteState_new = remoteState;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (capsHeader.Type == ovrControllerType_TrackedRemote) {
|
||||
ovrTracking remoteTracking;
|
||||
ovrInputTrackedRemoteCapabilities remoteCaps;
|
||||
remoteCaps.Header = capsHeader;
|
||||
if ( vrapi_GetInputDeviceCapabilities( Ovr, &remoteCaps.Header ) >= 0 )
|
||||
{
|
||||
// remote is connected
|
||||
ovrInputStateTrackedRemote remoteState;
|
||||
remoteState.Header.ControllerType = ovrControllerType_TrackedRemote;
|
||||
|
||||
if(vrapi_GetCurrentInputState(Ovr, capsHeader.DeviceID, &remoteState.Header) >= 0) {
|
||||
if (vrapi_GetInputTrackingState(Ovr, capsHeader.DeviceID, displayTime,
|
||||
&remoteTracking) >= 0) {
|
||||
// act on device state returned in remoteState
|
||||
if (remoteCaps.ControllerCapabilities & ovrControllerCaps_RightHand) {
|
||||
rightTrackedRemoteState_new = remoteState;
|
||||
rightRemoteTracking_new = remoteTracking;
|
||||
controllerIDs[1] = capsHeader.DeviceID;
|
||||
} else {
|
||||
leftTrackedRemoteState_new = remoteState;
|
||||
leftRemoteTracking_new = remoteTracking;
|
||||
controllerIDs[0] = capsHeader.DeviceID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
98
Projects/Android/jni/QzDoom/VrInputCommon.cpp
Normal file
98
Projects/Android/jni/QzDoom/VrInputCommon.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
/************************************************************************************
|
||||
|
||||
Filename : VrInputRight.c
|
||||
Content : Handles common controller input functionality
|
||||
Created : September 2019
|
||||
Authors : Simon Brown
|
||||
|
||||
*************************************************************************************/
|
||||
|
||||
|
||||
#include "VrInput.h"
|
||||
|
||||
ovrInputStateTrackedRemote leftTrackedRemoteState_old;
|
||||
ovrInputStateTrackedRemote leftTrackedRemoteState_new;
|
||||
ovrTrackedController leftRemoteTracking_new;
|
||||
|
||||
ovrInputStateTrackedRemote rightTrackedRemoteState_old;
|
||||
ovrInputStateTrackedRemote rightTrackedRemoteState_new;
|
||||
ovrTrackedController rightRemoteTracking_new;
|
||||
|
||||
|
||||
float remote_movementSideways;
|
||||
float remote_movementForward;
|
||||
float remote_movementUp;
|
||||
float positional_movementSideways;
|
||||
float positional_movementForward;
|
||||
float snapTurn;
|
||||
|
||||
float cinemamodeYaw;
|
||||
float cinemamodePitch;
|
||||
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
|
||||
|
||||
void handleTrackedControllerButton(ovrInputStateTrackedRemote * trackedRemoteState, ovrInputStateTrackedRemote * prevTrackedRemoteState, uint32_t button, int key)
|
||||
{
|
||||
Joy_GenerateButtonEvents(prevTrackedRemoteState->Buttons & button ? 1 : 0, trackedRemoteState->Buttons & button ? 1 : 0, 1, key);
|
||||
}
|
||||
|
||||
static void Matrix4x4_Transform (const matrix4x4 *in, const float v[3], float out[3])
|
||||
{
|
||||
out[0] = v[0] * (*in)[0][0] + v[1] * (*in)[0][1] + v[2] * (*in)[0][2] + (*in)[0][3];
|
||||
out[1] = v[0] * (*in)[1][0] + v[1] * (*in)[1][1] + v[2] * (*in)[1][2] + (*in)[1][3];
|
||||
out[2] = v[0] * (*in)[2][0] + v[1] * (*in)[2][1] + v[2] * (*in)[2][2] + (*in)[2][3];
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale );
|
||||
|
||||
void rotateAboutOrigin(float v1, float v2, float rotation, vec2_t out)
|
||||
{
|
||||
vec3_t temp = {0.0f, 0.0f, 0.0f};
|
||||
temp[0] = v1;
|
||||
temp[1] = v2;
|
||||
|
||||
vec3_t v = {0.0f, 0.0f, 0.0f};
|
||||
matrix4x4 matrix;
|
||||
vec3_t angles = {0.0f, rotation, 0.0f};
|
||||
vec3_t origin = {0.0f, 0.0f, 0.0f};
|
||||
Matrix4x4_CreateFromEntity(matrix, angles, origin, 1.0f);
|
||||
Matrix4x4_Transform(&matrix, temp, v);
|
||||
|
||||
out[0] = v[0];
|
||||
out[1] = v[1];
|
||||
}
|
||||
|
||||
float length(float x, float y)
|
||||
{
|
||||
return sqrtf(powf(x, 2.0f) + powf(y, 2.0f));
|
||||
}
|
||||
|
||||
#define NLF_DEADZONE 0.1
|
||||
#define NLF_POWER 2.2
|
||||
|
||||
float nonLinearFilter(float in)
|
||||
{
|
||||
float val = 0.0f;
|
||||
if (in > NLF_DEADZONE)
|
||||
{
|
||||
val = in;
|
||||
val -= NLF_DEADZONE;
|
||||
val /= (1.0f - NLF_DEADZONE);
|
||||
val = powf(val, NLF_POWER);
|
||||
}
|
||||
else if (in < -NLF_DEADZONE)
|
||||
{
|
||||
val = in;
|
||||
val += NLF_DEADZONE;
|
||||
val /= (1.0f - NLF_DEADZONE);
|
||||
val = -powf(fabsf(val), NLF_POWER);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool between(float min, float val, float max)
|
||||
{
|
||||
return (min < val) && (val < max);
|
||||
}
|
||||
|
|
@ -7,11 +7,7 @@ Authors : Simon Brown
|
|||
|
||||
*************************************************************************************/
|
||||
|
||||
#include <VrApi.h>
|
||||
#include <VrApi_Helpers.h>
|
||||
#include <VrApi_SystemUtils.h>
|
||||
#include <VrApi_Input.h>
|
||||
#include <VrApi_Types.h>
|
||||
|
||||
#include <android/keycodes.h>
|
||||
|
||||
#include "VrInput.h"
|
||||
|
@ -20,17 +16,11 @@ Authors : Simon Brown
|
|||
|
||||
extern ovrInputStateTrackedRemote leftTrackedRemoteState_old;
|
||||
extern ovrInputStateTrackedRemote leftTrackedRemoteState_new;
|
||||
extern ovrTracking leftRemoteTracking_new;
|
||||
extern ovrTrackedController leftRemoteTracking_new;
|
||||
|
||||
extern ovrInputStateTrackedRemote rightTrackedRemoteState_old;
|
||||
extern ovrInputStateTrackedRemote rightTrackedRemoteState_new;
|
||||
extern ovrTracking rightRemoteTracking_new;
|
||||
|
||||
extern ovrInputStateGamepad footTrackedRemoteState_old;
|
||||
extern ovrInputStateGamepad footTrackedRemoteState_new;
|
||||
|
||||
|
||||
extern ovrDeviceID controllerIDs[2];
|
||||
extern ovrTrackedController rightRemoteTracking_new;
|
||||
|
||||
extern float remote_movementSideways;
|
||||
extern float remote_movementForward;
|
||||
|
@ -42,29 +32,30 @@ extern float snapTurn;
|
|||
extern float cinemamodeYaw;
|
||||
extern float cinemamodePitch;
|
||||
|
||||
extern bool weaponStabilised;
|
||||
|
||||
int getGameState();
|
||||
int getMenuState();
|
||||
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
|
||||
float getViewpointYaw();
|
||||
|
||||
void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackingNew, ovrInputStateGamepad *pFootTrackingOld,
|
||||
ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, ovrInputStateTrackedRemote *pDominantTrackedRemoteOld, ovrTracking* pDominantTracking,
|
||||
ovrInputStateTrackedRemote *pOffTrackedRemoteNew, ovrInputStateTrackedRemote *pOffTrackedRemoteOld, ovrTracking* pOffTracking,
|
||||
void HandleInput_Default( int control_scheme, ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, ovrInputStateTrackedRemote *pDominantTrackedRemoteOld, ovrTrackedController* pDominantTracking,
|
||||
ovrInputStateTrackedRemote *pOffTrackedRemoteNew, ovrInputStateTrackedRemote *pOffTrackedRemoteOld, ovrTrackedController* pOffTracking,
|
||||
int domButton1, int domButton2, int offButton1, int offButton2 )
|
||||
|
||||
{
|
||||
//Menu button - invoke menu
|
||||
handleTrackedControllerButton(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, ovrButton_Enter, KEY_ESCAPE);
|
||||
handleTrackedControllerButton(&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, ovrButton_Enter, KEY_ESCAPE); // For users who have switched the buttons
|
||||
handleTrackedControllerButton(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, xrButton_Enter, KEY_ESCAPE);
|
||||
handleTrackedControllerButton(&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, xrButton_Enter, KEY_ESCAPE); // For users who have switched the buttons
|
||||
|
||||
//Dominant Grip works like a shift key
|
||||
bool dominantGripPushedOld = vr_secondarybuttonmappings ?
|
||||
(pDominantTrackedRemoteOld->Buttons & ovrButton_GripTrigger) != 0 : false;
|
||||
bool dominantGripPushedNew = vr_secondarybuttonmappings ?
|
||||
(pDominantTrackedRemoteNew->Buttons & ovrButton_GripTrigger) != 0 : false;
|
||||
bool dominantGripPushedOld = vr_secondary_button_mappings ?
|
||||
(pDominantTrackedRemoteOld->Buttons & xrButton_GripTrigger) : false;
|
||||
bool dominantGripPushedNew = vr_secondary_button_mappings ?
|
||||
(pDominantTrackedRemoteNew->Buttons & xrButton_GripTrigger) : false;
|
||||
|
||||
ovrInputStateTrackedRemote *pPrimaryTrackedRemoteNew, *pPrimaryTrackedRemoteOld, *pSecondaryTrackedRemoteNew, *pSecondaryTrackedRemoteOld;
|
||||
if (vr_switchsticks)
|
||||
if (vr_switch_sticks)
|
||||
{
|
||||
pPrimaryTrackedRemoteNew = pOffTrackedRemoteNew;
|
||||
pPrimaryTrackedRemoteOld = pOffTrackedRemoteOld;
|
||||
|
@ -129,19 +120,19 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
// Only do the following if we are definitely not in the menu
|
||||
if (getMenuState() == 0)
|
||||
{
|
||||
float distance = sqrtf(powf(pOffTracking->HeadPose.Pose.Position.x -
|
||||
pDominantTracking->HeadPose.Pose.Position.x, 2) +
|
||||
powf(pOffTracking->HeadPose.Pose.Position.y -
|
||||
pDominantTracking->HeadPose.Pose.Position.y, 2) +
|
||||
powf(pOffTracking->HeadPose.Pose.Position.z -
|
||||
pDominantTracking->HeadPose.Pose.Position.z, 2));
|
||||
float distance = sqrtf(powf(pOffTracking->Pose.position.x -
|
||||
pDominantTracking->Pose.position.x, 2) +
|
||||
powf(pOffTracking->Pose.position.y -
|
||||
pDominantTracking->Pose.position.y, 2) +
|
||||
powf(pOffTracking->Pose.position.z -
|
||||
pDominantTracking->Pose.position.z, 2));
|
||||
|
||||
//Turn on weapon stabilisation?
|
||||
if (vr_twohandedweapons &&
|
||||
(pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) !=
|
||||
(pOffTrackedRemoteOld->Buttons & ovrButton_GripTrigger)) {
|
||||
if (vr_two_handed_weapons &&
|
||||
(pOffTrackedRemoteNew->Buttons & xrButton_GripTrigger) !=
|
||||
(pOffTrackedRemoteOld->Buttons & xrButton_GripTrigger)) {
|
||||
|
||||
if (pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) {
|
||||
if (pOffTrackedRemoteNew->Buttons & xrButton_GripTrigger) {
|
||||
if (distance < 0.50f) {
|
||||
weaponStabilised = true;
|
||||
}
|
||||
|
@ -153,9 +144,9 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
//dominant hand stuff first
|
||||
{
|
||||
///Weapon location relative to view
|
||||
weaponoffset[0] = pDominantTracking->HeadPose.Pose.Position.x - hmdPosition[0] + vr_weapon_offset_x;
|
||||
weaponoffset[1] = pDominantTracking->HeadPose.Pose.Position.y - hmdPosition[1] + vr_weapon_offset_y;
|
||||
weaponoffset[2] = pDominantTracking->HeadPose.Pose.Position.z - hmdPosition[2] + vr_weapon_offset_z;
|
||||
weaponoffset[0] = pDominantTracking->Pose.position.x - hmdPosition[0] + vr_weaponOffsetX;
|
||||
weaponoffset[1] = pDominantTracking->Pose.position.y - hmdPosition[1] + vr_weaponOffsetY;
|
||||
weaponoffset[2] = pDominantTracking->Pose.position.z - hmdPosition[2] + vr_weaponOffsetZ;
|
||||
|
||||
vec2_t v;
|
||||
float yawRotation = getViewpointYaw() - hmdorientation[YAW];
|
||||
|
@ -164,23 +155,22 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
weaponoffset[2] = v[0];
|
||||
|
||||
//Set gun angles
|
||||
const ovrQuatf quatRemote = pDominantTracking->HeadPose.Pose.Orientation;
|
||||
vec3_t rotation = {0};
|
||||
rotation[PITCH] = vr_weapon_pitchadjust;
|
||||
QuatToYawPitchRoll(quatRemote, rotation, weaponangles);
|
||||
rotation[PITCH] = vr_weaponRotate;
|
||||
QuatToYawPitchRoll(pDominantTracking->Pose.orientation, rotation, weaponangles);
|
||||
|
||||
|
||||
if (weaponStabilised) {
|
||||
float z = pOffTracking->HeadPose.Pose.Position.z -
|
||||
pDominantTracking->HeadPose.Pose.Position.z;
|
||||
float x = pOffTracking->HeadPose.Pose.Position.x -
|
||||
pDominantTracking->HeadPose.Pose.Position.x;
|
||||
float y = pOffTracking->HeadPose.Pose.Position.y -
|
||||
pDominantTracking->HeadPose.Pose.Position.y;
|
||||
float z = pOffTracking->Pose.position.z -
|
||||
pDominantTracking->Pose.position.z;
|
||||
float x = pOffTracking->Pose.position.x -
|
||||
pDominantTracking->Pose.position.x;
|
||||
float y = pOffTracking->Pose.position.y -
|
||||
pDominantTracking->Pose.position.y;
|
||||
float zxDist = length(x, z);
|
||||
|
||||
if (zxDist != 0.0f && z != 0.0f) {
|
||||
VectorSet(weaponangles, -degrees(atanf(y / zxDist)), -degrees(atan2f(x, -z)),
|
||||
VectorSet(weaponangles, -RAD2DEG(atanf(y / zxDist)), -RAD2DEG(atan2f(x, -z)),
|
||||
weaponangles[ROLL]);
|
||||
}
|
||||
}
|
||||
|
@ -190,9 +180,9 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
|
||||
//off-hand stuff
|
||||
{
|
||||
offhandoffset[0] = pOffTracking->HeadPose.Pose.Position.x - hmdPosition[0] + vr_weapon_offset_x;
|
||||
offhandoffset[1] = pOffTracking->HeadPose.Pose.Position.y - hmdPosition[1] + vr_weapon_offset_y;
|
||||
offhandoffset[2] = pOffTracking->HeadPose.Pose.Position.z - hmdPosition[2] + vr_weapon_offset_z;
|
||||
offhandoffset[0] = pOffTracking->Pose.position.x - hmdPosition[0] + vr_weaponOffsetX;
|
||||
offhandoffset[1] = pOffTracking->Pose.position.y - hmdPosition[1] + vr_weaponOffsetY;
|
||||
offhandoffset[2] = pOffTracking->Pose.position.z - hmdPosition[2] + vr_weaponOffsetZ;
|
||||
|
||||
vec2_t v;
|
||||
float yawRotation = getViewpointYaw() - hmdorientation[YAW];
|
||||
|
@ -201,10 +191,10 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
offhandoffset[2] = v[0];
|
||||
|
||||
vec3_t rotation = {0};
|
||||
rotation[PITCH] = vr_weapon_pitchadjust;
|
||||
QuatToYawPitchRoll(pOffTracking->HeadPose.Pose.Orientation, rotation, offhandangles);
|
||||
rotation[PITCH] = vr_weaponRotate;
|
||||
QuatToYawPitchRoll(pOffTracking->Pose.orientation, rotation, offhandangles);
|
||||
|
||||
if (vr_moveuseoffhand) {
|
||||
if (vr_move_use_offhand) {
|
||||
controllerYawHeading = offhandangles[YAW] - hmdorientation[YAW];
|
||||
} else {
|
||||
controllerYawHeading = 0.0f;
|
||||
|
@ -214,9 +204,9 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
//Positional movement
|
||||
{
|
||||
ALOGV(" Right-Controller-Position: %f, %f, %f",
|
||||
pDominantTracking->HeadPose.Pose.Position.x,
|
||||
pDominantTracking->HeadPose.Pose.Position.y,
|
||||
pDominantTracking->HeadPose.Pose.Position.z);
|
||||
pDominantTracking->Pose.position.x,
|
||||
pDominantTracking->Pose.position.y,
|
||||
pDominantTracking->Pose.position.z);
|
||||
|
||||
vec2_t v;
|
||||
rotateAboutOrigin(positionDeltaThisFrame[0], positionDeltaThisFrame[2],
|
||||
|
@ -232,12 +222,12 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
//Off-hand specific stuff
|
||||
{
|
||||
ALOGV(" Left-Controller-Position: %f, %f, %f",
|
||||
pOffTracking->HeadPose.Pose.Position.x,
|
||||
pOffTracking->HeadPose.Pose.Position.y,
|
||||
pOffTracking->HeadPose.Pose.Position.z);
|
||||
pOffTracking->Pose.position.x,
|
||||
pOffTracking->Pose.position.y,
|
||||
pOffTracking->Pose.position.z);
|
||||
|
||||
//Teleport - only does anything if vr_teleport cvar is true
|
||||
if (vr_use_teleport) {
|
||||
if (vr_teleport) {
|
||||
if ((pSecondaryTrackedRemoteOld->Joystick.y > 0.7f) && !ready_teleport) {
|
||||
ready_teleport = true;
|
||||
} else if ((pSecondaryTrackedRemoteOld->Joystick.y < 0.7f) && ready_teleport) {
|
||||
|
@ -250,8 +240,8 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
//and we don't get movement jitter when the joystick doesn't quite center properly
|
||||
float dist = length(pSecondaryTrackedRemoteNew->Joystick.x, pSecondaryTrackedRemoteNew->Joystick.y);
|
||||
float nlf = nonLinearFilter(dist);
|
||||
float x = nlf * pSecondaryTrackedRemoteNew->Joystick.x + pFootTrackingNew->LeftJoystick.x;
|
||||
float y = nlf * pSecondaryTrackedRemoteNew->Joystick.y - pFootTrackingNew->LeftJoystick.y;
|
||||
float x = nlf * pSecondaryTrackedRemoteNew->Joystick.x;
|
||||
float y = nlf * pSecondaryTrackedRemoteNew->Joystick.y;
|
||||
|
||||
//Apply a simple deadzone
|
||||
player_moving = (fabs(x) + fabs(y)) > 0.05f;
|
||||
|
@ -276,8 +266,8 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
if (pPrimaryTrackedRemoteNew->Joystick.x > 0.6f) {
|
||||
if (increaseSnap) {
|
||||
resetDoomYaw = true;
|
||||
snapTurn -= vr_snapturn_angle;
|
||||
if (vr_snapturn_angle > 10.0f) {
|
||||
snapTurn -= vr_snapTurn;
|
||||
if (vr_snapTurn > 10.0f) {
|
||||
increaseSnap = false;
|
||||
}
|
||||
|
||||
|
@ -293,10 +283,10 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
if (pPrimaryTrackedRemoteNew->Joystick.x < -0.6f) {
|
||||
if (decreaseSnap) {
|
||||
resetDoomYaw = true;
|
||||
snapTurn += vr_snapturn_angle;
|
||||
snapTurn += vr_snapTurn;
|
||||
|
||||
//If snap turn configured for less than 10 degrees
|
||||
if (vr_snapturn_angle > 10.0f) {
|
||||
if (vr_snapTurn > 10.0f) {
|
||||
decreaseSnap = false;
|
||||
}
|
||||
|
||||
|
@ -328,13 +318,13 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
|
||||
//If snap turn set to 0, then we can use left/right on the stick as mappable functions
|
||||
Joy_GenerateButtonEvents(
|
||||
(pPrimaryTrackedRemoteOld->Joystick.x > 0.7f && !dominantGripPushedOld && !vr_snapturn_angle ? 1 : 0),
|
||||
(pPrimaryTrackedRemoteNew->Joystick.x > 0.7f && !dominantGripPushedNew && !vr_snapturn_angle ? 1 : 0),
|
||||
(pPrimaryTrackedRemoteOld->Joystick.x > 0.7f && !dominantGripPushedOld && !vr_snapTurn ? 1 : 0),
|
||||
(pPrimaryTrackedRemoteNew->Joystick.x > 0.7f && !dominantGripPushedNew && !vr_snapTurn ? 1 : 0),
|
||||
1, KEY_MWHEELLEFT);
|
||||
|
||||
Joy_GenerateButtonEvents(
|
||||
(pPrimaryTrackedRemoteOld->Joystick.x < -0.7f && !dominantGripPushedOld && !vr_snapturn_angle ? 1 : 0),
|
||||
(pPrimaryTrackedRemoteNew->Joystick.x < -0.7f && !dominantGripPushedNew && !vr_snapturn_angle ? 1 : 0),
|
||||
(pPrimaryTrackedRemoteOld->Joystick.x < -0.7f && !dominantGripPushedOld && !vr_snapTurn ? 1 : 0),
|
||||
(pPrimaryTrackedRemoteNew->Joystick.x < -0.7f && !dominantGripPushedNew && !vr_snapTurn ? 1 : 0),
|
||||
1, KEY_MWHEELRIGHT);
|
||||
}
|
||||
|
||||
|
@ -343,8 +333,8 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
{
|
||||
//Fire
|
||||
Joy_GenerateButtonEvents(
|
||||
((pDominantTrackedRemoteOld->Buttons & ovrButton_Trigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pDominantTrackedRemoteOld->Buttons & xrButton_Trigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & xrButton_Trigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_PAD_RTRIGGER);
|
||||
|
||||
//"Use" (open door, toggle switch etc)
|
||||
|
@ -361,21 +351,21 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
|
||||
// Inv Use
|
||||
Joy_GenerateButtonEvents(
|
||||
((pDominantTrackedRemoteOld->Buttons & ovrButton_Joystick) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & ovrButton_Joystick) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pDominantTrackedRemoteOld->Buttons & xrButton_Joystick) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & xrButton_Joystick) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_ENTER);
|
||||
|
||||
//No Default Binding
|
||||
Joy_GenerateButtonEvents(
|
||||
((pDominantTrackedRemoteOld->Touches & ovrTouch_ThumbRest) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Touches & ovrTouch_ThumbRest) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pDominantTrackedRemoteOld->Touches & xrButton_ThumbRest) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Touches & xrButton_ThumbRest) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_JOY5);
|
||||
|
||||
//Use grip as an extra button
|
||||
//Alt-Fire
|
||||
Joy_GenerateButtonEvents(
|
||||
((pDominantTrackedRemoteOld->Buttons & ovrButton_GripTrigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & ovrButton_GripTrigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pDominantTrackedRemoteOld->Buttons & xrButton_GripTrigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & xrButton_GripTrigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_PAD_LTRIGGER);
|
||||
}
|
||||
|
||||
|
@ -383,8 +373,8 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
{
|
||||
//Alt-Fire
|
||||
Joy_GenerateButtonEvents(
|
||||
((pDominantTrackedRemoteOld->Buttons & ovrButton_Trigger) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
((pDominantTrackedRemoteOld->Buttons & xrButton_Trigger) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & xrButton_Trigger) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_PAD_LTRIGGER);
|
||||
|
||||
//Crouch
|
||||
|
@ -401,14 +391,14 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
|
||||
//No Binding
|
||||
Joy_GenerateButtonEvents(
|
||||
((pDominantTrackedRemoteOld->Buttons & ovrButton_Joystick) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & ovrButton_Joystick) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
((pDominantTrackedRemoteOld->Buttons & xrButton_Joystick) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Buttons & xrButton_Joystick) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_TAB);
|
||||
|
||||
//No Default Binding
|
||||
Joy_GenerateButtonEvents(
|
||||
((pDominantTrackedRemoteOld->Touches & ovrTouch_ThumbRest) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Touches & ovrTouch_ThumbRest) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
((pDominantTrackedRemoteOld->Touches & xrButton_ThumbRest) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pDominantTrackedRemoteNew->Touches & xrButton_ThumbRest) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_JOY6);
|
||||
|
||||
}
|
||||
|
@ -418,8 +408,8 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
{
|
||||
//No Default Binding
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Buttons & ovrButton_Trigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & ovrButton_Trigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Buttons & xrButton_Trigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & xrButton_Trigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_LSHIFT);
|
||||
|
||||
//No Default Binding
|
||||
|
@ -436,19 +426,19 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
|
||||
//"Use" (open door, toggle switch etc) - Can be rebound for other uses
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Buttons & ovrButton_Joystick) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & ovrButton_Joystick) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Buttons & xrButton_Joystick) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & xrButton_Joystick) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_SPACE);
|
||||
|
||||
//No Default Binding
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Touches & ovrTouch_ThumbRest) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Touches & ovrTouch_ThumbRest) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Touches & xrButton_ThumbRest) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Touches & xrButton_ThumbRest) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_JOY7);
|
||||
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Buttons & ovrButton_GripTrigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Buttons & xrButton_GripTrigger) != 0) && !dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & xrButton_GripTrigger) != 0) && !dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_PAD_RTHUMB);
|
||||
}
|
||||
|
||||
|
@ -456,8 +446,8 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
{
|
||||
//No Default Binding
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Buttons & ovrButton_Trigger) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & ovrButton_Trigger) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Buttons & xrButton_Trigger) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & xrButton_Trigger) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_LALT);
|
||||
|
||||
//Move Down
|
||||
|
@ -474,19 +464,19 @@ void HandleInput_Default( int control_scheme, ovrInputStateGamepad *pFootTrackin
|
|||
|
||||
//Land
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Buttons & ovrButton_Joystick) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & ovrButton_Joystick) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Buttons & xrButton_Joystick) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & xrButton_Joystick) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_HOME);
|
||||
|
||||
//No Default Binding
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Touches & ovrTouch_ThumbRest) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Touches & ovrTouch_ThumbRest) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Touches & xrButton_ThumbRest) != 0) && dominantGripPushedOld ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Touches & xrButton_ThumbRest) != 0) && dominantGripPushedNew ? 1 : 0,
|
||||
1, KEY_JOY8);
|
||||
|
||||
Joy_GenerateButtonEvents(
|
||||
((pOffTrackedRemoteOld->Buttons & ovrButton_GripTrigger) != 0) && dominantGripPushedOld && !vr_twohandedweapons ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) != 0) && dominantGripPushedNew && !vr_twohandedweapons ? 1 : 0,
|
||||
((pOffTrackedRemoteOld->Buttons & xrButton_GripTrigger) != 0) && dominantGripPushedOld && !vr_two_handed_weapons ? 1 : 0,
|
||||
((pOffTrackedRemoteNew->Buttons & xrButton_GripTrigger) != 0) && dominantGripPushedNew && !vr_two_handed_weapons ? 1 : 0,
|
||||
1, KEY_PAD_DPAD_UP);
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 88800f0fc2f5a8cb41b0714ebfd234b9f0ba624e
|
||||
Subproject commit e813c7adec5578b1385f641962af1dc803046d84
|
|
@ -1,4 +1,4 @@
|
|||
rootProject.projectDir = new File(settingsDir, '../../../..')
|
||||
rootProject.name = "QuestZDoom"
|
||||
|
||||
include ':', 'VrSamples:QuestZDoom:Projects:Android'
|
||||
include ':', 'XrSamples:QuestZDoom:Projects:Android'
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":VrSamples:QuestzDoom:Projects" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/Android" external.system.id="GRADLE" external.system.module.group="QuestzDoom.VrSamples.QuestzDoom" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<module external.linked.project.id=":XrSamples:QuestZDoom:Projects" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/Android" external.system.id="GRADLE" external.system.module.group="QuestZDoom.XrSamples.QuestZDoom" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":VrSamples:QuestzDoom:Projects" />
|
||||
<option name="GRADLE_PROJECT_PATH" value=":XrSamples:QuestZDoom:Projects" />
|
||||
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
|
||||
<option name="LAST_KNOWN_AGP_VERSION" />
|
||||
</configuration>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":VrSamples:QuestzDoom" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/Projects/Android" external.system.id="GRADLE" external.system.module.group="QuestzDoom.VrSamples" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<module external.linked.project.id=":XrSamples:QuestZDoom" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/Projects/Android" external.system.id="GRADLE" external.system.module.group="QuestZDoom.XrSamples" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":VrSamples:QuestzDoom" />
|
||||
<option name="GRADLE_PROJECT_PATH" value=":XrSamples:QuestZDoom" />
|
||||
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
|
||||
<option name="LAST_KNOWN_AGP_VERSION" />
|
||||
</configuration>
|
Binary file not shown.
Loading…
Reference in a new issue