Changes to sync up with the PCVR build

This commit is contained in:
Simon 2023-07-27 21:56:20 +01:00
parent c663fdc776
commit a58e4051b5
11 changed files with 86 additions and 129 deletions

View file

@ -445,7 +445,7 @@ void VR_FrameSetup()
vr.immersive_cinematics = (vr_immersive_cinematics->value != 0.0f); vr.immersive_cinematics = (vr_immersive_cinematics->value != 0.0f);
} }
bool VR_GetVRProjection(int eye, float zNear, float zFar, float* projection) 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 //Don't use our projection if playing a cinematic and we are not immersive
if (vr.cin_camera && !vr.immersive_cinematics) if (vr.cin_camera && !vr.immersive_cinematics)
@ -453,37 +453,25 @@ bool VR_GetVRProjection(int eye, float zNear, float zFar, float* projection)
return false; return false;
} }
if (!vr.cgzoommode) //Just use game-calculated FOV when showing the quad screen
if (vr.using_screen_layer)
{ {
if (strstr(gAppState.OpenXRHMD, "meta") != NULL)
{
XrFovf fov = {};
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
fov.angleLeft += gAppState.Projections[eye].fov.angleLeft / 2.0f;
fov.angleRight += gAppState.Projections[eye].fov.angleRight / 2.0f;
fov.angleUp += gAppState.Projections[eye].fov.angleUp / 2.0f;
fov.angleDown += gAppState.Projections[eye].fov.angleDown / 2.0f;
}
XrMatrix4x4f_CreateProjectionFov(
&(gAppState.ProjectionMatrices[eye]), GRAPHICS_OPENGL_ES,
fov, zNear, zFar);
}
if (strstr(gAppState.OpenXRHMD, "pico") != NULL)
{
XrMatrix4x4f_CreateProjectionFov(
&(gAppState.ProjectionMatrices[eye]), GRAPHICS_OPENGL_ES,
gAppState.Projections[eye].fov, zNear, zFar);
}
memcpy(projection, gAppState.ProjectionMatrices[eye].m, 16 * sizeof(float));
return true;
}
return false; return false;
} }
XrFovf fov = gAppState.Views[eye].fov;
fov.angleLeft /= zZoomX;
fov.angleRight /= zZoomX;
fov.angleUp /= zZoomY;
fov.angleDown /= zZoomY;
XrMatrix4x4f_CreateProjectionFov(
(XrMatrix4x4f*)projection, GRAPHICS_OPENGL,
fov, zNear, zFar);
return true;
}
extern "C" { extern "C" {
void jni_haptic_event(const char *event, int position, int flags, int intensity, float angle, float yHeight); void jni_haptic_event(const char *event, int position, int flags, int intensity, float angle, float yHeight);

View file

@ -439,7 +439,7 @@ void TBXR_UpdateControllers( )
XrSpaceLocation loc = {}; XrSpaceLocation loc = {};
loc.type = XR_TYPE_SPACE_LOCATION; loc.type = XR_TYPE_SPACE_LOCATION;
loc.next = &vel; loc.next = &vel;
XrResult res = xrLocateSpace(aimSpace[i], gAppState.CurrentSpace, gAppState.FrameState.predictedDisplayTime, &loc); XrResult res = xrLocateSpace(aimSpace[i], gAppState.StageSpace, gAppState.FrameState.predictedDisplayTime, &loc);
if (res != XR_SUCCESS) { if (res != XR_SUCCESS) {
Com_Printf("xrLocateSpace error: %d", (int)res); Com_Printf("xrLocateSpace error: %d", (int)res);
} }

View file

@ -874,10 +874,11 @@ void ovrApp_Clear(ovrApp* app) {
memset(&app->ViewportConfig, 0, sizeof(XrViewConfigurationProperties)); memset(&app->ViewportConfig, 0, sizeof(XrViewConfigurationProperties));
memset(&app->ViewConfigurationView, 0, ovrMaxNumEyes * sizeof(XrViewConfigurationView)); memset(&app->ViewConfigurationView, 0, ovrMaxNumEyes * sizeof(XrViewConfigurationView));
app->SystemId = XR_NULL_SYSTEM_ID; app->SystemId = XR_NULL_SYSTEM_ID;
app->LocalSpace = XR_NULL_HANDLE;
app->HeadSpace = XR_NULL_HANDLE; app->HeadSpace = XR_NULL_HANDLE;
app->StageSpace = XR_NULL_HANDLE; app->StageSpace = XR_NULL_HANDLE;
app->FakeStageSpace = XR_NULL_HANDLE;
app->CurrentSpace = XR_NULL_HANDLE;
app->SessionActive = false; app->SessionActive = false;
app->SupportedDisplayRefreshRates = NULL; app->SupportedDisplayRefreshRates = NULL;
app->RequestedDisplayRefreshRateIndex = 0; app->RequestedDisplayRefreshRateIndex = 0;
@ -1335,6 +1336,7 @@ void TBXR_InitialiseResolution()
XrViewConfigurationProperties viewportConfig; XrViewConfigurationProperties viewportConfig;
viewportConfig.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES; viewportConfig.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES;
viewportConfig.next = NULL;
OXR(xrGetViewConfigurationProperties( OXR(xrGetViewConfigurationProperties(
gAppState.Instance, gAppState.SystemId, viewportConfigType, &viewportConfig)); gAppState.Instance, gAppState.SystemId, viewportConfigType, &viewportConfig));
ALOGV( ALOGV(
@ -1424,12 +1426,8 @@ void TBXR_EnterVR( ) {
void TBXR_LeaveVR( ) { void TBXR_LeaveVR( ) {
if (gAppState.Session) { if (gAppState.Session) {
OXR(xrDestroySpace(gAppState.HeadSpace)); OXR(xrDestroySpace(gAppState.HeadSpace));
// StageSpace is optional. OXR(xrDestroySpace(gAppState.LocalSpace));
if (gAppState.StageSpace != XR_NULL_HANDLE) {
OXR(xrDestroySpace(gAppState.StageSpace)); OXR(xrDestroySpace(gAppState.StageSpace));
}
OXR(xrDestroySpace(gAppState.FakeStageSpace));
gAppState.CurrentSpace = XR_NULL_HANDLE;
OXR(xrDestroySession(gAppState.Session)); OXR(xrDestroySession(gAppState.Session));
gAppState.Session = NULL; gAppState.Session = NULL;
} }
@ -1554,14 +1552,12 @@ void TBXR_InitRenderer( ) {
free(referenceSpaces); free(referenceSpaces);
if (gAppState.CurrentSpace == XR_NULL_HANDLE) {
TBXR_Recenter(); TBXR_Recenter();
}
gAppState.Projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView))); gAppState.Views = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView)));
for (int eye = 0; eye < ovrMaxNumEyes; eye++) { for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
memset(&gAppState.Projections[eye], 0, sizeof(XrView)); memset(&gAppState.Views[eye], 0, sizeof(XrView));
gAppState.Projections[eye].type = XR_TYPE_VIEW; gAppState.Views[eye].type = XR_TYPE_VIEW;
} }
if (strstr(gAppState.OpenXRHMD, "pico") != NULL) if (strstr(gAppState.OpenXRHMD, "pico") != NULL)
@ -1585,7 +1581,7 @@ void TBXR_InitRenderer( ) {
void VR_DestroyRenderer( ) void VR_DestroyRenderer( )
{ {
ovrRenderer_Destroy(&gAppState.Renderer); ovrRenderer_Destroy(&gAppState.Renderer);
free(gAppState.Projections); free(gAppState.Views);
} }
void TBXR_InitialiseOpenXR() void TBXR_InitialiseOpenXR()
@ -1710,57 +1706,29 @@ void TBXR_Recenter() {
XrReferenceSpaceCreateInfo spaceCreateInfo = {}; XrReferenceSpaceCreateInfo spaceCreateInfo = {};
spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO; spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f; spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f;
if (gAppState.CurrentSpace != XR_NULL_HANDLE) { if (gAppState.StageSpace != XR_NULL_HANDLE) {
vec3_t rotation = {0, 0, 0}; vec3_t rotation = {0, 0, 0};
XrSpaceLocation loc = {}; XrSpaceLocation loc = {};
loc.type = XR_TYPE_SPACE_LOCATION; loc.type = XR_TYPE_SPACE_LOCATION;
OXR(xrLocateSpace(gAppState.HeadSpace, gAppState.CurrentSpace, gAppState.FrameState.predictedDisplayTime, &loc)); OXR(xrLocateSpace(gAppState.HeadSpace, gAppState.StageSpace, gAppState.FrameState.predictedDisplayTime, &loc));
QuatToYawPitchRoll(loc.pose.orientation, rotation, vr.hmdorientation); QuatToYawPitchRoll(loc.pose.orientation, rotation, vr.hmdorientation);
spaceCreateInfo.poseInReferenceSpace.orientation.x = 0;
spaceCreateInfo.poseInReferenceSpace.orientation.y = 0;
spaceCreateInfo.poseInReferenceSpace.orientation.z = 0;
spaceCreateInfo.poseInReferenceSpace.orientation.w = 1;
} }
// Delete previous space instances // Delete previous space instances
if (gAppState.StageSpace != XR_NULL_HANDLE) { if (gAppState.StageSpace != XR_NULL_HANDLE) {
OXR(xrDestroySpace(gAppState.StageSpace)); OXR(xrDestroySpace(gAppState.StageSpace));
} }
if (gAppState.FakeStageSpace != XR_NULL_HANDLE) { if (gAppState.LocalSpace != XR_NULL_HANDLE) {
OXR(xrDestroySpace(gAppState.FakeStageSpace)); OXR(xrDestroySpace(gAppState.LocalSpace));
} }
// Create a default stage space to use if SPACE_TYPE_STAGE is not
// supported, or calls to xrGetReferenceSpaceBoundsRect fail.
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
spaceCreateInfo.poseInReferenceSpace.position.y = -1.6750f;
OXR(xrCreateReferenceSpace(gAppState.Session, &spaceCreateInfo, &gAppState.FakeStageSpace));
ALOGV("Created fake stage space from local space with offset");
gAppState.CurrentSpace = gAppState.FakeStageSpace;
if (stageSupported) {
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE; spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
spaceCreateInfo.poseInReferenceSpace.position.y = 0.0f; spaceCreateInfo.poseInReferenceSpace.position.y = 0.0f;
OXR(xrCreateReferenceSpace(gAppState.Session, &spaceCreateInfo, &gAppState.StageSpace)); OXR(xrCreateReferenceSpace(gAppState.Session, &spaceCreateInfo, &gAppState.StageSpace));
ALOGV("Created stage space"); ALOGV("Created stage space");
gAppState.CurrentSpace = gAppState.StageSpace;
}
}
void TBXR_UpdateStageBounds() { spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
XrExtent2Df stageBounds = {}; OXR(xrCreateReferenceSpace(gAppState.Session, &spaceCreateInfo, &gAppState.LocalSpace));
XrResult result;
OXR(result = xrGetReferenceSpaceBoundsRect(
gAppState.Session, XR_REFERENCE_SPACE_TYPE_STAGE, &stageBounds));
if (result != XR_SUCCESS) {
ALOGE("Stage bounds query failed: using small defaults");
stageBounds.width = 1.0f;
stageBounds.height = 1.0f;
gAppState.CurrentSpace = gAppState.FakeStageSpace;
}
} }
void TBXR_WaitForSessionActive() void TBXR_WaitForSessionActive()
@ -1786,7 +1754,7 @@ static void TBXR_GetHMDOrientation() {
// The better the prediction, the less black will be pulled in at the edges. // The better the prediction, the less black will be pulled in at the edges.
XrSpaceLocation loc = {}; XrSpaceLocation loc = {};
loc.type = XR_TYPE_SPACE_LOCATION; loc.type = XR_TYPE_SPACE_LOCATION;
OXR(xrLocateSpace(gAppState.HeadSpace, gAppState.CurrentSpace, gAppState.FrameState.predictedDisplayTime, &loc)); OXR(xrLocateSpace(gAppState.HeadSpace, gAppState.StageSpace, gAppState.FrameState.predictedDisplayTime, &loc));
gAppState.xfStageFromHead = loc.pose; gAppState.xfStageFromHead = loc.pose;
const XrQuaternionf quatHmd = gAppState.xfStageFromHead.orientation; const XrQuaternionf quatHmd = gAppState.xfStageFromHead.orientation;
@ -1812,7 +1780,6 @@ void TBXR_FrameSetup()
{ {
TBXR_ProcessMessageQueue(); TBXR_ProcessMessageQueue();
GLboolean stageBoundsDirty = GL_TRUE;
if (ovrApp_HandleXrEvents(&gAppState)) if (ovrApp_HandleXrEvents(&gAppState))
{ {
TBXR_Recenter(); TBXR_Recenter();
@ -1823,12 +1790,6 @@ void TBXR_FrameSetup()
continue; continue;
} }
if (stageBoundsDirty)
{
TBXR_UpdateStageBounds();
stageBoundsDirty = GL_FALSE;
}
break; break;
} }
@ -1901,10 +1862,16 @@ void TBXR_ClearFrameBuffer(int width, int height)
void TBXR_prepareEyeBuffer(int eye ) void TBXR_prepareEyeBuffer(int eye )
{ {
vr.eye = eye;
ovrFramebuffer* frameBuffer = &(gAppState.Renderer.FrameBuffer[eye]); ovrFramebuffer* frameBuffer = &(gAppState.Renderer.FrameBuffer[eye]);
ovrFramebuffer_Acquire(frameBuffer); ovrFramebuffer_Acquire(frameBuffer);
ovrFramebuffer_SetCurrent(frameBuffer); ovrFramebuffer_SetCurrent(frameBuffer);
TBXR_ClearFrameBuffer(frameBuffer->ColorSwapChain.Width, frameBuffer->ColorSwapChain.Height); TBXR_ClearFrameBuffer(frameBuffer->ColorSwapChain.Width, frameBuffer->ColorSwapChain.Height);
//Seems odd, but used to move the HUD elements to be central on the player's view
//HMDs with a symmetric fov (like the PICO) will have 0 in this value, but the Meta Quest
//will have an asymmetric fov and the HUD would be very misaligned as a result
vr.off_center_fov = -(gAppState.Views[eye].fov.angleLeft + gAppState.Views[eye].fov.angleRight) / 2.0f;
} }
void TBXR_finishEyeBuffer(int eye ) void TBXR_finishEyeBuffer(int eye )
@ -1931,7 +1898,7 @@ void TBXR_updateProjections()
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO; projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
projectionInfo.viewConfigurationType = gAppState.ViewportConfig.viewConfigurationType; projectionInfo.viewConfigurationType = gAppState.ViewportConfig.viewConfigurationType;
projectionInfo.displayTime = gAppState.FrameState.predictedDisplayTime; projectionInfo.displayTime = gAppState.FrameState.predictedDisplayTime;
projectionInfo.space = gAppState.HeadSpace; projectionInfo.space = gAppState.LocalSpace;
XrViewState viewState = {XR_TYPE_VIEW_STATE, NULL}; XrViewState viewState = {XR_TYPE_VIEW_STATE, NULL};
@ -1944,7 +1911,7 @@ void TBXR_updateProjections()
&viewState, &viewState,
projectionCapacityInput, projectionCapacityInput,
&projectionCountOutput, &projectionCountOutput,
gAppState.Projections)); gAppState.Views));
} }
void TBXR_submitFrame() void TBXR_submitFrame()
@ -1955,28 +1922,9 @@ void TBXR_submitFrame()
TBXR_updateProjections(); TBXR_updateProjections();
XrFovf fov = {}; //Calculate the maximum extent fov for use in culling in the engine (we won't want to cull inside this fov)
XrPosef viewTransform[2]; vr.fov_x = (fabs(gAppState.Views[0].fov.angleLeft) + fabs(gAppState.Views[1].fov.angleLeft)) * 180.0f / M_PI;
vr.fov_y = (fabs(gAppState.Views[0].fov.angleUp) + fabs(gAppState.Views[0].fov.angleUp)) * 180.0f / M_PI;
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
XrPosef xfHeadFromEye = gAppState.Projections[eye].pose;
XrPosef xfStageFromEye = XrPosef_Multiply(gAppState.xfStageFromHead, xfHeadFromEye);
viewTransform[eye] = XrPosef_Inverse(xfStageFromEye);
fov.angleLeft += gAppState.Projections[eye].fov.angleLeft / 2.0f;
fov.angleRight += gAppState.Projections[eye].fov.angleRight / 2.0f;
fov.angleUp += gAppState.Projections[eye].fov.angleUp / 2.0f;
fov.angleDown += gAppState.Projections[eye].fov.angleDown / 2.0f;
}
vr.fov_x = (fabs(fov.angleLeft) + fabs(fov.angleRight)) * 180.0f / M_PI;
vr.fov_y = (fabs(fov.angleUp) + fabs(fov.angleDown)) * 180.0f / M_PI;
if (vr.cgzoommode)
{
fov.angleLeft /= 1.3f;
fov.angleRight /= 1.3f;
fov.angleUp /= 1.3f;
fov.angleDown /= 1.3f;
}
gAppState.LayerCount = 0; gAppState.LayerCount = 0;
memset(gAppState.Layers, 0, sizeof(xrCompositorLayer_Union) * ovrMaxLayerCount); memset(gAppState.Layers, 0, sizeof(xrCompositorLayer_Union) * ovrMaxLayerCount);
@ -1987,16 +1935,26 @@ void TBXR_submitFrame()
projection_layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION; projection_layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
projection_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT; projection_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
projection_layer.layerFlags |= XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT; projection_layer.layerFlags |= XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
projection_layer.space = gAppState.CurrentSpace; projection_layer.space = gAppState.LocalSpace;
projection_layer.viewCount = ovrMaxNumEyes; projection_layer.viewCount = ovrMaxNumEyes;
projection_layer.views = projection_layer_elements; projection_layer.views = projection_layer_elements;
for (int eye = 0; eye < ovrMaxNumEyes; eye++) { for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
XrFovf fov = gAppState.Views[eye].fov;
if (vr.cgzoommode)
{
fov.angleLeft /= 1.3f;
fov.angleRight /= 1.3f;
fov.angleUp /= 1.3f;
fov.angleDown /= 1.3f;
}
ovrFramebuffer* frameBuffer = &gAppState.Renderer.FrameBuffer[eye]; ovrFramebuffer* frameBuffer = &gAppState.Renderer.FrameBuffer[eye];
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView)); memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW; projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
projection_layer_elements[eye].pose = gAppState.xfStageFromHead; projection_layer_elements[eye].pose = gAppState.Views[eye].pose;
projection_layer_elements[eye].fov = fov; projection_layer_elements[eye].fov = fov;
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage)); memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
projection_layer_elements[eye].subImage.swapchain = projection_layer_elements[eye].subImage.swapchain =
@ -2020,7 +1978,7 @@ void TBXR_submitFrame()
quad_layer.type = XR_TYPE_COMPOSITION_LAYER_QUAD; quad_layer.type = XR_TYPE_COMPOSITION_LAYER_QUAD;
quad_layer.next = NULL; quad_layer.next = NULL;
quad_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT; quad_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
quad_layer.space = gAppState.CurrentSpace; quad_layer.space = gAppState.StageSpace;
quad_layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH; quad_layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH;
memset(&quad_layer.subImage, 0, sizeof(XrSwapchainSubImage)); memset(&quad_layer.subImage, 0, sizeof(XrSwapchainSubImage));
quad_layer.subImage.swapchain = gAppState.Renderer.FrameBuffer[0].ColorSwapChain.Handle; quad_layer.subImage.swapchain = gAppState.Renderer.FrameBuffer[0].ColorSwapChain.Handle;

