2022-09-18 15:37:21 +00:00
|
|
|
/************************************************************************************
|
|
|
|
|
|
|
|
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;
|
2022-12-14 14:45:51 +00:00
|
|
|
cvar_t *vr_use_gesture_boundary;
|
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;
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|