2022-09-18 15:37:21 +00:00
/************************************************************************************
Filename : VrInputRight . c
Content : Handles common controller input functionality
Created : September 2019
Authors : Simon Brown
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "VrInput.h"
2022-09-19 21:46:47 +00:00
# include <qcommon/qcommon.h>
# include <qcommon/q_platform.h>
2022-09-18 15:37:21 +00:00
2022-09-20 22:15:52 +00:00
cvar_t * vr_turn_mode ;
cvar_t * vr_turn_angle ;
cvar_t * vr_positional_factor ;
cvar_t * vr_walkdirection ;
cvar_t * vr_weapon_pitchadjust ;
cvar_t * vr_control_scheme ;
cvar_t * vr_virtual_stock ;
cvar_t * vr_switch_sticks ;
2022-09-27 22:19:12 +00:00
cvar_t * vr_immersive_cinematics ;
2022-09-20 22:15:52 +00:00
cvar_t * vr_screen_dist ;
2022-10-12 17:00:26 +00:00
cvar_t * vr_weapon_velocity_trigger ;
2022-11-07 23:57:10 +00:00
cvar_t * vr_force_velocity_trigger ;
2022-11-27 14:51:07 +00:00
cvar_t * vr_force_distance_trigger ;
2022-10-20 16:47:12 +00:00
cvar_t * vr_two_handed_weapons ;
2022-11-07 23:57:10 +00:00
cvar_t * vr_force_motion_controlled ;
2022-11-11 23:43:50 +00:00
cvar_t * vr_crouch_toggle ;
2022-11-16 21:27:36 +00:00
cvar_t * vr_irl_crouch_enabled ;
cvar_t * vr_irl_crouch_to_stand_ratio ;
2022-11-12 17:05:39 +00:00
cvar_t * vr_saber_block_debounce_time ;
2022-11-17 00:05:01 +00:00
cvar_t * vr_haptic_intensity ;
2022-11-25 18:01:08 +00:00
cvar_t * vr_comfort_vignette ;
2022-11-25 23:35:49 +00:00
cvar_t * vr_saber_3rdperson_mode ;
2022-11-26 15:38:17 +00:00
cvar_t * vr_gesture_triggered_use ;
cvar_t * vr_gesture_triggered_use_threshold ;
2022-09-20 22:15:52 +00:00
ovrInputStateTrackedRemote leftTrackedRemoteState_old ;
ovrInputStateTrackedRemote leftTrackedRemoteState_new ;
2022-12-04 11:46:32 +00:00
ovrTrackedController leftRemoteTracking_new ;
2022-09-20 22:15:52 +00:00
ovrInputStateTrackedRemote rightTrackedRemoteState_old ;
ovrInputStateTrackedRemote rightTrackedRemoteState_new ;
2022-12-04 11:46:32 +00:00
ovrTrackedController rightRemoteTracking_new ;
2022-09-20 22:15:52 +00:00
float remote_movementSideways ;
float remote_movementForward ;
float remote_movementUp ;
float positional_movementSideways ;
float positional_movementForward ;
2022-09-29 22:38:22 +00:00
bool openjk_initialised ;
2022-09-20 22:15:52 +00:00
long long global_time ;
int ducked ;
vr_client_info_t vr ;
2022-12-09 18:57:02 +00:00
extern ovrApp gAppState ;
//OpenXR
XrPath leftHandPath ;
XrPath rightHandPath ;
XrAction handPoseLeftAction ;
XrAction handPoseRightAction ;
XrAction indexLeftAction ;
XrAction indexRightAction ;
XrAction menuAction ;
XrAction buttonAAction ;
XrAction buttonBAction ;
XrAction buttonXAction ;
XrAction buttonYAction ;
XrAction gripLeftAction ;
XrAction gripRightAction ;
XrAction moveOnLeftJoystickAction ;
XrAction moveOnRightJoystickAction ;
XrAction thumbstickLeftClickAction ;
XrAction thumbstickRightClickAction ;
XrAction vibrateLeftFeedback ;
XrAction vibrateRightFeedback ;
XrActionSet runningActionSet ;
XrSpace leftControllerAimSpace = XR_NULL_HANDLE ;
XrSpace rightControllerAimSpace = XR_NULL_HANDLE ;
qboolean inputInitialized = qfalse ;
qboolean useSimpleProfile = qfalse ;
XrSpace CreateActionSpace ( XrAction poseAction , XrPath subactionPath ) {
XrActionSpaceCreateInfo asci = { } ;
asci . type = XR_TYPE_ACTION_SPACE_CREATE_INFO ;
asci . action = poseAction ;
asci . poseInActionSpace . orientation . w = 1.0f ;
asci . subactionPath = subactionPath ;
XrSpace actionSpace = XR_NULL_HANDLE ;
OXR ( xrCreateActionSpace ( gAppState . Session , & asci , & actionSpace ) ) ;
return actionSpace ;
}
XrActionSuggestedBinding ActionSuggestedBinding ( XrAction action , const char * bindingString ) {
XrActionSuggestedBinding asb ;
asb . action = action ;
XrPath bindingPath ;
OXR ( xrStringToPath ( gAppState . Instance , bindingString , & bindingPath ) ) ;
asb . binding = bindingPath ;
return asb ;
}
XrActionSet CreateActionSet ( int priority , const char * name , const char * localizedName ) {
XrActionSetCreateInfo asci = { } ;
asci . type = XR_TYPE_ACTION_SET_CREATE_INFO ;
asci . next = NULL ;
asci . priority = priority ;
strcpy ( asci . actionSetName , name ) ;
strcpy ( asci . localizedActionSetName , localizedName ) ;
XrActionSet actionSet = XR_NULL_HANDLE ;
OXR ( xrCreateActionSet ( gAppState . Instance , & asci , & actionSet ) ) ;
return actionSet ;
}
XrAction CreateAction (
XrActionSet actionSet ,
XrActionType type ,
const char * actionName ,
const char * localizedName ,
int countSubactionPaths ,
XrPath * subactionPaths ) {
ALOGV ( " CreateAction %s, % " PRIi32 , actionName , countSubactionPaths ) ;
XrActionCreateInfo aci = { } ;
aci . type = XR_TYPE_ACTION_CREATE_INFO ;
aci . next = NULL ;
aci . actionType = type ;
if ( countSubactionPaths > 0 ) {
aci . countSubactionPaths = countSubactionPaths ;
aci . subactionPaths = subactionPaths ;
}
strcpy ( aci . actionName , actionName ) ;
strcpy ( aci . localizedActionName , localizedName ? localizedName : actionName ) ;
XrAction action = XR_NULL_HANDLE ;
OXR ( xrCreateAction ( actionSet , & aci , & action ) ) ;
return action ;
}
bool ActionPoseIsActive ( XrAction action , XrPath subactionPath ) {
XrActionStateGetInfo getInfo = { } ;
getInfo . type = XR_TYPE_ACTION_STATE_GET_INFO ;
getInfo . action = action ;
getInfo . subactionPath = subactionPath ;
XrActionStatePose state = { } ;
state . type = XR_TYPE_ACTION_STATE_POSE ;
OXR ( xrGetActionStatePose ( gAppState . Session , & getInfo , & state ) ) ;
return state . isActive ! = XR_FALSE ;
}
XrActionStateFloat GetActionStateFloat ( XrAction action ) {
XrActionStateGetInfo getInfo = { } ;
getInfo . type = XR_TYPE_ACTION_STATE_GET_INFO ;
getInfo . action = action ;
XrActionStateFloat state = { } ;
state . type = XR_TYPE_ACTION_STATE_FLOAT ;
OXR ( xrGetActionStateFloat ( gAppState . Session , & getInfo , & state ) ) ;
return state ;
}
XrActionStateBoolean GetActionStateBoolean ( XrAction action ) {
XrActionStateGetInfo getInfo = { } ;
getInfo . type = XR_TYPE_ACTION_STATE_GET_INFO ;
getInfo . action = action ;
XrActionStateBoolean state = { } ;
state . type = XR_TYPE_ACTION_STATE_BOOLEAN ;
OXR ( xrGetActionStateBoolean ( gAppState . Session , & getInfo , & state ) ) ;
return state ;
}
XrActionStateVector2f GetActionStateVector2 ( XrAction action ) {
XrActionStateGetInfo getInfo = { } ;
getInfo . type = XR_TYPE_ACTION_STATE_GET_INFO ;
getInfo . action = action ;
XrActionStateVector2f state = { } ;
state . type = XR_TYPE_ACTION_STATE_VECTOR2F ;
OXR ( xrGetActionStateVector2f ( gAppState . Session , & getInfo , & state ) ) ;
return state ;
}
void JKVR_InitActions ( void )
{
// Actions
runningActionSet = CreateActionSet ( 1 , " running_action_set " , " Action Set used on main loop " ) ;
indexLeftAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " index_left " , " Index left " , 0 , NULL ) ;
indexRightAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " index_right " , " Index right " , 0 , NULL ) ;
menuAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " menu_action " , " Menu " , 0 , NULL ) ;
buttonAAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " button_a " , " Button A " , 0 , NULL ) ;
buttonBAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " button_b " , " Button B " , 0 , NULL ) ;
buttonXAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " button_x " , " Button X " , 0 , NULL ) ;
buttonYAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " button_y " , " Button Y " , 0 , NULL ) ;
gripLeftAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_FLOAT_INPUT , " grip_left " , " Grip left " , 0 , NULL ) ;
gripRightAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_FLOAT_INPUT , " grip_right " , " Grip right " , 0 , NULL ) ;
moveOnLeftJoystickAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_VECTOR2F_INPUT , " move_on_left_joy " , " Move on left Joy " , 0 , NULL ) ;
moveOnRightJoystickAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_VECTOR2F_INPUT , " move_on_right_joy " , " Move on right Joy " , 0 , NULL ) ;
thumbstickLeftClickAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " thumbstick_left " , " Thumbstick left " , 0 , NULL ) ;
thumbstickRightClickAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " thumbstick_right " , " Thumbstick right " , 0 , NULL ) ;
vibrateLeftFeedback = CreateAction ( runningActionSet , XR_ACTION_TYPE_VIBRATION_OUTPUT , " vibrate_left_feedback " , " Vibrate Left Controller Feedback " , 0 , NULL ) ;
vibrateRightFeedback = CreateAction ( runningActionSet , XR_ACTION_TYPE_VIBRATION_OUTPUT , " vibrate_right_feedback " , " Vibrate Right Controller Feedback " , 0 , NULL ) ;
OXR ( xrStringToPath ( gAppState . Instance , " /user/hand/left " , & leftHandPath ) ) ;
OXR ( xrStringToPath ( gAppState . Instance , " /user/hand/right " , & rightHandPath ) ) ;
handPoseLeftAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_POSE_INPUT , " hand_pose_left " , NULL , 1 , & leftHandPath ) ;
handPoseRightAction = CreateAction ( runningActionSet , XR_ACTION_TYPE_POSE_INPUT , " hand_pose_right " , NULL , 1 , & rightHandPath ) ;
XrPath interactionProfilePath = XR_NULL_PATH ;
XrPath interactionProfilePathTouch = XR_NULL_PATH ;
XrPath interactionProfilePathKHRSimple = XR_NULL_PATH ;
OXR ( xrStringToPath ( gAppState . Instance , " /interaction_profiles/oculus/touch_controller " , & interactionProfilePathTouch ) ) ;
OXR ( xrStringToPath ( gAppState . Instance , " /interaction_profiles/khr/simple_controller " , & interactionProfilePathKHRSimple ) ) ;
// Toggle this to force simple as a first choice, otherwise use it as a last resort
if ( useSimpleProfile ) {
ALOGV ( " xrSuggestInteractionProfileBindings found bindings for Khronos SIMPLE controller " ) ;
interactionProfilePath = interactionProfilePathKHRSimple ;
} else {
// Query Set
XrActionSet queryActionSet = CreateActionSet ( 1 , " query_action_set " , " Action Set used to query device caps " ) ;
XrAction dummyAction = CreateAction ( queryActionSet , XR_ACTION_TYPE_BOOLEAN_INPUT , " dummy_action " , " Dummy Action " , 0 , NULL ) ;
// Map bindings
XrActionSuggestedBinding bindings [ 1 ] ;
int currBinding = 0 ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( dummyAction , " /user/hand/right/input/system/click " ) ;
XrInteractionProfileSuggestedBinding suggestedBindings = { } ;
suggestedBindings . type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING ;
suggestedBindings . next = NULL ;
suggestedBindings . suggestedBindings = bindings ;
suggestedBindings . countSuggestedBindings = currBinding ;
// Try all
suggestedBindings . interactionProfile = interactionProfilePathTouch ;
XrResult suggestTouchResult = xrSuggestInteractionProfileBindings ( gAppState . Instance , & suggestedBindings ) ;
OXR ( suggestTouchResult ) ;
if ( XR_SUCCESS = = suggestTouchResult ) {
ALOGV ( " xrSuggestInteractionProfileBindings found bindings for QUEST controller " ) ;
interactionProfilePath = interactionProfilePathTouch ;
}
if ( interactionProfilePath = = XR_NULL_PATH ) {
// Simple as a fallback
bindings [ 0 ] = ActionSuggestedBinding ( dummyAction , " /user/hand/right/input/select/click " ) ;
suggestedBindings . interactionProfile = interactionProfilePathKHRSimple ;
XrResult suggestKHRSimpleResult = xrSuggestInteractionProfileBindings ( gAppState . Instance , & suggestedBindings ) ;
OXR ( suggestKHRSimpleResult ) ;
if ( XR_SUCCESS = = suggestKHRSimpleResult ) {
ALOGV ( " xrSuggestInteractionProfileBindings found bindings for Khronos SIMPLE controller " ) ;
interactionProfilePath = interactionProfilePathKHRSimple ;
} else {
ALOGE ( " xrSuggestInteractionProfileBindings did NOT find any bindings. " ) ;
assert ( qfalse ) ;
}
}
}
// Action creation
{
// Map bindings
XrActionSuggestedBinding bindings [ 32 ] ; // large enough for all profiles
int currBinding = 0 ;
{
if ( interactionProfilePath = = interactionProfilePathTouch ) {
bindings [ currBinding + + ] = ActionSuggestedBinding ( indexLeftAction , " /user/hand/left/input/trigger " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( indexRightAction , " /user/hand/right/input/trigger " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( menuAction , " /user/hand/left/input/menu/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( buttonXAction , " /user/hand/left/input/x/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( buttonYAction , " /user/hand/left/input/y/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( buttonAAction , " /user/hand/right/input/a/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( buttonBAction , " /user/hand/right/input/b/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( gripLeftAction , " /user/hand/left/input/squeeze/value " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( gripRightAction , " /user/hand/right/input/squeeze/value " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( moveOnLeftJoystickAction , " /user/hand/left/input/thumbstick " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( moveOnRightJoystickAction , " /user/hand/right/input/thumbstick " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( thumbstickLeftClickAction , " /user/hand/left/input/thumbstick/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( thumbstickRightClickAction , " /user/hand/right/input/thumbstick/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( vibrateLeftFeedback , " /user/hand/left/output/haptic " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( vibrateRightFeedback , " /user/hand/right/output/haptic " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( handPoseLeftAction , " /user/hand/left/input/aim/pose " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( handPoseRightAction , " /user/hand/right/input/aim/pose " ) ;
}
if ( interactionProfilePath = = interactionProfilePathKHRSimple ) {
bindings [ currBinding + + ] = ActionSuggestedBinding ( indexLeftAction , " /user/hand/left/input/select/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( indexRightAction , " /user/hand/right/input/select/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( buttonAAction , " /user/hand/left/input/menu/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( buttonXAction , " /user/hand/right/input/menu/click " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( vibrateLeftFeedback , " /user/hand/left/output/haptic " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( vibrateRightFeedback , " /user/hand/right/output/haptic " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( handPoseLeftAction , " /user/hand/left/input/aim/pose " ) ;
bindings [ currBinding + + ] = ActionSuggestedBinding ( handPoseRightAction , " /user/hand/right/input/aim/pose " ) ;
}
}
XrInteractionProfileSuggestedBinding suggestedBindings = { } ;
suggestedBindings . type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING ;
suggestedBindings . next = NULL ;
suggestedBindings . interactionProfile = interactionProfilePath ;
suggestedBindings . suggestedBindings = bindings ;
suggestedBindings . countSuggestedBindings = currBinding ;
OXR ( xrSuggestInteractionProfileBindings ( gAppState . Instance , & suggestedBindings ) ) ;
// Enumerate actions
XrPath actionPathsBuffer [ 32 ] ;
char stringBuffer [ 256 ] ;
XrAction actionsToEnumerate [ ] = {
indexLeftAction ,
indexRightAction ,
menuAction ,
buttonAAction ,
buttonBAction ,
buttonXAction ,
buttonYAction ,
gripLeftAction ,
gripRightAction ,
moveOnLeftJoystickAction ,
moveOnRightJoystickAction ,
thumbstickLeftClickAction ,
thumbstickRightClickAction ,
vibrateLeftFeedback ,
vibrateRightFeedback ,
handPoseLeftAction ,
handPoseRightAction
} ;
for ( size_t i = 0 ; i < sizeof ( actionsToEnumerate ) / sizeof ( actionsToEnumerate [ 0 ] ) ; + + i ) {
XrBoundSourcesForActionEnumerateInfo enumerateInfo = { } ;
enumerateInfo . type = XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO ;
enumerateInfo . next = NULL ;
enumerateInfo . action = actionsToEnumerate [ i ] ;
// Get Count
uint32_t countOutput = 0 ;
OXR ( xrEnumerateBoundSourcesForAction (
gAppState . Session , & enumerateInfo , 0 /* request size */ , & countOutput , NULL ) ) ;
ALOGV (
" xrEnumerateBoundSourcesForAction action=%lld count=%u " ,
( long long ) enumerateInfo . action ,
countOutput ) ;
if ( countOutput < 32 ) {
OXR ( xrEnumerateBoundSourcesForAction (
gAppState . Session , & enumerateInfo , 32 , & countOutput , actionPathsBuffer ) ) ;
for ( uint32_t a = 0 ; a < countOutput ; + + a ) {
XrInputSourceLocalizedNameGetInfo nameGetInfo = { } ;
nameGetInfo . type = XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO ;
nameGetInfo . next = NULL ;
nameGetInfo . sourcePath = actionPathsBuffer [ a ] ;
nameGetInfo . whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT |
XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT ;
uint32_t stringCount = 0u ;
OXR ( xrGetInputSourceLocalizedName (
gAppState . Session , & nameGetInfo , 0 , & stringCount , NULL ) ) ;
if ( stringCount < 256 ) {
OXR ( xrGetInputSourceLocalizedName (
gAppState . Session , & nameGetInfo , 256 , & stringCount , stringBuffer ) ) ;
char pathStr [ 256 ] ;
uint32_t strLen = 0 ;
OXR ( xrPathToString (
gAppState . Instance ,
actionPathsBuffer [ a ] ,
( uint32_t ) sizeof ( pathStr ) ,
& strLen ,
pathStr ) ) ;
ALOGV (
" -> path = %lld `%s` -> `%s` " ,
( long long ) actionPathsBuffer [ a ] ,
pathStr ,
stringBuffer ) ;
}
}
}
}
}
inputInitialized = qtrue ;
}
//0 = left, 1 = right
float vibration_channel_duration [ 2 ] = { 0.0f , 0.0f } ;
float vibration_channel_intensity [ 2 ] = { 0.0f , 0.0f } ;
void JKVR_Vibrate ( int duration , int chan , float intensity )
{
for ( int i = 0 ; i < 2 ; + + i )
{
int channel = ( i + 1 ) & chan ;
if ( channel )
{
if ( vibration_channel_duration [ channel - 1 ] > 0.0f )
return ;
if ( vibration_channel_duration [ channel - 1 ] = = - 1.0f & & duration ! = 0.0f )
return ;
vibration_channel_duration [ channel - 1 ] = duration ;
vibration_channel_intensity [ channel - 1 ] = intensity * vr_haptic_intensity - > value ;
}
}
}
void JKVR_processHaptics ( ) {
static float lastFrameTime = 0.0f ;
float timestamp = ( float ) ( Sys_Milliseconds ( ) ) ;
float frametime = timestamp - lastFrameTime ;
lastFrameTime = timestamp ;
for ( int i = 0 ; i < 2 ; + + i ) {
if ( vibration_channel_duration [ i ] > 0.0f | |
vibration_channel_duration [ i ] = = - 1.0f ) {
// fire haptics using output action
XrHapticVibration vibration = { } ;
vibration . type = XR_TYPE_HAPTIC_VIBRATION ;
vibration . next = NULL ;
vibration . amplitude = vibration_channel_intensity [ i ] ;
vibration . duration = ToXrTime ( vibration_channel_duration [ i ] ) ;
vibration . frequency = 3000 ;
XrHapticActionInfo hapticActionInfo = { } ;
hapticActionInfo . type = XR_TYPE_HAPTIC_ACTION_INFO ;
hapticActionInfo . next = NULL ;
hapticActionInfo . action = i = = 0 ? vibrateLeftFeedback : vibrateRightFeedback ;
OXR ( xrApplyHapticFeedback ( gAppState . Session , & hapticActionInfo , ( const XrHapticBaseHeader * ) & vibration ) ) ;
if ( vibration_channel_duration [ i ] ! = - 1.0f ) {
vibration_channel_duration [ i ] - = frametime ;
if ( vibration_channel_duration [ i ] < 0.0f ) {
vibration_channel_duration [ i ] = 0.0f ;
vibration_channel_intensity [ i ] = 0.0f ;
}
}
} else {
// Stop haptics
XrHapticActionInfo hapticActionInfo = { } ;
hapticActionInfo . type = XR_TYPE_HAPTIC_ACTION_INFO ;
hapticActionInfo . next = NULL ;
hapticActionInfo . action = i = = 0 ? vibrateLeftFeedback : vibrateRightFeedback ;
OXR ( xrStopHapticFeedback ( gAppState . Session , & hapticActionInfo ) ) ;
}
}
}
2022-09-18 15:37:21 +00:00
//keys.h
void Sys_QueEvent ( int time , sysEventType_t type , int value , int value2 , int ptrLength , void * ptr ) ;
void handleTrackedControllerButton ( ovrInputStateTrackedRemote * trackedRemoteState , ovrInputStateTrackedRemote * prevTrackedRemoteState , uint32_t button , int key )
{
if ( ( trackedRemoteState - > Buttons & button ) ! = ( prevTrackedRemoteState - > Buttons & button ) )
{
Sys_QueEvent ( 0 , SE_KEY , key , ( trackedRemoteState - > Buttons & button ) ! = 0 , 0 , NULL ) ;
// Key_Event(key, (trackedRemoteState->Buttons & button) != 0, global_time);
}
}
void rotateAboutOrigin ( float x , float y , float rotation , vec2_t out )
{
out [ 0 ] = cosf ( DEG2RAD ( - rotation ) ) * x + sinf ( DEG2RAD ( - rotation ) ) * y ;
out [ 1 ] = cosf ( DEG2RAD ( - rotation ) ) * y - sinf ( DEG2RAD ( - rotation ) ) * x ;
}
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 ;
}
void sendButtonActionSimple ( const char * action )
{
char command [ 256 ] ;
snprintf ( command , sizeof ( command ) , " %s \n " , action ) ;
Cbuf_AddText ( command ) ;
}
2022-09-19 21:46:47 +00:00
bool between ( float min , float val , float max )
2022-09-18 15:37:21 +00:00
{
return ( min < val ) & & ( val < max ) ;
}
void sendButtonAction ( const char * action , long buttonDown )
{
char command [ 256 ] ;
snprintf ( command , sizeof ( command ) , " %s \n " , action ) ;
if ( ! buttonDown )
{
command [ 0 ] = ' - ' ;
}
Cbuf_AddText ( command ) ;
}
void PortableMouseAbs ( float x , float y ) ;
float clamp ( float _min , float _val , float _max )
{
2022-09-19 21:46:47 +00:00
return fmax ( fmin ( _val , _max ) , _min ) ;
2022-09-18 15:37:21 +00:00
}
2022-09-19 21:46:47 +00:00
void interactWithTouchScreen ( bool reset , ovrInputStateTrackedRemote * newState , ovrInputStateTrackedRemote * oldState ) {
2022-09-18 15:37:21 +00:00
2022-10-04 21:48:30 +00:00
static float centerYaw = 0 ;
2022-10-05 20:54:36 +00:00
if ( reset | | Q_isnan ( centerYaw ) | | fabs ( sinf ( DEG2RAD ( vr . weaponangles [ YAW ] - centerYaw ) ) ) > 0.9f )
2022-10-04 21:48:30 +00:00
{
centerYaw = vr . weaponangles [ YAW ] ;
}
float cursorX = - sinf ( DEG2RAD ( vr . weaponangles [ YAW ] - centerYaw ) ) + 0.5f ;
2022-09-23 22:10:32 +00:00
float cursorY = ( float ) ( vr . weaponangles [ PITCH ] / 90.0 ) + 0.5f ;
2022-09-18 15:37:21 +00:00
PortableMouseAbs ( cursorX , cursorY ) ;
2022-12-04 11:46:32 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
ovrMatrix4f
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
ovrMatrix4f ovrMatrix4f_CreateProjectionFov (
const float angleLeft ,
const float angleRight ,
const float angleUp ,
const float angleDown ,
const float nearZ ,
const float farZ ) {
const float tanAngleLeft = tanf ( angleLeft ) ;
const float tanAngleRight = tanf ( angleRight ) ;
const float tanAngleDown = tanf ( angleDown ) ;
const float tanAngleUp = tanf ( angleUp ) ;
const float tanAngleWidth = tanAngleRight - tanAngleLeft ;
// Set to tanAngleDown - tanAngleUp for a clip space with positive Y
// down (Vulkan). Set to tanAngleUp - tanAngleDown for a clip space with
// positive Y up (OpenGL / D3D / Metal).
const float tanAngleHeight = tanAngleUp - tanAngleDown ;
// Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
// Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
const float offsetZ = nearZ ;
ovrMatrix4f result ;
if ( farZ < = nearZ ) {
// place the far plane at infinity
result . M [ 0 ] [ 0 ] = 2 / tanAngleWidth ;
result . M [ 0 ] [ 1 ] = 0 ;
result . M [ 0 ] [ 2 ] = ( tanAngleRight + tanAngleLeft ) / tanAngleWidth ;
result . M [ 0 ] [ 3 ] = 0 ;
result . M [ 1 ] [ 0 ] = 0 ;
result . M [ 1 ] [ 1 ] = 2 / tanAngleHeight ;
result . M [ 1 ] [ 2 ] = ( tanAngleUp + tanAngleDown ) / tanAngleHeight ;
result . M [ 1 ] [ 3 ] = 0 ;
result . M [ 2 ] [ 0 ] = 0 ;
result . M [ 2 ] [ 1 ] = 0 ;
result . M [ 2 ] [ 2 ] = - 1 ;
result . M [ 2 ] [ 3 ] = - ( nearZ + offsetZ ) ;
result . M [ 3 ] [ 0 ] = 0 ;
result . M [ 3 ] [ 1 ] = 0 ;
result . M [ 3 ] [ 2 ] = - 1 ;
result . M [ 3 ] [ 3 ] = 0 ;
} else {
// normal projection
result . M [ 0 ] [ 0 ] = 2 / tanAngleWidth ;
result . M [ 0 ] [ 1 ] = 0 ;
result . M [ 0 ] [ 2 ] = ( tanAngleRight + tanAngleLeft ) / tanAngleWidth ;
result . M [ 0 ] [ 3 ] = 0 ;
result . M [ 1 ] [ 0 ] = 0 ;
result . M [ 1 ] [ 1 ] = 2 / tanAngleHeight ;
result . M [ 1 ] [ 2 ] = ( tanAngleUp + tanAngleDown ) / tanAngleHeight ;
result . M [ 1 ] [ 3 ] = 0 ;
result . M [ 2 ] [ 0 ] = 0 ;
result . M [ 2 ] [ 1 ] = 0 ;
result . M [ 2 ] [ 2 ] = - ( farZ + offsetZ ) / ( farZ - nearZ ) ;
result . M [ 2 ] [ 3 ] = - ( farZ * ( nearZ + offsetZ ) ) / ( farZ - nearZ ) ;
result . M [ 3 ] [ 0 ] = 0 ;
result . M [ 3 ] [ 1 ] = 0 ;
result . M [ 3 ] [ 2 ] = - 1 ;
result . M [ 3 ] [ 3 ] = 0 ;
}
return result ;
}
ovrMatrix4f ovrMatrix4f_CreateFromQuaternion ( const XrQuaternionf * q ) {
const float ww = q - > w * q - > w ;
const float xx = q - > x * q - > x ;
const float yy = q - > y * q - > y ;
const float zz = q - > z * q - > z ;
ovrMatrix4f out ;
out . M [ 0 ] [ 0 ] = ww + xx - yy - zz ;
out . M [ 0 ] [ 1 ] = 2 * ( q - > x * q - > y - q - > w * q - > z ) ;
out . M [ 0 ] [ 2 ] = 2 * ( q - > x * q - > z + q - > w * q - > y ) ;
out . M [ 0 ] [ 3 ] = 0 ;
out . M [ 1 ] [ 0 ] = 2 * ( q - > x * q - > y + q - > w * q - > z ) ;
out . M [ 1 ] [ 1 ] = ww - xx + yy - zz ;
out . M [ 1 ] [ 2 ] = 2 * ( q - > y * q - > z - q - > w * q - > x ) ;
out . M [ 1 ] [ 3 ] = 0 ;
out . M [ 2 ] [ 0 ] = 2 * ( q - > x * q - > z - q - > w * q - > y ) ;
out . M [ 2 ] [ 1 ] = 2 * ( q - > y * q - > z + q - > w * q - > x ) ;
out . M [ 2 ] [ 2 ] = ww - xx - yy + zz ;
out . M [ 2 ] [ 3 ] = 0 ;
out . M [ 3 ] [ 0 ] = 0 ;
out . M [ 3 ] [ 1 ] = 0 ;
out . M [ 3 ] [ 2 ] = 0 ;
out . M [ 3 ] [ 3 ] = 1 ;
return out ;
}
/// Use left-multiplication to accumulate transformations.
ovrMatrix4f ovrMatrix4f_Multiply ( const ovrMatrix4f * a , const ovrMatrix4f * b ) {
ovrMatrix4f out ;
out . M [ 0 ] [ 0 ] = a - > M [ 0 ] [ 0 ] * b - > M [ 0 ] [ 0 ] + a - > M [ 0 ] [ 1 ] * b - > M [ 1 ] [ 0 ] + a - > M [ 0 ] [ 2 ] * b - > M [ 2 ] [ 0 ] +
a - > M [ 0 ] [ 3 ] * b - > M [ 3 ] [ 0 ] ;
out . M [ 1 ] [ 0 ] = a - > M [ 1 ] [ 0 ] * b - > M [ 0 ] [ 0 ] + a - > M [ 1 ] [ 1 ] * b - > M [ 1 ] [ 0 ] + a - > M [ 1 ] [ 2 ] * b - > M [ 2 ] [ 0 ] +
a - > M [ 1 ] [ 3 ] * b - > M [ 3 ] [ 0 ] ;
out . M [ 2 ] [ 0 ] = a - > M [ 2 ] [ 0 ] * b - > M [ 0 ] [ 0 ] + a - > M [ 2 ] [ 1 ] * b - > M [ 1 ] [ 0 ] + a - > M [ 2 ] [ 2 ] * b - > M [ 2 ] [ 0 ] +
a - > M [ 2 ] [ 3 ] * b - > M [ 3 ] [ 0 ] ;
out . M [ 3 ] [ 0 ] = a - > M [ 3 ] [ 0 ] * b - > M [ 0 ] [ 0 ] + a - > M [ 3 ] [ 1 ] * b - > M [ 1 ] [ 0 ] + a - > M [ 3 ] [ 2 ] * b - > M [ 2 ] [ 0 ] +
a - > M [ 3 ] [ 3 ] * b - > M [ 3 ] [ 0 ] ;
out . M [ 0 ] [ 1 ] = a - > M [ 0 ] [ 0 ] * b - > M [ 0 ] [ 1 ] + a - > M [ 0 ] [ 1 ] * b - > M [ 1 ] [ 1 ] + a - > M [ 0 ] [ 2 ] * b - > M [ 2 ] [ 1 ] +
a - > M [ 0 ] [ 3 ] * b - > M [ 3 ] [ 1 ] ;
out . M [ 1 ] [ 1 ] = a - > M [ 1 ] [ 0 ] * b - > M [ 0 ] [ 1 ] + a - > M [ 1 ] [ 1 ] * b - > M [ 1 ] [ 1 ] + a - > M [ 1 ] [ 2 ] * b - > M [ 2 ] [ 1 ] +
a - > M [ 1 ] [ 3 ] * b - > M [ 3 ] [ 1 ] ;
out . M [ 2 ] [ 1 ] = a - > M [ 2 ] [ 0 ] * b - > M [ 0 ] [ 1 ] + a - > M [ 2 ] [ 1 ] * b - > M [ 1 ] [ 1 ] + a - > M [ 2 ] [ 2 ] * b - > M [ 2 ] [ 1 ] +
a - > M [ 2 ] [ 3 ] * b - > M [ 3 ] [ 1 ] ;
out . M [ 3 ] [ 1 ] = a - > M [ 3 ] [ 0 ] * b - > M [ 0 ] [ 1 ] + a - > M [ 3 ] [ 1 ] * b - > M [ 1 ] [ 1 ] + a - > M [ 3 ] [ 2 ] * b - > M [ 2 ] [ 1 ] +
a - > M [ 3 ] [ 3 ] * b - > M [ 3 ] [ 1 ] ;
out . M [ 0 ] [ 2 ] = a - > M [ 0 ] [ 0 ] * b - > M [ 0 ] [ 2 ] + a - > M [ 0 ] [ 1 ] * b - > M [ 1 ] [ 2 ] + a - > M [ 0 ] [ 2 ] * b - > M [ 2 ] [ 2 ] +
a - > M [ 0 ] [ 3 ] * b - > M [ 3 ] [ 2 ] ;
out . M [ 1 ] [ 2 ] = a - > M [ 1 ] [ 0 ] * b - > M [ 0 ] [ 2 ] + a - > M [ 1 ] [ 1 ] * b - > M [ 1 ] [ 2 ] + a - > M [ 1 ] [ 2 ] * b - > M [ 2 ] [ 2 ] +
a - > M [ 1 ] [ 3 ] * b - > M [ 3 ] [ 2 ] ;
out . M [ 2 ] [ 2 ] = a - > M [ 2 ] [ 0 ] * b - > M [ 0 ] [ 2 ] + a - > M [ 2 ] [ 1 ] * b - > M [ 1 ] [ 2 ] + a - > M [ 2 ] [ 2 ] * b - > M [ 2 ] [ 2 ] +
a - > M [ 2 ] [ 3 ] * b - > M [ 3 ] [ 2 ] ;
out . M [ 3 ] [ 2 ] = a - > M [ 3 ] [ 0 ] * b - > M [ 0 ] [ 2 ] + a - > M [ 3 ] [ 1 ] * b - > M [ 1 ] [ 2 ] + a - > M [ 3 ] [ 2 ] * b - > M [ 2 ] [ 2 ] +
a - > M [ 3 ] [ 3 ] * b - > M [ 3 ] [ 2 ] ;
out . M [ 0 ] [ 3 ] = a - > M [ 0 ] [ 0 ] * b - > M [ 0 ] [ 3 ] + a - > M [ 0 ] [ 1 ] * b - > M [ 1 ] [ 3 ] + a - > M [ 0 ] [ 2 ] * b - > M [ 2 ] [ 3 ] +
a - > M [ 0 ] [ 3 ] * b - > M [ 3 ] [ 3 ] ;
out . M [ 1 ] [ 3 ] = a - > M [ 1 ] [ 0 ] * b - > M [ 0 ] [ 3 ] + a - > M [ 1 ] [ 1 ] * b - > M [ 1 ] [ 3 ] + a - > M [ 1 ] [ 2 ] * b - > M [ 2 ] [ 3 ] +
a - > M [ 1 ] [ 3 ] * b - > M [ 3 ] [ 3 ] ;
out . M [ 2 ] [ 3 ] = a - > M [ 2 ] [ 0 ] * b - > M [ 0 ] [ 3 ] + a - > M [ 2 ] [ 1 ] * b - > M [ 1 ] [ 3 ] + a - > M [ 2 ] [ 2 ] * b - > M [ 2 ] [ 3 ] +
a - > M [ 2 ] [ 3 ] * b - > M [ 3 ] [ 3 ] ;
out . M [ 3 ] [ 3 ] = a - > M [ 3 ] [ 0 ] * b - > M [ 0 ] [ 3 ] + a - > M [ 3 ] [ 1 ] * b - > M [ 1 ] [ 3 ] + a - > M [ 3 ] [ 2 ] * b - > M [ 2 ] [ 3 ] +
a - > M [ 3 ] [ 3 ] * b - > M [ 3 ] [ 3 ] ;
return out ;
}
ovrMatrix4f ovrMatrix4f_CreateRotation ( const float radiansX , const float radiansY , const float radiansZ ) {
const float sinX = sinf ( radiansX ) ;
const float cosX = cosf ( radiansX ) ;
const ovrMatrix4f rotationX = {
{ { 1 , 0 , 0 , 0 } , { 0 , cosX , - sinX , 0 } , { 0 , sinX , cosX , 0 } , { 0 , 0 , 0 , 1 } } } ;
const float sinY = sinf ( radiansY ) ;
const float cosY = cosf ( radiansY ) ;
const ovrMatrix4f rotationY = {
{ { cosY , 0 , sinY , 0 } , { 0 , 1 , 0 , 0 } , { - sinY , 0 , cosY , 0 } , { 0 , 0 , 0 , 1 } } } ;
const float sinZ = sinf ( radiansZ ) ;
const float cosZ = cosf ( radiansZ ) ;
const ovrMatrix4f rotationZ = {
{ { cosZ , - sinZ , 0 , 0 } , { sinZ , cosZ , 0 , 0 } , { 0 , 0 , 1 , 0 } , { 0 , 0 , 0 , 1 } } } ;
const ovrMatrix4f rotationXY = ovrMatrix4f_Multiply ( & rotationY , & rotationX ) ;
return ovrMatrix4f_Multiply ( & rotationZ , & rotationXY ) ;
}
XrVector4f XrVector4f_MultiplyMatrix4f ( const ovrMatrix4f * a , const XrVector4f * v ) {
XrVector4f out ;
out . x = a - > M [ 0 ] [ 0 ] * v - > x + a - > M [ 0 ] [ 1 ] * v - > y + a - > M [ 0 ] [ 2 ] * v - > z + a - > M [ 0 ] [ 3 ] * v - > w ;
out . y = a - > M [ 1 ] [ 0 ] * v - > x + a - > M [ 1 ] [ 1 ] * v - > y + a - > M [ 1 ] [ 2 ] * v - > z + a - > M [ 1 ] [ 3 ] * v - > w ;
out . z = a - > M [ 2 ] [ 0 ] * v - > x + a - > M [ 2 ] [ 1 ] * v - > y + a - > M [ 2 ] [ 2 ] * v - > z + a - > M [ 2 ] [ 3 ] * v - > w ;
out . w = a - > M [ 3 ] [ 0 ] * v - > x + a - > M [ 3 ] [ 1 ] * v - > y + a - > M [ 3 ] [ 2 ] * v - > z + a - > M [ 3 ] [ 3 ] * v - > w ;
return out ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
ovrTrackedController
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void ovrTrackedController_Clear ( ovrTrackedController * controller ) {
controller - > Active = false ;
controller - > Pose = XrPosef_Identity ( ) ;
}