#include #include #include #include #include "VrInput.h" #include "VrCvars.h" #include #include #ifdef JK2_MODE #include "game/weapons.h" #else #include "game/weapons.h" #include "game/g_vehicles.h" #endif /* ================================================================================ JKXR Stuff ================================================================================ */ bool VR_UseScreenLayer() { vr.using_screen_layer = _UI_IsFullscreen() || (bool)((vr.cin_camera && !vr.immersive_cinematics) || vr.misc_camera || (CL_IsRunningInGameCinematic() || CL_InGameCinematicOnStandBy()) || (cls.state == CA_CINEMATIC) || (cls.state == CA_LOADING) || ( Key_GetCatcher( ) & KEYCATCH_UI ) || ( Key_GetCatcher( ) & KEYCATCH_CONSOLE )); return vr.using_screen_layer; } float VR_GetScreenLayerDistance() { return (2.0f + vr_screen_dist->value); } void VR_SetHMDOrientation(float pitch, float yaw, float roll) { //Orientation VectorSet(vr.hmdorientation, pitch, yaw, roll); VectorSubtract(vr.hmdorientation_last, vr.hmdorientation, vr.hmdorientation_delta); //Keep this for our records VectorCopy(vr.hmdorientation, vr.hmdorientation_last); if (!vr.third_person && !vr.remote_npc && !vr.remote_turret #ifndef JK2_MODE && !vr.in_vehicle #endif ) { VectorCopy(vr.hmdorientation, vr.hmdorientation_first); } if (!vr.remote_turret) { VectorCopy(vr.weaponangles[ANGLES_ADJUSTED], vr.weaponangles_first[ANGLES_ADJUSTED]); } // View yaw delta float clientview_yaw = vr.clientviewangles[YAW] - vr.hmdorientation[YAW]; vr.clientview_yaw_delta = vr.clientview_yaw_last - clientview_yaw; vr.clientview_yaw_last = clientview_yaw; // Max-height is set only once on start, or after re-calibration // (ignore too low value which is sometimes provided on start) if (!vr.maxHeight || vr.maxHeight < 1.0) { vr.maxHeight = vr.hmdposition[1]; } //GB Instantiate initial velocity if(!vr.tempWeaponVelocity) { vr.tempWeaponVelocity = 400.0f; } vr.curHeight = vr.hmdposition[1]; } void VR_SetHMDPosition(float x, float y, float z ) { static bool s_useScreen = qfalse; VectorSet(vr.hmdposition, x, y, z); //Can be set elsewhere vr.take_snap |= s_useScreen != VR_UseScreenLayer(); if (vr.take_snap) { s_useScreen = VR_UseScreenLayer(); //Record player position on transition VectorSet(vr.hmdposition_snap, x, y, z); VectorCopy(vr.hmdorientation, vr.hmdorientation_snap); if (vr.cin_camera) { //Reset snap turn too if in a cinematic vr.snapTurn = 0; } vr.take_snap = false; } VectorSubtract(vr.hmdposition, vr.hmdposition_snap, vr.hmdposition_offset); //Position VectorSubtract(vr.hmdposition_last, vr.hmdposition, vr.hmdposition_delta); //Keep this for our records VectorCopy(vr.hmdposition, vr.hmdposition_last); } void VR_GetMove(float *forward, float *side, float *pos_forward, float *pos_side, float *up, float *yaw, float *pitch, float *roll) { if (vr.remote_turret) { *forward = 0.0f; *pos_forward = 0.0f; *up = 0.0f; *side = 0.0f; *pos_side = 0.0f; *yaw = vr.snapTurn + vr.hmdorientation_first[YAW] + vr.weaponangles[ANGLES_ADJUSTED][YAW] - vr.weaponangles_first[ANGLES_ADJUSTED][YAW]; *pitch = vr.weaponangles[ANGLES_ADJUSTED][PITCH]; *roll = 0.0f; } else if (vr.cgzoommode == 2 || vr.cgzoommode == 4) { *forward = 0.0f; *pos_forward = 0.0f; *up = 0.0f; *side = 0.0f; *pos_side = 0.0f; *yaw = vr.snapTurn; *pitch = vr.weaponangles[ANGLES_ADJUSTED][PITCH]; *roll = 0.0f;//vr.hmdorientation[ROLL]; } else if (vr.remote_npc) { *forward = remote_movementForward; *pos_forward = 0.0f; *up = 0.0f; *side = remote_movementSideways; *pos_side = 0.0f; *yaw = vr.hmdorientation[YAW] + vr.snapTurn; *pitch = vr.hmdorientation[PITCH]; *roll = 0.0f; } #ifndef JK2_MODE //Special code for JKA's vehicles else if (vr.in_vehicle) { //in vehicle *forward = remote_movementForward; *pos_forward = 0.0f; *up = 0.0f; *side = remote_movementSideways; *pos_side = 0.0f; if (vr_vehicle_use_hmd_direction->integer) { *yaw = vr.hmdorientation[YAW] + vr.snapTurn; *pitch = vr.hmdorientation[PITCH]; } else { *yaw = vr.snapTurn + vr.hmdorientation_first[YAW]; if (vr.vehicle_type == VH_FIGHTER || vr.vehicle_type == VH_FLIER) { *pitch = (vr.weaponangles[ANGLES_ADJUSTED][PITCH] + vr.offhandangles[ANGLES_ADJUSTED][PITCH]) / 2.0f; } else { *pitch = 0.0f; } } *roll = 0.0f; } #endif else if (!vr.third_person) { *forward = remote_movementForward; *pos_forward = positional_movementForward; *up = remote_movementUp; *side = remote_movementSideways; *pos_side = positional_movementSideways; *yaw = vr.hmdorientation[YAW] + vr.snapTurn; *pitch = vr.hmdorientation[PITCH]; *roll = 0.0f;//vr.hmdorientation[ROLL]; } else { //in third person just send the bare minimum *forward = remote_movementForward; *pos_forward = 0.0f; *up = 0.0f; *side = remote_movementSideways; *pos_side = 0.0f; *yaw = vr.snapTurn + vr.hmdorientation_first[YAW]; *pitch = 0.0f; *roll = 0.0f; } } void VR_Init() { GlInitExtensions(); //First - all the OpenXR stuff and nonsense TBXR_InitialiseOpenXR(); TBXR_EnterVR(); TBXR_InitRenderer(); TBXR_InitActions(); TBXR_WaitForSessionActive(); //Initialise all our variables remote_movementSideways = 0.0f; remote_movementForward = 0.0f; remote_movementUp = 0.0f; positional_movementSideways = 0.0f; positional_movementForward = 0.0f; vr.snapTurn = 0.0f; vr.immersive_cinematics = true; vr.move_speed = 1; // Default to full speed now //init randomiser srand(time(NULL)); //Create Cvars vr_turn_mode = Cvar_Get( "vr_turn_mode", "0", CVAR_ARCHIVE); // 0 = snap, 1 = smooth (3rd person only), 2 = smooth (all modes) vr_turn_angle = Cvar_Get( "vr_turn_angle", "45", CVAR_ARCHIVE); vr_positional_factor = Cvar_Get( "vr_positional_factor", "12", CVAR_ARCHIVE); vr_walkdirection = Cvar_Get( "vr_walkdirection", "1", CVAR_ARCHIVE); vr_weapon_pitchadjust = Cvar_Get( "vr_weapon_pitchadjust", "-20.0", CVAR_ARCHIVE); vr_saber_pitchadjust = Cvar_Get( "vr_saber_pitchadjust", "-20.0", CVAR_ARCHIVE); vr_virtual_stock = Cvar_Get( "vr_virtual_stock", "0", CVAR_ARCHIVE); //Defaults vr_control_scheme = Cvar_Get( "vr_control_scheme", "0", CVAR_ARCHIVE); vr_switch_sticks = Cvar_Get( "vr_switch_sticks", "0", CVAR_ARCHIVE); vr_immersive_cinematics = Cvar_Get("vr_immersive_cinematics", "1", CVAR_ARCHIVE); vr_screen_dist = Cvar_Get( "vr_screen_dist", "3.5", CVAR_ARCHIVE); vr_weapon_velocity_trigger = Cvar_Get( "vr_weapon_velocity_trigger", "2.0", CVAR_ARCHIVE); vr_force_velocity_trigger = Cvar_Get( "vr_force_velocity_trigger", "2.09", CVAR_ARCHIVE); vr_force_distance_trigger = Cvar_Get( "vr_force_distance_trigger", "0.15", CVAR_ARCHIVE); vr_two_handed_weapons = Cvar_Get ("vr_two_handed_weapons", "1", CVAR_ARCHIVE); vr_force_motion_controlled = Cvar_Get ("vr_force_motion_controlled", "1", CVAR_ARCHIVE); vr_force_motion_push = Cvar_Get ("vr_force_motion_push", "3", CVAR_ARCHIVE); vr_force_motion_pull = Cvar_Get ("vr_force_motion_pull", "4", CVAR_ARCHIVE); vr_motion_enable_saber = Cvar_Get ("vr_motion_enable_saber", "0", CVAR_ARCHIVE); vr_crouch_toggle = Cvar_Get ("vr_crouch_toggle", "0", CVAR_ARCHIVE); vr_irl_crouch_enabled = Cvar_Get ("vr_irl_crouch_enabled", "0", CVAR_ARCHIVE); vr_irl_crouch_to_stand_ratio = Cvar_Get ("vr_irl_crouch_to_stand_ratio", "0.65", CVAR_ARCHIVE); vr_saber_block_debounce_time = Cvar_Get ("vr_saber_block_debounce_time", "200", CVAR_ARCHIVE); vr_haptic_intensity = Cvar_Get ("vr_haptic_intensity", "1.0", CVAR_ARCHIVE); vr_comfort_vignette = Cvar_Get ("vr_comfort_vignette", "0.0", CVAR_ARCHIVE); vr_saber_3rdperson_mode = Cvar_Get ("vr_saber_3rdperson_mode", "1", CVAR_ARCHIVE); vr_vehicle_use_hmd_direction = Cvar_Get ("vr_vehicle_use_hmd_direction", "0", CVAR_ARCHIVE); vr_vehicle_use_3rd_person = Cvar_Get ("vr_vehicle_use_3rd_person", "0", CVAR_ARCHIVE); vr_vehicle_use_controller_for_speed = Cvar_Get ("vr_vehicle_use_controller_for_speed", "1", CVAR_ARCHIVE); vr_gesture_triggered_use = Cvar_Get ("vr_gesture_triggered_use", "1", CVAR_ARCHIVE); vr_use_gesture_boundary = Cvar_Get ("vr_use_gesture_boundary", "0.35", CVAR_ARCHIVE); vr_align_weapons = Cvar_Get ("vr_align_weapons", "0", CVAR_ARCHIVE); vr_refresh = Cvar_Get ("vr_refresh", "72", CVAR_ARCHIVE); cvar_t *expanded_menu_enabled = Cvar_Get ("expanded_menu_enabled", "0", CVAR_ARCHIVE); if (FS_FileExists("expanded_menu.pk3") || FS_BaseFileExists("expanded_menu.pk3")) { Cvar_Set( "expanded_menu_enabled", "1" ); } else { Cvar_Set( "expanded_menu_enabled", "0" ); } vr.menu_right_handed = vr_control_scheme->integer == 0; } int VR_SetRefreshRate(int refreshRate) { return 0; } //All the stuff we want to do each frame specifically for this game void VR_FrameSetup() { static float refresh = 0; if (refresh != vr_refresh->value) { refresh = vr_refresh->value; VR_SetRefreshRate(vr_refresh->value); } //get any cvar values required here vr.immersive_cinematics = (vr_immersive_cinematics->value != 0.0f); } bool VR_GetVRProjection(int eye, float zNear, float zFar, float zZoomX, float zZoomY, float* projection) { //Don't use our projection if playing a cinematic and we are not immersive if (vr.cin_camera && !vr.immersive_cinematics) { return false; } //Just use game-calculated FOV when showing the quad screen if (vr.using_screen_layer) { return false; } XrFovf fov = gAppState.Views[eye].fov; fov.angleLeft = atanf((tanf(fov.angleLeft) / zZoomX)); fov.angleRight = atanf((tanf(fov.angleRight) / zZoomX)); fov.angleUp = atanf((tanf(fov.angleUp) / zZoomY)); fov.angleDown = atanf((tanf(fov.angleDown) / zZoomY)); XrMatrix4x4f_CreateProjectionFov( (XrMatrix4x4f*)projection, GRAPHICS_OPENGL, fov, zNear, zFar); return true; } void VR_ExternalHapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight ) { } void VR_HapticUpdateEvent(const char* event, int intensity, float angle ) { } void VR_HapticEndFrame() { } void VR_HapticStopEvent(const char* event) { } void VR_HapticEnable() { } void VR_HapticDisable() { } /* * event - name of event * position - for the use of external haptics providers to indicate which bit of haptic hardware should be triggered * flags - a way for the code to specify which controller to produce haptics on, if 0 then weaponFireChannel is calculated in this function * intensity - 0-100 * angle - yaw angle (again for external haptics devices) to place the feedback correctly * yHeight - for external haptics devices to place the feedback correctly */ void VR_HapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight ) { if (vr_haptic_intensity->value == 0.0f) { return; } //Pass on to any external services VR_ExternalHapticEvent(event, position, flags, intensity, angle, yHeight); float fIntensity = intensity / 100.0f; //Controller Haptic Support int weaponFireChannel = vr.weapon_stabilised ? 3 : (vr_control_scheme->integer ? 2 : 1); if (flags != 0) { weaponFireChannel = flags; } if (strcmp(event, "pickup_shield") == 0 || strcmp(event, "pickup_weapon") == 0 || strstr(event, "pickup_item") != NULL) { TBXR_Vibrate(100, 3, 1.0); } else if (strcmp(event, "weapon_switch") == 0) { TBXR_Vibrate(250, vr_control_scheme->integer ? 2 : 1, 0.8); } else if (strcmp(event, "shotgun") == 0 || strcmp(event, "fireball") == 0) { TBXR_Vibrate(400, 3, fIntensity); } else if (strcmp(event, "bullet") == 0) { TBXR_Vibrate(150, 3, fIntensity); } else if (strcmp(event, "chainsaw_fire") == 0) // Saber { //Special handling for dual sabers / melee if (vr.dualsabers || cl.frame.ps.weapon == WP_MELEE) { if (position == 4 || position == 0) // both hands { weaponFireChannel = 3; } else if (position == 1) // left hand { weaponFireChannel = 2; } else if (position == 2) // right hand { weaponFireChannel = 1; } else { //no longer need to trigger haptic return; } } TBXR_Vibrate(300, weaponFireChannel, fIntensity); } else if (strcmp(event, "RTCWQuest:fire_tesla") == 0) // Weapon power build up { TBXR_Vibrate(500, weaponFireChannel, fIntensity); } else if (strcmp(event, "machinegun_fire") == 0 || strcmp(event, "plasmagun_fire") == 0) { TBXR_Vibrate(90, weaponFireChannel, fIntensity); } else if (strcmp(event, "shotgun_fire") == 0) { TBXR_Vibrate(250, weaponFireChannel, fIntensity); } else if (strcmp(event, "rocket_fire") == 0 || strcmp(event, "RTCWQuest:fire_sniper") == 0 || strcmp(event, "bfg_fire") == 0 || strcmp(event, "handgrenade_fire") == 0 ) { TBXR_Vibrate(400, weaponFireChannel, fIntensity); } else if (strcmp(event, "selector_icon") == 0 || strcmp(event, "use_button") == 0 ) { //Quick blip TBXR_Vibrate(50, flags, fIntensity); } } void VR_HandleControllerInput() { TBXR_UpdateControllers(); //Call additional control schemes here switch (vr_control_scheme->integer) { case RIGHT_HANDED_DEFAULT: HandleInput_Default(&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: HandleInput_Default(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new, &rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new, xrButton_X, xrButton_Y, xrButton_A, xrButton_B); break; case WEAPON_ALIGN: HandleInput_WeaponAlign(&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new, &leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new, xrButton_A, xrButton_B, xrButton_X, xrButton_Y); break; } }