OpenXR - Get rid of ovrMatrix4f structure

This commit is contained in:
Lubos 2022-11-06 20:42:28 +01:00
parent 3e0b598da1
commit 637bb57bc6
5 changed files with 136 additions and 311 deletions

View file

@ -9,6 +9,8 @@
#endif
#include "Common/GPU/Vulkan/VulkanContext.h"
#include "Common/Math/lin/matrix4x4.h"
#include "Core/HLE/sceDisplay.h"
#include "Core/Config.h"
#include "Core/KeyMap.h"
@ -584,15 +586,13 @@ void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye) {
float* dst[] = {leftEye, rightEye};
VRMatrix enums[] = {VR_PROJECTION_MATRIX_LEFT_EYE, VR_PROJECTION_MATRIX_RIGHT_EYE};
for (int index = 0; index < 2; index++) {
ovrMatrix4f hmdProjection = VR_GetMatrix(enums[index]);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((hmdProjection.M[i][j] > 0) != (projMatrix[i * 4 + j] > 0)) {
hmdProjection.M[i][j] *= -1.0f;
}
float* hmdProjection = VR_GetMatrix(enums[index]);
for (int i = 0; i < 16; i++) {
if ((hmdProjection[i] > 0) != (projMatrix[i] > 0)) {
hmdProjection[i] *= -1.0f;
}
}
memcpy(dst[index], hmdProjection.M, 16 * sizeof(float));
memcpy(dst[index], hmdProjection, 16 * sizeof(float));
}
}
@ -602,14 +602,15 @@ void UpdateVRView(float* leftEye, float* rightEye) {
for (int index = 0; index < 2; index++) {
// Get view matrix from the game
ovrMatrix4f gameView;
memcpy(gameView.M, dst[index], 16 * sizeof(float));
Lin::Matrix4x4 gameView = {};
memcpy(gameView.m, dst[index], 16 * sizeof(float));
// Get view matrix from the headset
ovrMatrix4f hmdView = VR_GetMatrix(enums[index]);
Lin::Matrix4x4 hmdView = {};
memcpy(hmdView.m, VR_GetMatrix(enums[index]), 16 * sizeof(float));
// Combine the matrices
ovrMatrix4f renderView = ovrMatrix4f_Multiply(&hmdView, &gameView);
memcpy(dst[index], renderView.M, 16 * sizeof(float));
Lin::Matrix4x4 renderView = hmdView * gameView;
memcpy(dst[index], renderView.m, 16 * sizeof(float));
}
}

View file

