Lots of good stuff..

- Multiplayer 6DoF can be disabled setting vr_mp6DoF to 0 (will use a 3DoF scheme instead)
- Cross hair now correctly aligned with weapon aiming when playing on a swerver
- "Use Item" is not a right thumbstick click
- B button will perform crouch in single player or skirmish
- B button will realign the weapon with the controller when playing on a server
This commit is contained in:
Simon 2022-02-10 23:28:34 +00:00
parent 49b8ba1f43
commit f5bced0623
10 changed files with 109 additions and 45 deletions

View file

@ -3,7 +3,7 @@
package="com.drbeef.ioq3quest"
android:installLocation="preferExternal"
android:versionCode="13"
android:versionName="0.8.1">
android:versionName="0.9.0">
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1" android:required="true" />
<uses-feature android:glEsVersion="0x00030001" />

View file

@ -1992,7 +1992,7 @@ static void CG_DrawCrosshair3D(void)
vec3_t viewaxis[3];
vec3_t weaponangles;
vec3_t origin;
CG_CalculateVRWeaponPosition(origin, weaponangles);
CG_CalculateVRWeaponPosition(origin, weaponangles, qtrue);
AnglesToAxis(weaponangles, viewaxis);
maxdist = cgs.glconfig.vidWidth * stereoSep * zProj / (2 * xmax);
VectorMA(origin, maxdist, viewaxis[0], endpos);
@ -2679,21 +2679,26 @@ void CG_DrawActive( stereoFrame_t stereoView ) {
float ipd = trap_Cvar_VariableValue("r_stereoSeparation") / 1000.0f;
float separation = stereoView == STEREO_LEFT ?
worldscale * (-ipd / 2) : //left
worldscale * (ipd / 2); // right
float separation = worldscale * (ipd / 2) * (stereoView == STEREO_LEFT ? -1.0f : 1.0f);
cg.refdef.vieworg[2] -= PLAYER_HEIGHT;
cg.refdef.vieworg[2] += vr->hmdposition[1] * worldscale;
//If connected to external server, allow some amount of faked positional tracking
float sv_running = trap_Cvar_VariableValue("sv_running");
if ( sv_running == 0.0f && ( cg.snap->ps.stats[STAT_HEALTH] > 0 )) {
vec3_t pos;
VectorClear(pos);
rotateAboutOrigin(vr->hmdposition[2], vr->hmdposition[0], cg.refdefViewAngles[YAW] - vr->weaponangles[YAW], pos);
VectorScale(pos, worldscale, pos);
VectorSubtract(cg.refdef.vieworg, pos, cg.refdef.vieworg);
if (cgs.localServer) {
cg.refdef.vieworg[2] -= PLAYER_HEIGHT;
cg.refdef.vieworg[2] += vr->hmdposition[1] * worldscale;
}
else if (trap_Cvar_VariableValue("vr_mp6DoF") == 1.0f)
{
//If connected to external server, allow some amount of faked positional tracking
cg.refdef.vieworg[2] -= PLAYER_HEIGHT;
cg.refdef.vieworg[2] += vr->hmdposition[1] * worldscale;
if (cg.snap->ps.stats[STAT_HEALTH] > 0)
{
vec3_t pos;
VectorClear(pos);
rotateAboutOrigin(vr->hmdposition[2], vr->hmdposition[0],
cg.refdefViewAngles[YAW] - vr->weaponangles[YAW], pos);
VectorScale(pos, worldscale, pos);
VectorSubtract(cg.refdef.vieworg, pos, cg.refdef.vieworg);
}
}
VectorMA(cg.refdef.vieworg, -separation, cg.refdef.viewaxis[1], cg.refdef.vieworg);

View file

@ -988,7 +988,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
if(es->clientNum == cg.snap->ps.clientNum && !cg.renderingThirdPerson)
{
vec3_t angles;
CG_CalculateVRWeaponPosition(es->origin2, angles);
CG_CalculateVRWeaponPosition(es->origin2, angles, qfalse);
/*
if(cg_drawGun.integer == 2)
VectorMA(es->origin2, 8, cg.refdef.viewaxis[1], es->origin2);

View file

@ -1369,7 +1369,7 @@ void CG_PrevWeapon_f( void );
void CG_Weapon_f( void );
void rotateAboutOrigin(float x, float y, float rotation, vec2_t out);
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles );
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles, qboolean crosshair );
void CG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out);
void CG_RegisterWeapon( int weaponNum );

View file

@ -704,8 +704,7 @@ static int CG_CalcViewValues( void ) {
}
// position eye relative to origin
float sv_running = trap_Cvar_VariableValue("sv_running");
if (sv_running == 0.0f )
if (!cgs.localServer)
{
//We are connected to a multiplayer server, so make the appropriate adjustment to the view
//angles as we send orientation to the server that includes the weapon angles

View file

@ -230,8 +230,7 @@ void CG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out)
VectorSet(vrSpace, in[2], in[0], in[1] );
vec2_t r;
float sv_running = trap_Cvar_VariableValue("sv_running");
if (sv_running == 0.0f )
if (!cgs.localServer)
{
//We are connected to a multiplayer server, so make the appropriate adjustment to the view
//angles as we send orientation to the server that includes the weapon angles
@ -254,29 +253,50 @@ void CG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out)
}
}
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles )
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles, qboolean crosshair )
{
qboolean localServer = trap_Cvar_VariableValue("sv_running") != 0;
float worldscale = trap_Cvar_VariableValue("vr_worldscale");
if (!localServer)
if (!cgs.localServer)
{
vec3_t offset;
VectorCopy(vr->weaponposition, offset);
offset[1] = vr->weaponoffset[1]; // up/down is index 1 in this case
CG_ConvertFromVR(offset, cg.refdef.vieworg, origin);
if (trap_Cvar_VariableValue("vr_mp6DoF") == 1.0f &&
!crosshair)
{
//Use absolute position for the faked 6DoF for multiplayer
vec3_t offset;
VectorCopy(vr->weaponposition, offset);
offset[1] = vr->weaponoffset[1]; // up/down is index 1 in this case
CG_ConvertFromVR(offset, cg.refdef.vieworg, origin);
origin[2] -= PLAYER_HEIGHT;
origin[2] += vr->hmdposition[1] * worldscale;
}
else
{
vec3_t weaponoffset;
VectorSet(weaponoffset, 0.0f, 0.0f, 0.0f);
//Fixed point
if (!crosshair) {
vec2_t temp;
rotateAboutOrigin(0.25f, -0.25f, -vr->hmdorientation[YAW], temp);
VectorSet(weaponoffset, temp[0], -0.3f, temp[1]);
}
CG_ConvertFromVR(weaponoffset, cg.refdef.vieworg, origin);
}
}
else
{
//Local server - true 6DoF offset from HMD
CG_ConvertFromVR(vr->weaponoffset, cg.refdef.vieworg, origin);
origin[2] -= PLAYER_HEIGHT;
origin[2] += vr->hmdposition[1] * worldscale;
}
float worldscale = trap_Cvar_VariableValue("vr_worldscale");
origin[2] -= PLAYER_HEIGHT;
origin[2] += vr->hmdposition[1] * worldscale;
VectorCopy(vr->weaponangles, angles);
if ( !localServer )
if ( !cgs.localServer )
{
//take player state angles provided by server
angles[YAW] = cg.predictedPlayerState.viewangles[YAW]; //cg.snap->ps.viewangles[YAW];
@ -1290,7 +1310,7 @@ static void CG_LightningBolt( centity_t *cent, vec3_t origin ) {
// CPMA "true" lightning
if ((cent->currentState.number == cg.predictedPlayerState.clientNum) && (cg_trueLightning.value != 0)) {
vec3_t angle;
CG_CalculateVRWeaponPosition(muzzlePoint, angle);
CG_CalculateVRWeaponPosition(muzzlePoint, angle, qfalse);
AngleVectors(angle, forward, NULL, NULL );
} else {
// !CPMA
@ -1648,7 +1668,7 @@ void CG_AddViewWeapon( playerState_t *ps ) {
refEntity_t hand;
centity_t *cent;
clientInfo_t *ci;
float fovOffset;
//float fovOffset;
vec3_t angles;
weaponInfo_t *weapon;
@ -1700,7 +1720,7 @@ void CG_AddViewWeapon( playerState_t *ps ) {
memset (&hand, 0, sizeof(hand));
// set up gun position
CG_CalculateVRWeaponPosition( hand.origin, angles );
CG_CalculateVRWeaponPosition( hand.origin, angles, qfalse );
//Scale / Move gun etc
float scale = 1.0f;
@ -1790,7 +1810,7 @@ void CG_AddViewWeapon( playerState_t *ps ) {
vec3_t endForward, endRight, endUp;
vec3_t _angles;
clientInfo_t ci;
CG_CalculateVRWeaponPosition( _origin, _angles );
CG_CalculateVRWeaponPosition( _origin, _angles, qfalse );
vec3_t forward, right, up;
AngleVectors(_angles, forward, right, up);

View file

@ -596,13 +596,22 @@ void CL_FinishMove( usercmd_t *cmd ) {
//and adjust the move values accordingly, to "fake" a 3DoF weapon but keeping the movement correct
if ( !com_sv_running || !com_sv_running->integer )
{
vr.localServer = qfalse;
vr.clientNum = -1;
vr.local_server = qfalse;
vec3_t angles;
VectorCopy(vr.weaponangles, angles);
angles[ROLL] = 0; // suppress roll
if (vr.realign_weapon)
{
vr.realign_weapon_pitch -= (cl.snap.ps.viewangles[PITCH]-vr.weaponangles[PITCH]) ;
vr.realign_weapon = qfalse;
}
angles[PITCH] += vr.realign_weapon_pitch;
angles[YAW] += (cl.viewangles[YAW] - vr.hmdorientation[YAW]);
angles[ROLL] = 0; // suppress roll
for (i = 0; i < 3; i++) {
cmd->angles[i] = ANGLE2SHORT(angles[i]);
}
@ -613,11 +622,10 @@ void CL_FinishMove( usercmd_t *cmd ) {
cmd->forwardmove = out[1];
}
else {
vr.localServer = qtrue;
//Record client number - local server uses this to know we can use absolute angles
//rather than deltas
vr.clientNum = cl.snap.ps.clientNum;
vr.local_server = qtrue;
for (i = 0; i < 3; i++) {
cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]);

View file

@ -1812,7 +1812,7 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) {
// circularly clamp the angles with deltas
for (i=0 ; i<3 ; i++) {
if (vr != NULL && vr->clientNum == ps->clientNum && vr->localServer)
if (vr != NULL && vr->clientNum == ps->clientNum && vr->local_server)
{
//Client is the VR player on the "local" server
temp = cmd->angles[i] + (i == YAW ? ps->delta_angles[i] : 0);

View file

@ -9,8 +9,11 @@ typedef struct {
qboolean weapon_stabilised;
qboolean right_handed;
qboolean virtual_screen;
qboolean local_server; // used in bg_pmove.c
qboolean realign_weapon; // used to realign the weapon in a multiplayer game
int realign_weapon_pitch; // used to realign the weapon pitch in a multiplayer game
qboolean localServer;
int clientNum;
vec3_t hmdposition;

View file

@ -67,6 +67,7 @@ float degrees(float rad) {
cvar_t *vr_extralatencymode = NULL;
cvar_t *vr_directionMode = NULL;
cvar_t *vr_mp6DoF = NULL;
void rotateAboutOrigin(float x, float y, float rotation, vec2_t out)
{
@ -196,6 +197,9 @@ void IN_VRInit( void )
vr_snapturn = Cvar_Get ("vr_snapturn", "45", CVAR_ARCHIVE);
vr_extralatencymode = Cvar_Get ("vr_extralatencymode", "1", CVAR_ARCHIVE);
vr_directionMode = Cvar_Get ("vr_directionMode", "0", CVAR_ARCHIVE); // 0 = HMD, 1 = Off-hand
vr_mp6DoF = Cvar_Get ("vr_mp6DoF", "1", CVAR_ARCHIVE); // if 0 then multiplayer will use only 3DoF for headset
memset(&vr, 0, sizeof(vr));
}
static void IN_VRController( qboolean isRightController, ovrTracking remoteTracking )
@ -397,11 +401,36 @@ static void IN_VRButtonsChanged( qboolean isRightController, uint32_t buttons )
}
if ((buttons & ovrButton_B) && !(controller->buttons & ovrButton_B)) {
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qtrue, 0, NULL);
if ( !com_sv_running || !com_sv_running->integer )
{
vr.realign_weapon = qtrue;
} else {
Com_QueueEvent(in_vrEventTime, SE_KEY, 'c', qtrue, 0, NULL);
}
} else if (!(buttons & ovrButton_B) && (controller->buttons & ovrButton_B)) {
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qfalse, 0, NULL);
if ( !com_sv_running || !com_sv_running->integer )
{
} else {
Com_QueueEvent(in_vrEventTime, SE_KEY, 'c', qfalse, 0, NULL);
}
}
if (isRightController == (vr_righthanded->integer != 0)) {
//thumbstick is "use item"
if ((buttons & ovrButton_RThumb) && !(controller->buttons & ovrButton_RThumb)) {
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qtrue, 0, NULL);
} else if (!(buttons & ovrButton_RThumb) && (controller->buttons & ovrButton_RThumb)) {
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qfalse, 0, NULL);
}
} else {
//thumbstick is "use item"
if ((buttons & ovrButton_LThumb) && !(controller->buttons & ovrButton_LThumb)) {
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qtrue, 0, NULL);
} else if (!(buttons & ovrButton_LThumb) && (controller->buttons & ovrButton_LThumb)) {
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qfalse, 0, NULL);
}
}
if ((buttons & ovrButton_X) && !(controller->buttons & ovrButton_X)) {
//sendButtonActionSimple("fraglimit 1");
Com_QueueEvent(in_vrEventTime, SE_KEY, K_PAD0_X, qtrue, 0, NULL);