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;
}
//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;
ovrApp_HandleXrEvents(&engine->appState);
if (engine->appState.SessionActive == GL_FALSE) {
@ -395,16 +389,27 @@ void VR_DrawFrame( engine_t* engine ) {
projections));
//
XrFovf fov;
XrPosef viewTransform[2];
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
XrPosef xfHeadFromEye = projections[eye].pose;
XrPosef xfStageFromEye = XrPosef_Multiply(xfStageFromHead, xfHeadFromEye);
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;
}
//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;
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));
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
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));
projection_layer_elements[eye].subImage.swapchain = frameBuffer->ColorSwapChain.Handle;

View file

@ -465,82 +465,76 @@ ovrMatrix4f
================================================================================
*/
ovrMatrix4f ovrMatrix4f_CreateProjection(
const float minX,
const float maxX,
float const minY,
const float maxY,
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
const float angleLeft,
const float angleRight,
const float angleUp,
const float angleDown,
const float nearZ,
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) {
// place the far plane at infinity
out.M[0][0] = 2 * nearZ / width;
out.M[0][1] = 0;
out.M[0][2] = (maxX + minX) / width;
out.M[0][3] = 0;
result.M[0][0] = 2 / tanAngleWidth;
result.M[0][1] = 0;
result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result.M[0][3] = 0;
out.M[1][0] = 0;
out.M[1][1] = 2 * nearZ / height;
out.M[1][2] = (maxY + minY) / height;
out.M[1][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;
out.M[2][0] = 0;
out.M[2][1] = 0;
out.M[2][2] = -1;
out.M[2][3] = -(nearZ + offsetZ);
result.M[2][0] = 0;
result.M[2][1] = 0;
result.M[2][2] = -1;
result.M[2][3] = -(nearZ + offsetZ);
out.M[3][0] = 0;
out.M[3][1] = 0;
out.M[3][2] = -1;
out.M[3][3] = 0;
result.M[3][0] = 0;
result.M[3][1] = 0;
result.M[3][2] = -1;
result.M[3][3] = 0;
} else {
// normal projection
out.M[0][0] = 2 * nearZ / width;
out.M[0][1] = 0;
out.M[0][2] = (maxX + minX) / width;
out.M[0][3] = 0;
result.M[0][0] = 2 / tanAngleWidth;
result.M[0][1] = 0;
result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result.M[0][3] = 0;
out.M[1][0] = 0;
out.M[1][1] = 2 * nearZ / height;
out.M[1][2] = (maxY + minY) / height;
out.M[1][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;
out.M[2][0] = 0;
out.M[2][1] = 0;
out.M[2][2] = -(farZ + offsetZ) / (farZ - nearZ);
out.M[2][3] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
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);
out.M[3][0] = 0;
out.M[3][1] = 0;
out.M[3][2] = -1;
out.M[3][3] = 0;
result.M[3][0] = 0;
result.M[3][1] = 0;
result.M[3][2] = -1;
result.M[3][3] = 0;
}
return out;
}
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);
return result;
}
ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q) {