@ -1,6 +1,7 @@
#define _USE_MATH_DEFINES
#include <cmath>
#include <cstring>
#include "VRMath.h"
@ -15,240 +16,21 @@ float ToRadians(float deg) {
/*
================================================================================
ovrMatrix4f
================================================================================
*/
float ovrMatrix4f_Minor(const ovrMatrix4f* m, int r0, int r1, int r2, int c0, int c1, int c2) {
return m->M[r0][c0] * (m->M[r1][c1] * m->M[r2][c2] - m->M[r2][c1] * m->M[r1][c2]) -
m->M[r0][c1] * (m->M[r1][c0] * m->M[r2][c2] - m->M[r2][c0] * m->M[r1][c2]) +
m->M[r0][c2] * (m->M[r1][c0] * m->M[r2][c1] - m->M[r2][c0] * m->M[r1][c1]);
}
ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q) {
const float ww = q->w * q->w;
const float xx = q->x * q->x;
const float yy = q->y * q->y;
const float zz = q->z * q->z;
ovrMatrix4f out;
out.M[0][0] = ww + xx - yy - zz;
out.M[0][1] = 2 * (q->x * q->y - q->w * q->z);
out.M[0][2] = 2 * (q->x * q->z + q->w * q->y);
out.M[0][3] = 0;
out.M[1][0] = 2 * (q->x * q->y + q->w * q->z);
out.M[1][1] = ww - xx + yy - zz;
out.M[1][2] = 2 * (q->y * q->z - q->w * q->x);
out.M[1][3] = 0;
out.M[2][0] = 2 * (q->x * q->z - q->w * q->y);
out.M[2][1] = 2 * (q->y * q->z + q->w * q->x);
out.M[2][2] = ww - xx - yy + zz;
out.M[2][3] = 0;
out.M[3][0] = 0;
out.M[3][1] = 0;
out.M[3][2] = 0;
out.M[3][3] = 1;
return out;
}
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
const float angleLeft,
const float angleRight,
const float angleUp,
const float angleDown,
const float nearZ,
const float farZ) {
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
result.M[0][0] = 2 / tanAngleWidth;
result.M[0][1] = 0;
result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result.M[0][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;
result.M[2][0] = 0;
result.M[2][1] = 0;
result.M[2][2] = -1;
result.M[2][3] = -(nearZ + offsetZ);
result.M[3][0] = 0;
result.M[3][1] = 0;
result.M[3][2] = -1;
result.M[3][3] = 0;
} else {
// normal projection
result.M[0][0] = 2 / tanAngleWidth;
result.M[0][1] = 0;
result.M[0][2] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result.M[0][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;
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);
result.M[3][0] = 0;
result.M[3][1] = 0;
result.M[3][2] = -1;
result.M[3][3] = 0;
}
return result;
}
ovrMatrix4f ovrMatrix4f_CreateRotation(const float radiansX, const float radiansY, const float radiansZ) {
const float sinX = sinf(radiansX);
const float cosX = cosf(radiansX);
const ovrMatrix4f rotationX = {
{{1, 0, 0, 0}, {0, cosX, -sinX, 0}, {0, sinX, cosX, 0}, {0, 0, 0, 1}}};
const float sinY = sinf(radiansY);
const float cosY = cosf(radiansY);
const ovrMatrix4f rotationY = {
{{cosY, 0, sinY, 0}, {0, 1, 0, 0}, {-sinY, 0, cosY, 0}, {0, 0, 0, 1}}};
const float sinZ = sinf(radiansZ);
const float cosZ = cosf(radiansZ);
const ovrMatrix4f rotationZ = {
{{cosZ, -sinZ, 0, 0}, {sinZ, cosZ, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}};
const ovrMatrix4f rotationXY = ovrMatrix4f_Multiply(&rotationY, &rotationX);
return ovrMatrix4f_Multiply(&rotationZ, &rotationXY);
}
ovrMatrix4f ovrMatrix4f_Inverse(const ovrMatrix4f* m) {
const float rcpDet = 1.0f /
(m->M[0][0] * ovrMatrix4f_Minor(m, 1, 2, 3, 1, 2, 3) -
m->M[0][1] * ovrMatrix4f_Minor(m, 1, 2, 3, 0, 2, 3) +
m->M[0][2] * ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 3) -
m->M[0][3] * ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 2));
ovrMatrix4f out;
out.M[0][0] = ovrMatrix4f_Minor(m, 1, 2, 3, 1, 2, 3) * rcpDet;
out.M[0][1] = -ovrMatrix4f_Minor(m, 0, 2, 3, 1, 2, 3) * rcpDet;
out.M[0][2] = ovrMatrix4f_Minor(m, 0, 1, 3, 1, 2, 3) * rcpDet;
out.M[0][3] = -ovrMatrix4f_Minor(m, 0, 1, 2, 1, 2, 3) * rcpDet;
out.M[1][0] = -ovrMatrix4f_Minor(m, 1, 2, 3, 0, 2, 3) * rcpDet;
out.M[1][1] = ovrMatrix4f_Minor(m, 0, 2, 3, 0, 2, 3) * rcpDet;
out.M[1][2] = -ovrMatrix4f_Minor(m, 0, 1, 3, 0, 2, 3) * rcpDet;
out.M[1][3] = ovrMatrix4f_Minor(m, 0, 1, 2, 0, 2, 3) * rcpDet;
out.M[2][0] = ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 3) * rcpDet;
out.M[2][1] = -ovrMatrix4f_Minor(m, 0, 2, 3, 0, 1, 3) * rcpDet;
out.M[2][2] = ovrMatrix4f_Minor(m, 0, 1, 3, 0, 1, 3) * rcpDet;
out.M[2][3] = -ovrMatrix4f_Minor(m, 0, 1, 2, 0, 1, 3) * rcpDet;
out.M[3][0] = -ovrMatrix4f_Minor(m, 1, 2, 3, 0, 1, 2) * rcpDet;
out.M[3][1] = ovrMatrix4f_Minor(m, 0, 2, 3, 0, 1, 2) * rcpDet;
out.M[3][2] = -ovrMatrix4f_Minor(m, 0, 1, 3, 0, 1, 2) * rcpDet;
out.M[3][3] = ovrMatrix4f_Minor(m, 0, 1, 2, 0, 1, 2) * rcpDet;
return out;
}
/// Use left-multiplication to accumulate transformations.
ovrMatrix4f ovrMatrix4f_Multiply(const ovrMatrix4f* a, const ovrMatrix4f* b) {
ovrMatrix4f out;
out.M[0][0] = a->M[0][0] * b->M[0][0] + a->M[0][1] * b->M[1][0] + a->M[0][2] * b->M[2][0] +
a->M[0][3] * b->M[3][0];
out.M[1][0] = a->M[1][0] * b->M[0][0] + a->M[1][1] * b->M[1][0] + a->M[1][2] * b->M[2][0] +
a->M[1][3] * b->M[3][0];
out.M[2][0] = a->M[2][0] * b->M[0][0] + a->M[2][1] * b->M[1][0] + a->M[2][2] * b->M[2][0] +
a->M[2][3] * b->M[3][0];
out.M[3][0] = a->M[3][0] * b->M[0][0] + a->M[3][1] * b->M[1][0] + a->M[3][2] * b->M[2][0] +
a->M[3][3] * b->M[3][0];
out.M[0][1] = a->M[0][0] * b->M[0][1] + a->M[0][1] * b->M[1][1] + a->M[0][2] * b->M[2][1] +
a->M[0][3] * b->M[3][1];
out.M[1][1] = a->M[1][0] * b->M[0][1] + a->M[1][1] * b->M[1][1] + a->M[1][2] * b->M[2][1] +
a->M[1][3] * b->M[3][1];
out.M[2][1] = a->M[2][0] * b->M[0][1] + a->M[2][1] * b->M[1][1] + a->M[2][2] * b->M[2][1] +
a->M[2][3] * b->M[3][1];
out.M[3][1] = a->M[3][0] * b->M[0][1] + a->M[3][1] * b->M[1][1] + a->M[3][2] * b->M[2][1] +
a->M[3][3] * b->M[3][1];
out.M[0][2] = a->M[0][0] * b->M[0][2] + a->M[0][1] * b->M[1][2] + a->M[0][2] * b->M[2][2] +
a->M[0][3] * b->M[3][2];
out.M[1][2] = a->M[1][0] * b->M[0][2] + a->M[1][1] * b->M[1][2] + a->M[1][2] * b->M[2][2] +
a->M[1][3] * b->M[3][2];
out.M[2][2] = a->M[2][0] * b->M[0][2] + a->M[2][1] * b->M[1][2] + a->M[2][2] * b->M[2][2] +
a->M[2][3] * b->M[3][2];
out.M[3][2] = a->M[3][0] * b->M[0][2] + a->M[3][1] * b->M[1][2] + a->M[3][2] * b->M[2][2] +
a->M[3][3] * b->M[3][2];
out.M[0][3] = a->M[0][0] * b->M[0][3] + a->M[0][1] * b->M[1][3] + a->M[0][2] * b->M[2][3] +
a->M[0][3] * b->M[3][3];
out.M[1][3] = a->M[1][0] * b->M[0][3] + a->M[1][1] * b->M[1][3] + a->M[1][2] * b->M[2][3] +
a->M[1][3] * b->M[3][3];
out.M[2][3] = a->M[2][0] * b->M[0][3] + a->M[2][1] * b->M[1][3] + a->M[2][2] * b->M[2][3] +
a->M[2][3] * b->M[3][3];
out.M[3][3] = a->M[3][0] * b->M[0][3] + a->M[3][1] * b->M[1][3] + a->M[3][2] * b->M[2][3] +
a->M[3][3] * b->M[3][3];
return out;
}
XrVector3f ovrMatrix4f_ToEulerAngles(const ovrMatrix4f* m) {
XrVector4f v1 = {0, 0, -1, 0};
XrVector4f v2 = {1, 0, 0, 0};
XrVector4f v3 = {0, 1, 0, 0};
XrVector4f forwardInVRSpace = XrVector4f_MultiplyMatrix4f(m, &v1);
XrVector4f rightInVRSpace = XrVector4f_MultiplyMatrix4f(m, &v2);
XrVector4f upInVRSpace = XrVector4f_MultiplyMatrix4f(m, &v3);
XrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y};
XrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y};
XrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y};
XrVector3f forwardNormal = XrVector3f_Normalized(forward);
XrVector3f rightNormal = XrVector3f_Normalized(right);
XrVector3f upNormal = XrVector3f_Normalized(up);
return XrVector3f_GetAnglesFromVectors(forwardNormal, rightNormal, upNormal);
}
/*
================================================================================
XrPosef
================================================================================
*/
XrPosef XrPosef_Identity() {
XrPosef r;
r.orientation.x = 0;
r.orientation.y = 0;
r.orientation.z = 0;
r.orientation.w = 1;
r.position.x = 0;
r.position.y = 0;
r.position.z = 0;
return r;
XrPosef r;
r.orientation.x = 0;
r.orientation.y = 0;
r.orientation.z = 0;
r.orientation.w = 1;
r.position.x = 0;
r.position.y = 0;
r.position.z = 0;
return r;
}
XrPosef XrPosef_Inverse(const XrPosef a) {
@ -258,18 +40,6 @@ XrPosef XrPosef_Inverse(const XrPosef a) {
return b;
}
XrPosef XrPosef_Multiply(const XrPosef a, const XrPosef b) {
XrPosef c;
c.orientation = XrQuaternionf_Multiply(a.orientation, b.orientation);
c.position = XrPosef_Transform(a, b.position);
return c;
}
XrVector3f XrPosef_Transform(const XrPosef a, const XrVector3f v) {
XrVector3f r0 = XrQuaternionf_Rotate(a.orientation, v);
return XrVector3f_Add(r0, a.position);
}
/*
================================================================================
@ -329,8 +99,56 @@ XrVector3f XrQuaternionf_Rotate(const XrQuaternionf a, const XrVector3f v) {
}
XrVector3f XrQuaternionf_ToEulerAngles(const XrQuaternionf q) {
ovrMatrix4f m = ovrMatrix4f_CreateFromQuaternion( &q );
return ovrMatrix4f_ToEulerAngles(&m);
float M[16];
XrQuaternionf_ToMatrix4f( &q, M);
XrVector4f v1 = {0, 0, -1, 0};
XrVector4f v2 = {1, 0, 0, 0};
XrVector4f v3 = {0, 1, 0, 0};
XrVector4f forwardInVRSpace = XrVector4f_MultiplyMatrix4f(M, &v1);
XrVector4f rightInVRSpace = XrVector4f_MultiplyMatrix4f(M, &v2);
XrVector4f upInVRSpace = XrVector4f_MultiplyMatrix4f(M, &v3);
XrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y};
XrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y};
XrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y};
XrVector3f forwardNormal = XrVector3f_Normalized(forward);
XrVector3f rightNormal = XrVector3f_Normalized(right);
XrVector3f upNormal = XrVector3f_Normalized(up);
return XrVector3f_GetAnglesFromVectors(forwardNormal, rightNormal, upNormal);
}
void XrQuaternionf_ToMatrix4f(const XrQuaternionf* q, float* matrix) {
const float ww = q->w * q->w;
const float xx = q->x * q->x;
const float yy = q->y * q->y;
const float zz = q->z * q->z;
float M[4][4];
M[0][0] = ww + xx - yy - zz;
M[0][1] = 2 * (q->x * q->y - q->w * q->z);
M[0][2] = 2 * (q->x * q->z + q->w * q->y);
M[0][3] = 0;
M[1][0] = 2 * (q->x * q->y + q->w * q->z);
M[1][1] = ww - xx + yy - zz;
M[1][2] = 2 * (q->y * q->z - q->w * q->x);
M[1][3] = 0;
M[2][0] = 2 * (q->x * q->z - q->w * q->y);
M[2][1] = 2 * (q->y * q->z + q->w * q->x);
M[2][2] = ww - xx - yy + zz;
M[2][3] = 0;
M[3][0] = 0;
M[3][1] = 0;
M[3][2] = 0;
M[3][3] = 1;
memcpy(matrix, &M, sizeof(float) * 16);
}
/*
@ -341,22 +159,10 @@ XrVector3f, XrVector4f
================================================================================
*/
float XrVector3f_Length(const XrVector3f v) {
return sqrtf(XrVector3f_LengthSquared(v));
}
float XrVector3f_LengthSquared(const XrVector3f v) {
return v.x * v.x + v.y * v.y + v.z * v.z;;
}
XrVector3f XrVector3f_Add(const XrVector3f u, const XrVector3f v) {
XrVector3f w;
w.x = u.x + v.x;
w.y = u.y + v.y;
w.z = u.z + v.z;
return w;
}
XrVector3f XrVector3f_GetAnglesFromVectors(const XrVector3f forward, const XrVector3f right, const XrVector3f up) {
float sr, sp, sy, cr, cp, cy;
@ -397,7 +203,7 @@ XrVector3f XrVector3f_GetAnglesFromVectors(const XrVector3f forward, const XrVec
}
XrVector3f XrVector3f_Normalized(const XrVector3f v) {
float rcpLen = 1.0f / XrVector3f_Length(v);
float rcpLen = 1.0f / sqrtf(XrVector3f_LengthSquared(v));
return XrVector3f_ScalarMultiply(v, rcpLen);
}
@ -409,11 +215,14 @@ XrVector3f XrVector3f_ScalarMultiply(const XrVector3f v, float scale) {
return u;
}
XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v) {
XrVector4f XrVector4f_MultiplyMatrix4f(const float* m, const XrVector4f* v) {
float M[4][4];
memcpy(&M, m, sizeof(float) * 16);
XrVector4f out;
out.x = a->M[0][0] * v->x + a->M[0][1] * v->y + a->M[0][2] * v->z + a->M[0][3] * v->w;
out.y = a->M[1][0] * v->x + a->M[1][1] * v->y + a->M[1][2] * v->z + a->M[1][3] * v->w;
out.z = a->M[2][0] * v->x + a->M[2][1] * v->y + a->M[2][2] * v->z + a->M[2][3] * v->w;
out.w = a->M[3][0] * v->x + a->M[3][1] * v->y + a->M[3][2] * v->z + a->M[3][3] * v->w;
out.x = M[0][0] * v->x + M[0][1] * v->y + M[0][2] * v->z + M[0][3] * v->w;
out.y = M[1][0] * v->x + M[1][1] * v->y + M[1][2] * v->z + M[1][3] * v->w;
out.z = M[2][0] * v->x + M[2][1] * v->y + M[2][2] * v->z + M[2][3] * v->w;
out.w = M[3][0] * v->x + M[3][1] * v->y + M[3][2] * v->z + M[3][3] * v->w;
return out;
}

View file

@ -7,27 +7,12 @@
#define EPSILON 0.001f
#endif
typedef struct {
float M[4][4];
} ovrMatrix4f;
float ToDegrees(float rad);
float ToRadians(float deg);
// ovrMatrix4f
float ovrMatrix4f_Minor(const ovrMatrix4f* m, int r0, int r1, int r2, int c0, int c1, int c2);
ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q);
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(const float angleLeft, const float angleRight, const float angleUp, const float angleDown, const float nearZ, const float farZ);
ovrMatrix4f ovrMatrix4f_CreateRotation(const float radiansX, const float radiansY, const float radiansZ);
ovrMatrix4f ovrMatrix4f_Inverse(const ovrMatrix4f* m);
ovrMatrix4f ovrMatrix4f_Multiply(const ovrMatrix4f* a, const ovrMatrix4f* b);
XrVector3f ovrMatrix4f_ToEulerAngles(const ovrMatrix4f* m);
// XrPosef
XrPosef XrPosef_Identity();
XrPosef XrPosef_Inverse(const XrPosef a);
XrPosef XrPosef_Multiply(const XrPosef a, const XrPosef b);
XrVector3f XrPosef_Transform(const XrPosef a, const XrVector3f v);
// XrQuaternionf
XrQuaternionf XrQuaternionf_CreateFromVectorAngle(const XrVector3f axis, const float angle);
@ -35,12 +20,11 @@ XrQuaternionf XrQuaternionf_Inverse(const XrQuaternionf q);
XrQuaternionf XrQuaternionf_Multiply(const XrQuaternionf a, const XrQuaternionf b);
XrVector3f XrQuaternionf_Rotate(const XrQuaternionf a, const XrVector3f v);
XrVector3f XrQuaternionf_ToEulerAngles(const XrQuaternionf q);
void XrQuaternionf_ToMatrix4f(const XrQuaternionf* q, float* m);
// XrVector3f, XrVector4f
float XrVector3f_Length(const XrVector3f v);
float XrVector3f_LengthSquared(const XrVector3f v);
XrVector3f XrVector3f_Add(const XrVector3f u, const XrVector3f v);
XrVector3f XrVector3f_GetAnglesFromVectors(const XrVector3f forward, const XrVector3f right, const XrVector3f up);
XrVector3f XrVector3f_Normalized(const XrVector3f v);
XrVector3f XrVector3f_ScalarMultiply(const XrVector3f v, float scale);
XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v);
XrVector4f XrVector4f_MultiplyMatrix4f(const float* m, const XrVector4f* v);