View file

@ -235,14 +235,14 @@ typedef struct
XrViewConfigurationProperties ViewportConfig; XrViewConfigurationProperties ViewportConfig;
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes]; XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
XrSystemId SystemId; XrSystemId SystemId;
XrSpace LocalSpace;
XrSpace HeadSpace; XrSpace HeadSpace;
XrSpace StageSpace; XrSpace StageSpace;
XrSpace FakeStageSpace;
XrSpace CurrentSpace;
GLboolean SessionActive; GLboolean SessionActive;
XrPosef xfStageFromHead; XrPosef xfStageFromHead;
XrView* Projections; XrView* Views;
XrMatrix4x4f ProjectionMatrices[2];
float currentDisplayRefreshRate; float currentDisplayRefreshRate;
@ -303,7 +303,7 @@ void surfaceMessageQueue_PostMessage(surfaceMessageQueue * messageQueue, const s
void VR_FrameSetup(); void VR_FrameSetup();
bool VR_UseScreenLayer(); bool VR_UseScreenLayer();
float VR_GetScreenLayerDistance(); float VR_GetScreenLayerDistance();
bool VR_GetVRProjection(int eye, float zNear, float zFar, float* projection); bool VR_GetVRProjection(int eye, float zNear, float zFar, float zZoomX, float zZoomY, float* projection);
void VR_HandleControllerInput(); void VR_HandleControllerInput();
void VR_SetHMDOrientation(float pitch, float yaw, float roll ); void VR_SetHMDOrientation(float pitch, float yaw, float roll );
void VR_SetHMDPosition(float x, float y, float z ); void VR_SetHMDPosition(float x, float y, float z );

View file

@ -33,10 +33,12 @@ typedef struct {
float remote_snapTurn; // how much turn has been applied to the yaw by joystick for a remote controlled entity float remote_snapTurn; // how much turn has been applied to the yaw by joystick for a remote controlled entity
int remote_cooldown; int remote_cooldown;
int eye;
bool using_screen_layer; bool using_screen_layer;
bool third_person; bool third_person;
float fov_x; float fov_x;
float fov_y; float fov_y;
float off_center_fov;
float tempWeaponVelocity; float tempWeaponVelocity;

View file

@ -38,6 +38,9 @@ void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) {
xoffset *= -1; xoffset *= -1;
} }
//We need to add an offset due to the effect of the compositor projection for asymmetric FOVs
xoffset += vr->off_center_fov * 640;
*x *= screenXScale; *x *= screenXScale;
*y *= screenYScale; *y *= screenYScale;
if (w != NULL) { if (w != NULL) {

View file

@ -129,7 +129,7 @@ typedef struct {
//JKXR Functions //JKXR Functions
bool (*TBXR_useScreenLayer) ( void ); bool (*TBXR_useScreenLayer) ( void );
bool (*TBXR_GetVRProjection) (int eye, float zNear, float zFar, float* projection); bool (*TBXR_GetVRProjection) (int eye, float zNear, float zFar, float zZoomX, float zZoomY, float* projection);
} refimport_t; } refimport_t;

View file

@ -1431,8 +1431,6 @@ const void *RB_DrawBuffer( const void *data ) {
cmd = (const drawBufferCommand_t *)data; cmd = (const drawBufferCommand_t *)data;
tr.stereoFrame = (stereoFrame_t )cmd->buffer;
// clear screen for debugging // clear screen for debugging
if ( r_clear->integer ) { if ( r_clear->integer ) {
qglClearColor( 0, 0, 0, 1 ); qglClearColor( 0, 0, 0, 1 );

View file

@ -1018,7 +1018,6 @@ typedef struct {
model_t *currentModel; model_t *currentModel;
viewParms_t viewParms; viewParms_t viewParms;
stereoFrame_t stereoFrame;
float identityLight; // 1.0 / ( 1 << overbrightBits ) float identityLight; // 1.0 / ( 1 << overbrightBits )
int identityLightByte; // identityLight * 255 int identityLightByte; // identityLight * 255

View file

@ -528,7 +528,7 @@ R_SetupProjection
void R_SetupProjection( void ) { void R_SetupProjection( void ) {
float xmin, xmax, ymin, ymax; float xmin, xmax, ymin, ymax;
float width, height, depth; float width, height, depth;
float zNear, zFar; float zNear, zFar, zZoomX, zZoomY;
// dynamically compute far clip plane distance // dynamically compute far clip plane distance
SetFarClip(); SetFarClip();
@ -538,14 +538,20 @@ void R_SetupProjection( void ) {
// //
zNear = r_znear->value; zNear = r_znear->value;
zFar = tr.viewParms.zFar; zFar = tr.viewParms.zFar;
zZoomX = 1.0f;
zZoomY = 1.0f;
if (!tr.refdef.override_fov && if (tr.refdef.override_fov || vr->cgzoommode)
ri.TBXR_GetVRProjection((int)tr.stereoFrame, zNear, zFar, tr.viewParms.projectionMatrix)) {
zZoomX = vr->fov_x / tr.refdef.fov_x;
zZoomY = vr->fov_y / tr.refdef.fov_y;
}
if (ri.TBXR_GetVRProjection(vr->eye, zNear, zFar, zZoomX, zZoomY, tr.viewParms.projectionMatrix))
{ {
return; return;
} }
ymax = zNear * tan( tr.refdef.fov_y * M_PI / 360.0f ); ymax = zNear * tan( tr.refdef.fov_y * M_PI / 360.0f );
ymin = -ymax; ymin = -ymax;

View file

@ -37,6 +37,9 @@ void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) {
xoffset *= -1; xoffset *= -1;
} }
//We need to add an offset due to the effect of the compositor projection for asymmetric FOVs
xoffset += vr->off_center_fov * 640;
*x *= screenXScale; *x *= screenXScale;
*y *= screenYScale; *y *= screenYScale;
if (w != NULL) { if (w != NULL) {