OpenXR projection matrix calculation from example code

This commit is contained in:
Lubos 2022-04-30 14:02:21 +02:00
parent ecd50dbcb1
commit 61b3192bce
2 changed files with 71 additions and 72 deletions

View file

@ -328,12 +328,6 @@ void VR_DrawFrame( engine_t* engine ) {
vr.weapon_zoomLevel = 1.0f; vr.weapon_zoomLevel = 1.0f;
} }
//Projection used for drawing HUD models etc
const ovrMatrix4f monoVRMatrix = ovrMatrix4f_CreateProjectionFov(
30.0f, 30.0f, 0.0f, 0.0f, 1.0f, 0.0f );
const ovrMatrix4f projectionMatrix = ovrMatrix4f_CreateProjectionFov(
vr.fov_x / vr.weapon_zoomLevel, vr.fov_y / vr.weapon_zoomLevel, 0.0f, 0.0f, 1.0f, 0.0f );
GLboolean stageBoundsDirty = GL_TRUE; GLboolean stageBoundsDirty = GL_TRUE;
ovrApp_HandleXrEvents(&engine->appState); ovrApp_HandleXrEvents(&engine->appState);
if (engine->appState.SessionActive == GL_FALSE) { if (engine->appState.SessionActive == GL_FALSE) {
@ -395,16 +389,27 @@ void VR_DrawFrame( engine_t* engine ) {
projections)); projections));
// //
XrFovf fov;
XrPosef viewTransform[2]; XrPosef viewTransform[2];
for (int eye = 0; eye < ovrMaxNumEyes; eye++) { for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
XrPosef xfHeadFromEye = projections[eye].pose; XrPosef xfHeadFromEye = projections[eye].pose;
XrPosef xfStageFromEye = XrPosef_Multiply(xfStageFromHead, xfHeadFromEye); XrPosef xfStageFromEye = XrPosef_Multiply(xfStageFromHead, xfHeadFromEye);
viewTransform[eye] = XrPosef_Inverse(xfStageFromEye); viewTransform[eye] = XrPosef_Inverse(xfStageFromEye);
const XrFovf fov = projections[eye].fov; fov = projections[eye].fov;
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;
} }
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;
//Projection used for drawing HUD models etc
const ovrMatrix4f monoVRMatrix = ovrMatrix4f_CreateProjectionFov(
30.0f, 30.0f, 0.0f, 0.0f, 1.0f, 0.0f );
const ovrMatrix4f projectionMatrix = ovrMatrix4f_CreateProjectionFov(
fov.angleLeft / vr.weapon_zoomLevel,
fov.angleRight / vr.weapon_zoomLevel,
fov.angleUp / vr.weapon_zoomLevel,
fov.angleDown / vr.weapon_zoomLevel,
1.0f, 0.0f );
engine->appState.LayerCount = 0; engine->appState.LayerCount = 0;
memset(engine->appState.Layers, 0, sizeof(ovrCompositorLayer_Union) * ovrMaxLayerCount); memset(engine->appState.Layers, 0, sizeof(ovrCompositorLayer_Union) * ovrMaxLayerCount);
@ -438,7 +443,7 @@ void VR_DrawFrame( engine_t* engine ) {
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 = XrPosef_Inverse(viewTransform[eye]); projection_layer_elements[eye].pose = XrPosef_Inverse(viewTransform[eye]);
projection_layer_elements[eye].fov = projections[eye].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 = frameBuffer->ColorSwapChain.Handle; projection_layer_elements[eye].subImage.swapchain = frameBuffer->ColorSwapChain.Handle;

View file

@ -465,82 +465,76 @@ ovrMatrix4f
================================================================================ ================================================================================
*/ */
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
ovrMatrix4f ovrMatrix4f_CreateProjection( const float angleLeft,
const float minX, const float angleRight,
const float maxX, const float angleUp,
float const minY, const float angleDown,
const float maxY,
const float nearZ, const float nearZ,
const float farZ) { const float farZ) {
const float width = maxX - minX;
const float height = maxY - minY;
const float offsetZ = nearZ; // set to zero for a [0,1] clip space
ovrMatrix4f out; 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) { if (farZ <= nearZ) {
// place the far plane at infinity // place the far plane at infinity
out.M[0][0] = 2 * nearZ / width; result.M[0][0] = 2 / tanAngleWidth;
out.M[0][1] = 0; result.M[0][1] = 0;
out.M[0][2] = (maxX + minX) / width; result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
out.M[0][3] = 0; result.M[0][3] = 0;
out.M[1][0] = 0; result.M[1][0] = 0;
out.M[1][1] = 2 * nearZ / height; result.M[1][1] = 2 / tanAngleHeight;
out.M[1][2] = (maxY + minY) / height; result.M[1][2] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
out.M[1][3] = 0; result.M[1][3] = 0;
out.M[2][0] = 0; result.M[2][0] = 0;
out.M[2][1] = 0; result.M[2][1] = 0;
out.M[2][2] = -1; result.M[2][2] = -1;
out.M[2][3] = -(nearZ + offsetZ); result.M[2][3] = -(nearZ + offsetZ);
out.M[3][0] = 0; result.M[3][0] = 0;
out.M[3][1] = 0; result.M[3][1] = 0;
out.M[3][2] = -1; result.M[3][2] = -1;
out.M[3][3] = 0; result.M[3][3] = 0;
} else { } else {
// normal projection // normal projection
out.M[0][0] = 2 * nearZ / width; result.M[0][0] = 2 / tanAngleWidth;
out.M[0][1] = 0; result.M[0][1] = 0;
out.M[0][2] = (maxX + minX) / width; result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
out.M[0][3] = 0; result.M[0][3] = 0;
out.M[1][0] = 0; result.M[1][0] = 0;
out.M[1][1] = 2 * nearZ / height; result.M[1][1] = 2 / tanAngleHeight;
out.M[1][2] = (maxY + minY) / height; result.M[1][2] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
out.M[1][3] = 0; result.M[1][3] = 0;
out.M[2][0] = 0; result.M[2][0] = 0;
out.M[2][1] = 0; result.M[2][1] = 0;
out.M[2][2] = -(farZ + offsetZ) / (farZ - nearZ); result.M[2][2] = -(farZ + offsetZ) / (farZ - nearZ);
out.M[2][3] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ); result.M[2][3] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
out.M[3][0] = 0; result.M[3][0] = 0;
out.M[3][1] = 0; result.M[3][1] = 0;
out.M[3][2] = -1; result.M[3][2] = -1;
out.M[3][3] = 0; result.M[3][3] = 0;
} }
return out; return result;
}
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
const float fovDegreesX,
const float fovDegreesY,
const float offsetX,
const float offsetY,
const float nearZ,
const float farZ) {
const float halfWidth = nearZ * tanf(fovDegreesX * (M_PI / 180.0f * 0.5f));
const float halfHeight = nearZ * tanf(fovDegreesY * (M_PI / 180.0f * 0.5f));
const float minX = offsetX - halfWidth;
const float maxX = offsetX + halfWidth;
const float minY = offsetY - halfHeight;
const float maxY = offsetY + halfHeight;
return ovrMatrix4f_CreateProjection(minX, maxX, minY, maxY, nearZ, farZ);
} }
ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q) { ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q) {