From 2c9b286da5c6ee16209d3c84dfe6b0e023c363b3 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 3 Feb 2022 21:32:09 +0000 Subject: [PATCH] Several good fixes / improvements - Positional tracking in Death Cam mode (so much nicer now) - All 2D HUD elements now draw in both eyes - HUD elements based on models are now 3D (face etc) - Better 4:3 screen for virtual screen --- code/cgame/cg_draw.c | 8 ++--- code/cgame/cg_drawtools.c | 2 +- code/cgame/cg_local.h | 9 ++++++ code/cgame/cg_view.c | 42 +++++++++++++++++-------- code/cgame/cg_weapons.c | 4 +-- code/renderercommon/tr_public.h | 3 +- code/renderergl2/tr_backend.c | 4 +++ code/renderergl2/tr_cmds.c | 6 ++-- code/renderergl2/tr_local.h | 6 ++-- code/renderergl2/tr_main.c | 3 -- code/vr/vr_base.h | 2 -- code/vr/vr_input.c | 56 ++++++++++++++++++++++++++------- code/vr/vr_renderer.c | 27 ++++++++-------- 13 files changed, 115 insertions(+), 57 deletions(-) diff --git a/code/cgame/cg_draw.c b/code/cgame/cg_draw.c index 07f310d5..a480291b 100644 --- a/code/cgame/cg_draw.c +++ b/code/cgame/cg_draw.c @@ -2670,12 +2670,8 @@ void CG_DrawActive( stereoFrame_t stereoView ) { vec3_t baseOrg; VectorCopy( cg.refdef.vieworg, baseOrg ); - float worldscale = trap_Cvar_VariableValue("vr_worldscale"); - - if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) - { - worldscale *= 50; - } + float worldscale = trap_Cvar_VariableValue("vr_worldscale") * + (( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) ? DEATH_WORLDSCALE_MULTIPLIER : 1.0f); float ipd = 0.065f; float separation = stereoView == STEREO_LEFT ? diff --git a/code/cgame/cg_drawtools.c b/code/cgame/cg_drawtools.c index 2e84685a..5e7ae0ad 100644 --- a/code/cgame/cg_drawtools.c +++ b/code/cgame/cg_drawtools.c @@ -61,7 +61,7 @@ void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) { float screenXScale = cgs.screenXScale / 2.75f; float screenYScale = cgs.screenYScale / 2.25f; - int xoffset = -60; + int xoffset = -120; if (hudStereoView == STEREO_LEFT) { xoffset *= -1; } diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index 17033ce2..6e2c36bb 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -76,6 +76,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define NUM_CROSSHAIRS 10 +//multiplying size you go to when dead looking down on the match +#define DEATH_WORLDSCALE_MULTIPLIER 40 + +#define PLAYER_HEIGHT 48 + #define TEAM_OVERLAY_MAXNAME_WIDTH 12 #define TEAM_OVERLAY_MAXLOCATION_WIDTH 16 @@ -627,6 +632,7 @@ typedef struct { float v_dmg_time; float v_dmg_pitch; float v_dmg_roll; + vec3_t v_death_origin; // temp working variables for player view float bobfracsin; @@ -1362,7 +1368,9 @@ void CG_NextWeapon_f( void ); 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_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out); void CG_RegisterWeapon( int weaponNum ); void CG_RegisterItemVisuals( int itemNum ); @@ -1501,6 +1509,7 @@ void trap_Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *def void trap_Cvar_Update( vmCvar_t *vmCvar ); void trap_Cvar_Set( const char *var_name, const char *value ); void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ); +float trap_Cvar_VariableValue( const char *var_name ); // ServerCommand and ConsoleCommand parameter access int trap_Argc( void ); diff --git a/code/cgame/cg_view.c b/code/cgame/cg_view.c index 599d7b70..8249394a 100644 --- a/code/cgame/cg_view.c +++ b/code/cgame/cg_view.c @@ -23,7 +23,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // cg_view.c -- setup all the parameters (position, angle, etc) // for a 3D rendering #include "cg_local.h" +#include "../vr/vr_clientinfo.h" +extern vr_clientinfo_t* cgVR; /* ============================================================================= @@ -216,6 +218,25 @@ static void CG_CalcVrect (void) { //============================================================================== +/* +=============== +CG_OffsetDeathView + +=============== +*/ +static void CG_OffsetDeathView( void ) { + + vec3_t position_delta; + VectorNegate(cgVR->hmdposition_delta, position_delta); + CG_ConvertFromVR(position_delta, NULL, position_delta); + position_delta[2] = 0; + VectorScale(position_delta, (DEATH_WORLDSCALE_MULTIPLIER / 2), position_delta); + + VectorAdd(cg.v_death_origin, position_delta, cg.v_death_origin); + VectorCopy(cg.v_death_origin, cg.refdef.vieworg); + cg.refdef.vieworg[2] += DEATH_WORLDSCALE_MULTIPLIER * cg.predictedPlayerState.viewheight; +} + /* =============== CG_OffsetThirdPersonView @@ -234,16 +255,12 @@ static void CG_OffsetThirdPersonView( void ) { float focusDist; float forwardScale, sideScale; + VectorCopy(cg.refdef.vieworg, cg.v_death_origin); + cg.refdef.vieworg[2] += cg.predictedPlayerState.viewheight; VectorCopy( cg.refdefViewAngles, focusAngles ); - if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) { - //Be 50 times taller - cg.refdef.vieworg[2] += 50 * cg.predictedPlayerState.viewheight; - return; - } - if ( focusAngles[PITCH] > 45 ) { focusAngles[PITCH] = 45; // don't go too far overhead } @@ -331,11 +348,7 @@ static void CG_OffsetFirstPersonView( void ) { origin = cg.refdef.vieworg; angles = cg.refdefViewAngles; - if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) { - //Be 50 times taller - origin[2] += 50 * cg.predictedPlayerState.viewheight; - return; - } + VectorCopy(cg.refdef.vieworg, cg.v_death_origin); // add angles based on damage kick if ( cg.damageTime ) { @@ -671,7 +684,10 @@ static int CG_CalcViewValues( void ) { } } - if ( cg.renderingThirdPerson ) { + if (cg.snap->ps.stats[STAT_HEALTH] <= 0) { + //If dead, view the map from above + CG_OffsetDeathView(); + } else if ( cg.renderingThirdPerson ) { // back away from character CG_OffsetThirdPersonView(); } else { @@ -799,7 +815,7 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo // decide on third person view cg.renderingThirdPerson = cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR - && (cg_thirdPerson.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0)); + && cg_thirdPerson.integer; // build cg.refdef inwater = CG_CalcViewValues(); diff --git a/code/cgame/cg_weapons.c b/code/cgame/cg_weapons.c index b3460180..c7cbc6d8 100644 --- a/code/cgame/cg_weapons.c +++ b/code/cgame/cg_weapons.c @@ -224,7 +224,7 @@ float trap_Cvar_VariableValue( const char *var_name ) { return atof(buf); } -void convertFromVR(vec3_t in, vec3_t offset, vec3_t out) +void CG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out) { vec3_t vrSpace; VectorSet(vrSpace, in[2], in[0], in[1] ); @@ -247,7 +247,7 @@ void convertFromVR(vec3_t in, vec3_t offset, vec3_t out) void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles ) { - convertFromVR(cgVR->calculated_weaponoffset, cg.refdef.vieworg, origin); + CG_ConvertFromVR(cgVR->calculated_weaponoffset, cg.refdef.vieworg, origin); float worldscale = trap_Cvar_VariableValue("vr_worldscale"); origin[2] -= PLAYER_HEIGHT; diff --git a/code/renderercommon/tr_public.h b/code/renderercommon/tr_public.h index 1fcc355d..1a47364b 100644 --- a/code/renderercommon/tr_public.h +++ b/code/renderercommon/tr_public.h @@ -90,7 +90,8 @@ typedef struct { void (*EndFrame)( int *frontEndMsec, int *backEndMsec ); #if __ANDROID__ - void (*SetVRHeadsetParms)( const ovrMatrix4f *projectionMatrix, int renderBufferL, int renderBufferR ); + void (*SetVRHeadsetParms)( const ovrMatrix4f *projectionMatrixLeft, const ovrMatrix4f *projectionMatrixRight, + int renderBufferL, int renderBufferR ); #endif int (*MarkFragments)( int numPoints, const vec3_t *points, const vec3_t projection, diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c index d5a5578f..dc914555 100644 --- a/code/renderergl2/tr_backend.c +++ b/code/renderergl2/tr_backend.c @@ -1769,6 +1769,10 @@ const void* RB_SwitchEye( const void* data ) { tr.renderFbo->frameBuffer = cmd->eye; + // finish any 2D drawing if needed + if(tess.numIndexes) + RB_EndSurface(); + // Not calling FBO_Bind explicitly, since we just update the frameBuffer // within the struct. if (tr.renderFbo == glState.currentFBO) diff --git a/code/renderergl2/tr_cmds.c b/code/renderergl2/tr_cmds.c index 59b0e383..847a7e39 100644 --- a/code/renderergl2/tr_cmds.c +++ b/code/renderergl2/tr_cmds.c @@ -584,8 +584,10 @@ void R_Mat4Transpose( const float in[4][4], float* out ) { } -void RE_SetVRHeadsetParms( const ovrMatrix4f *projectionMatrix, int renderBufferL, int renderBufferR ) { - R_Mat4Transpose(projectionMatrix->M, tr.vrParms.projection); +void RE_SetVRHeadsetParms( const ovrMatrix4f *projectionMatrixLeft, const ovrMatrix4f *projectionMatrixRight, + int renderBufferL, int renderBufferR ) { + R_Mat4Transpose(projectionMatrixLeft->M, tr.vrParms.projectionL); + R_Mat4Transpose(projectionMatrixRight->M, tr.vrParms.projectionR); tr.vrParms.renderBufferL = renderBufferL; tr.vrParms.renderBufferR = renderBufferR; tr.vrParms.valid = qtrue; diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 624da15f..e26aa3f4 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -841,7 +841,8 @@ typedef struct { typedef struct { qboolean valid; - float projection[16]; + float projectionL[16]; + float projectionR[16]; int renderBufferL; int renderBufferR; int renderBufferOriginal; @@ -2504,7 +2505,8 @@ void RE_StretchPic ( float x, float y, float w, float h, void RE_BeginFrame( stereoFrame_t stereoFrame ); void RE_EndFrame( int *frontEndMsec, int *backEndMsec ); #if __ANDROID__ -void RE_SetVRHeadsetParms( const ovrMatrix4f *projectionMatrix, int renderBufferL, int renderBufferR ); +void RE_SetVRHeadsetParms( const ovrMatrix4f *projectionMatrixLeft, const ovrMatrix4f *projectionMatrixRight, + int renderBufferL, int renderBufferR ); #endif void RE_SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer, int padding); diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c index e15ab040..709aedfe 100644 --- a/code/renderergl2/tr_main.c +++ b/code/renderergl2/tr_main.c @@ -765,15 +765,12 @@ void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean comp height = ymax - ymin; if (tr.vrParms.valid) { - memcpy(&dest->projectionMatrix, &tr.vrParms.projection, sizeof(dest->projectionMatrix)); - /* if (dest->stereoFrame == STEREO_LEFT) { memcpy(&dest->projectionMatrix, &tr.vrParms.projectionL, sizeof(dest->projectionMatrix)); } else { memcpy(&dest->projectionMatrix, &tr.vrParms.projectionR, sizeof(dest->projectionMatrix)); } - */ } else { /* * offset the view origin of the viewer for stereo rendering diff --git a/code/vr/vr_base.h b/code/vr/vr_base.h index c92a7427..75bc1f0c 100644 --- a/code/vr/vr_base.h +++ b/code/vr/vr_base.h @@ -5,8 +5,6 @@ #include "vr_types.h" -#define PLAYER_HEIGHT 48 - engine_t* VR_Init( ovrJava java ); void VR_InitCvars( void ); void VR_Destroy( engine_t* engine ); diff --git a/code/vr/vr_input.c b/code/vr/vr_input.c index 96cff032..f84c33eb 100644 --- a/code/vr/vr_input.c +++ b/code/vr/vr_input.c @@ -175,13 +175,17 @@ void QuatToYawPitchRoll(ovrQuatf q, vec3_t rotation, vec3_t out) { GetAnglesFromVectors(forwardNormal, rightNormal, upNormal, out); } -void sendButtonActionSimple(const char* action) +static void sendButtonActionSimple(const char* action) { char command[256]; snprintf( command, sizeof( command ), "%s\n", action ); Cbuf_AddText( command ); } +static float length(float x, float y) +{ + return sqrtf(powf(x, 2.0f) + powf(y, 2.0f)); +} void IN_VRInit( void ) { @@ -202,7 +206,6 @@ static void IN_VRController( qboolean isRightController, ovrTracking remoteTrack VectorSubtract(vr.weaponangles_last, vr.weaponangles, vr.weaponangles_delta); VectorCopy(vr.weaponangles, vr.weaponangles_last); - //Record recent weapon position for trajectory based stuff for (int i = (NUM_WEAPON_SAMPLES-1); i != 0; --i) { @@ -220,8 +223,29 @@ static void IN_VRController( qboolean isRightController, ovrTracking remoteTrack //Just copy to calculated offset, used to use this in case we wanted to apply any modifiers, but don't any more VectorCopy(vr.current_weaponoffset, vr.calculated_weaponoffset); + } else { + vec3_t rotation = {0}; + rotation[PITCH] =-20.0f; + QuatToYawPitchRoll(remoteTracking.HeadPose.Pose.Orientation, rotation, vr.offhandangles); + ///location relative to view + vr.offhandoffset[0] = remoteTracking.HeadPose.Pose.Position.x - vr.hmdposition[0]; + vr.offhandoffset[1] = remoteTracking.HeadPose.Pose.Position.y - vr.hmdposition[1]; + vr.offhandoffset[2] = remoteTracking.HeadPose.Pose.Position.z - vr.hmdposition[2]; } + + if (vr.weapon_stabilised) + { + float x = vr.offhandoffset[0] - vr.calculated_weaponoffset[0]; + float y = vr.offhandoffset[1] - vr.calculated_weaponoffset[1]; + float z = vr.offhandoffset[2] - vr.calculated_weaponoffset[2]; + float zxDist = length(x, z); + + if (zxDist != 0.0f && z != 0.0f) { + VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)), + -degrees(atan2f(x, -z)), vr.weaponangles[ROLL] / 2.0f); //Dampen roll on stabilised weapon + } + } } static void IN_VRJoystick( qboolean isRightController, float joystickX, float joystickY ) @@ -320,12 +344,20 @@ static void IN_VRButtonsChanged( qboolean isRightController, uint32_t buttons ) { vrController_t* controller = isRightController == qtrue ? &rightController : &leftController; - if (isRightController == qfalse) - { - if ((buttons & ovrButton_Enter) && !(controller->buttons & ovrButton_Enter)) { - Com_QueueEvent(in_vrEventTime, SE_KEY, K_ESCAPE, qtrue, 0, NULL); - } else if (!(buttons & ovrButton_Enter) && (controller->buttons & ovrButton_Enter)) { - Com_QueueEvent(in_vrEventTime, SE_KEY, K_ESCAPE, qfalse, 0, NULL); + if (isRightController == qfalse) { + if ((buttons & ovrButton_Enter) && !(controller->buttons & ovrButton_Enter)) { + Com_QueueEvent(in_vrEventTime, SE_KEY, K_ESCAPE, qtrue, 0, NULL); + } else if (!(buttons & ovrButton_Enter) && (controller->buttons & ovrButton_Enter)) { + Com_QueueEvent(in_vrEventTime, SE_KEY, K_ESCAPE, qfalse, 0, NULL); + } + } + + if (isRightController != (vr_righthanded->integer != 0)) + { + if ((buttons & ovrButton_GripTrigger) && !(controller->buttons & ovrButton_GripTrigger)) { + vr.weapon_stabilised = qtrue; + } else if (!(buttons & ovrButton_GripTrigger) && (controller->buttons & ovrButton_GripTrigger)) { + vr.weapon_stabilised = qfalse; } } @@ -453,13 +485,13 @@ void IN_VRInputFrame( void ) continue; } + if (controller->buttons ^ state.Buttons) { + IN_VRButtonsChanged(isRight, state.Buttons); + } + IN_VRController(isRight, remoteTracking); IN_VRJoystick(isRight, state.Joystick.x, state.Joystick.y); IN_VRTriggers(isRight, state.IndexTrigger); - - if (controller->buttons ^ state.Buttons) { - IN_VRButtonsChanged(isRight, state.Buttons); - } } in_vrEventTime = Sys_Milliseconds( ); diff --git a/code/vr/vr_renderer.c b/code/vr/vr_renderer.c index e8724e80..ffe015b9 100644 --- a/code/vr/vr_renderer.c +++ b/code/vr/vr_renderer.c @@ -7,6 +7,7 @@ #include "../VrApi/Include/VrApi_Types.h" #include "vr_clientinfo.h" +#include "vr_types.h" //#include "../SDL2/include/SDL_opengles2_gl2.h" #pragma clang diagnostic push @@ -46,8 +47,8 @@ void VR_GetResolution(engine_t* engine, int *pWidth, int *pHeight) if (engine) { - *pHeight = height = *pWidth = width = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH) * SUPER_SAMPLE; - //*pHeight = height = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_HEIGHT) * SUPER_SAMPLE; + *pWidth = width = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH) * SUPER_SAMPLE; + *pHeight = height = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_HEIGHT) * SUPER_SAMPLE; } else { @@ -228,13 +229,6 @@ void VR_DrawFrame( engine_t* engine ) { engine->predictedDisplayTime = vrapi_GetPredictedDisplayTime(engine->ovr, engine->frameIndex); engine->tracking = vrapi_GetPredictedTracking2(engine->ovr, engine->predictedDisplayTime); - //Now using a symmetrical render target, based on the horizontal FOV - float fov = vrapi_GetSystemPropertyInt( engine->ovr, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_Y); - - // Setup the projection matrix. - const ovrMatrix4f projectionMatrix = ovrMatrix4f_CreateProjectionFov( - fov, fov, 0.0f, 0.0f, 1.0f, 0.0f ); - static int playerYaw = 0; int eyeW, eyeH; @@ -247,7 +241,7 @@ void VR_DrawFrame( engine_t* engine ) { // Add a simple cylindrical layer cylinderLayer.Cylinder = - BuildCylinderLayer(engine, eyeW, eyeW, &engine->tracking, radians(playerYaw) ); + BuildCylinderLayer(engine, eyeW, eyeW * 0.75f, &engine->tracking, radians(playerYaw) ); const ovrLayerHeader2* layers[] = { &cylinderLayer.Header @@ -264,7 +258,14 @@ void VR_DrawFrame( engine_t* engine ) { const framebuffer_t* framebuffers = engine->framebuffers; - re.SetVRHeadsetParms(&projectionMatrix, + //Now using a symmetrical render target, based on the horizontal FOV + float fov = vrapi_GetSystemPropertyInt( engine->ovr, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_Y); + + // Setup the projection matrix. + const ovrMatrix4f projectionMatrix = ovrMatrix4f_CreateProjectionFov( + fov, fov, 0.0f, 0.0f, 1.0f, 0.0f ); + + re.SetVRHeadsetParms(&projectionMatrix, &projectionMatrix, framebuffers[0].framebuffers[framebuffers[0].swapchainIndex], framebuffers[1].framebuffers[framebuffers[1].swapchainIndex]); @@ -288,7 +289,7 @@ void VR_DrawFrame( engine_t* engine ) { for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) { layer.Textures[eye].ColorSwapChain = engine->framebuffers[eye].colorTexture; layer.Textures[eye].SwapChainIndex = engine->framebuffers[eye].swapchainIndex; - layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection(&projectionMatrix); + layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection(&engine->tracking.Eye[eye].ProjectionMatrix); } @@ -297,7 +298,7 @@ void VR_DrawFrame( engine_t* engine ) { VR_ClearFrameBuffer(framebuffers[0].framebuffers[framebuffers[0].swapchainIndex], eyeW, eyeH); VR_ClearFrameBuffer(framebuffers[1].framebuffers[framebuffers[1].swapchainIndex], eyeW, eyeH); - re.SetVRHeadsetParms(&projectionMatrix, + re.SetVRHeadsetParms(&engine->tracking.Eye[0].ProjectionMatrix, &engine->tracking.Eye[1].ProjectionMatrix, framebuffers[0].framebuffers[framebuffers[0].swapchainIndex], framebuffers[1].framebuffers[framebuffers[1].swapchainIndex]);