View file

@ -16,7 +16,7 @@ XrPosef invViewTransform[2];
XrFrameState frameState = {};
bool initialized = false;
bool stageSupported = false;
ovrMatrix4f vrMatrix[VR_MATRIX_COUNT];
float vrMatrix[VR_MATRIX_COUNT][16];
int vrConfig[VR_CONFIG_MAX] = {};
float vrConfigFloat[VR_CONFIG_FLOAT_MAX] = {};
@ -306,8 +306,35 @@ bool VR_InitFrame( engine_t* engine ) {
// Update matrices
for (int matrix = 0; matrix < VR_MATRIX_COUNT; matrix++) {
if ((matrix == VR_PROJECTION_MATRIX_LEFT_EYE) || (matrix == VR_PROJECTION_MATRIX_RIGHT_EYE)) {
float nearPlane = VR_GetConfigFloat(VR_CONFIG_FOV_SCALE) / 200.0f;
vrMatrix[matrix] = ovrMatrix4f_CreateProjectionFov(fov.angleLeft, fov.angleRight, fov.angleUp, fov.angleDown, nearPlane, 0.0f );
float nearZ = VR_GetConfigFloat(VR_CONFIG_FOV_SCALE) / 200.0f;
float tanAngleLeft = tanf(fov.angleLeft);
float tanAngleRight = tanf(fov.angleRight);
float tanAngleDown = tanf(fov.angleDown);
float tanAngleUp = tanf(fov.angleUp);
float M[4][4];
M[0][0] = 2 / (tanAngleRight - tanAngleLeft);
M[0][1] = 0;
M[0][2] = (tanAngleRight + tanAngleLeft) / (tanAngleRight - tanAngleLeft);
M[0][3] = 0;
M[1][0] = 0;
M[1][1] = 2 / (tanAngleUp - tanAngleDown);
M[1][2] = (tanAngleUp + tanAngleDown) / (tanAngleUp - tanAngleDown);
M[1][3] = 0;
// place the far plane at infinity
M[2][0] = 0;
M[2][1] = 0;
M[2][2] = -1;
M[2][3] = -(nearZ + nearZ);
M[3][0] = 0;
M[3][1] = 0;
M[3][2] = -1;
M[3][3] = 0;
memcpy(vrMatrix[matrix], M, sizeof(float) * 16);
} else if ((matrix == VR_VIEW_MATRIX_LEFT_EYE) || (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) {
bool flatScreen = false;
XrPosef invView = invViewTransform[0];
@ -340,36 +367,39 @@ bool VR_InitFrame( engine_t* engine ) {
invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw));
}
vrMatrix[matrix] = ovrMatrix4f_CreateFromQuaternion(&invView.orientation);
float M[16];
XrQuaternionf_ToMatrix4f(&invView.orientation, M);
memcpy(&M, M, sizeof(float) * 16);
float scale = VR_GetConfigFloat(VR_CONFIG_6DOF_SCALE);
if (!flatScreen && vrConfig[VR_CONFIG_6DOF_ENABLED]) {
vrMatrix[matrix].M[0][3] -= hmdposition.x * (vrConfig[VR_CONFIG_MIRROR_AXIS_X] ? -1.0f : 1.0f) * scale;
vrMatrix[matrix].M[1][3] -= hmdposition.y * (vrConfig[VR_CONFIG_MIRROR_AXIS_Y] ? -1.0f : 1.0f) * scale;
vrMatrix[matrix].M[2][3] -= hmdposition.z * (vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f) * scale;
M[12] -= hmdposition.x * (vrConfig[VR_CONFIG_MIRROR_AXIS_X] ? -1.0f : 1.0f) * scale;
M[13] -= hmdposition.y * (vrConfig[VR_CONFIG_MIRROR_AXIS_Y] ? -1.0f : 1.0f) * scale;
M[14] -= hmdposition.z * (vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f) * scale;
}
if (fabsf(VR_GetConfigFloat(VR_CONFIG_CAMERA_DISTANCE)) > 0.0f) {
XrVector3f forward = {0.0f, 0.0f, VR_GetConfigFloat(VR_CONFIG_CAMERA_DISTANCE) * scale};
forward = XrQuaternionf_Rotate(invView.orientation, forward);
forward = XrVector3f_ScalarMultiply(forward, vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f);
vrMatrix[matrix].M[0][3] += forward.x;
vrMatrix[matrix].M[1][3] += forward.y;
vrMatrix[matrix].M[2][3] += forward.z;
M[12] += forward.x;
M[13] += forward.y;
M[14] += forward.z;
}
if (fabsf(VR_GetConfigFloat(VR_CONFIG_CAMERA_HEIGHT)) > 0.0f) {
XrVector3f up = {0.0f, -VR_GetConfigFloat(VR_CONFIG_CAMERA_HEIGHT) * scale, 0.0f};
up = XrQuaternionf_Rotate(invView.orientation, up);
up = XrVector3f_ScalarMultiply(up, vrConfig[VR_CONFIG_MIRROR_AXIS_Y] ? -1.0f : 1.0f);
vrMatrix[matrix].M[0][3] += up.x;
vrMatrix[matrix].M[1][3] += up.y;
vrMatrix[matrix].M[2][3] += up.z;
M[12] += up.x;
M[13] += up.y;
M[14] += up.z;
}
if (fabsf(VR_GetConfigFloat(VR_CONFIG_CAMERA_SIDE)) > 0.0f) {
XrVector3f side = {-VR_GetConfigFloat(VR_CONFIG_CAMERA_SIDE) * scale, 0.0f, 0.0f};
side = XrQuaternionf_Rotate(invView.orientation, side);
side = XrVector3f_ScalarMultiply(side, vrConfig[VR_CONFIG_MIRROR_AXIS_X] ? -1.0f : 1.0f);
vrMatrix[matrix].M[0][3] += side.x;
vrMatrix[matrix].M[1][3] += side.y;
vrMatrix[matrix].M[2][3] += side.z;
M[12] += side.x;
M[13] += side.y;
M[14] += side.z;
}
if (vrConfig[VR_CONFIG_HAS_UNIT_SCALE] && (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) {
float dx = fabs(invViewTransform[1].position.x - invViewTransform[0].position.x);
@ -379,10 +409,11 @@ bool VR_InitFrame( engine_t* engine ) {
XrVector3f separation = {ipd * scale, 0.0f, 0.0f};
separation = XrQuaternionf_Rotate(invView.orientation, separation);
separation = XrVector3f_ScalarMultiply(separation, vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f);
vrMatrix[matrix].M[0][3] -= separation.x;
vrMatrix[matrix].M[1][3] -= separation.y;
vrMatrix[matrix].M[2][3] -= separation.z;
M[12] -= separation.x;
M[13] -= separation.y;
M[14] -= separation.z;
}
memcpy(vrMatrix[matrix], M, sizeof(float) * 16);
} else {
assert(false);
}
@ -550,6 +581,6 @@ void* VR_BindFramebuffer(engine_t *engine) {
return ovrFramebuffer_SetCurrent(&engine->appState.Renderer.FrameBuffer[fboIndex]);
}
ovrMatrix4f VR_GetMatrix( VRMatrix matrix ) {
float* VR_GetMatrix( VRMatrix matrix ) {
return vrMatrix[matrix];
}

View file

@ -67,4 +67,4 @@ float VR_GetConfigFloat( VRConfigFloat config );
void VR_SetConfigFloat( VRConfigFloat config, float value );
void* VR_BindFramebuffer(engine_t *engine);
ovrMatrix4f VR_GetMatrix( VRMatrix matrix );
float* VR_GetMatrix( VRMatrix matrix );