diff --git a/CMakeLists.txt b/CMakeLists.txt index ecfece342d..34cf8b39d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1073,6 +1073,8 @@ if(ANDROID) Common/VR/VRFramebuffer.h Common/VR/VRInput.cpp Common/VR/VRInput.h + Common/VR/VRMath.cpp + Common/VR/VRMath.h Common/VR/VRRenderer.cpp Common/VR/VRRenderer.h ) diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 3b15a90c08..be535e606c 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -12,6 +12,10 @@ #include #include +double FromXrTime(const XrTime time) { + return (time * 1e-9); +} + /* ================================================================================ @@ -20,7 +24,6 @@ ovrFramebuffer ================================================================================ */ - void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) { frameBuffer->Width = 0; frameBuffer->Height = 0; @@ -343,193 +346,3 @@ int ovrApp_HandleXrEvents(ovrApp* app) { } return recenter; } - -/* -================================================================================ - -ovrMatrix4f - -================================================================================ -*/ - -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_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; -} - - -/// 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; -} - -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); -} - -XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v) { - 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; - return out; -} - -/* -================================================================================ - -ovrTrackedController - -================================================================================ -*/ - -void ovrTrackedController_Clear(ovrTrackedController* controller) { - controller->Active = false; - controller->Pose = XrPosef_Identity(); -} diff --git a/Common/VR/VRFramebuffer.h b/Common/VR/VRFramebuffer.h index 1ede50a807..90e14a2030 100644 --- a/Common/VR/VRFramebuffer.h +++ b/Common/VR/VRFramebuffer.h @@ -10,8 +10,6 @@ #include #include -#define MATH_PI 3.14159265358979323846f - #define ALOGE(...) printf(__VA_ARGS__) #define ALOGV(...) printf(__VA_ARGS__) @@ -55,11 +53,6 @@ typedef struct { ovrFramebuffer FrameBuffer[ovrMaxNumEyes]; } ovrRenderer; -typedef struct { - int Active; - XrPosef Pose; -} ovrTrackedController; - typedef struct { int Focused; @@ -83,14 +76,8 @@ typedef struct { int TouchPadDownLastFrame; ovrRenderer Renderer; - ovrTrackedController TrackedController[2]; } ovrApp; - -typedef struct { - float M[4][4]; -} ovrMatrix4f; - typedef struct { uint64_t frameIndex; ovrApp appState; @@ -114,175 +101,3 @@ void ovrRenderer_Create( int suggestedEyeTextureWidth, int suggestedEyeTextureHeight); void ovrRenderer_Destroy(ovrRenderer* renderer); - -void ovrTrackedController_Clear(ovrTrackedController* controller); - -ovrMatrix4f ovrMatrix4f_Multiply(const ovrMatrix4f* a, const ovrMatrix4f* b); -ovrMatrix4f ovrMatrix4f_CreateRotation(const float radiansX, const float radiansY, const float radiansZ); -ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q); -ovrMatrix4f ovrMatrix4f_CreateProjectionFov( - const float fovDegreesX, - const float fovDegreesY, - const float offsetX, - const float offsetY, - const float nearZ, - const float farZ); - -static inline 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]); -} - -static inline 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; -} - - -XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v); - - -/// THESE METHODS HAVE ORIGIN IN openxr_oculus_helpers.h - -static inline double FromXrTime(const XrTime time) { - return (time * 1e-9); -} - -static inline XrTime ToXrTime(const double timeInSeconds) { - return (timeInSeconds * 1e9); -} - -static inline 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; -} - -static inline float XrVector3f_LengthSquared(const XrVector3f v) { - return v.x * v.x + v.y * v.y + v.z * v.z;; -} - -static inline float XrVector3f_Length(const XrVector3f v) { - return sqrtf(XrVector3f_LengthSquared(v)); -} - -static inline XrVector3f XrVector3f_ScalarMultiply(const XrVector3f v, float scale) { - XrVector3f u; - u.x = v.x * scale; - u.y = v.y * scale; - u.z = v.z * scale; - return u; -} - -static inline XrVector3f XrVector3f_Normalized(const XrVector3f v) { - float rcpLen = 1.0f / XrVector3f_Length(v); - return XrVector3f_ScalarMultiply(v, rcpLen); -} - -static inline XrQuaternionf XrQuaternionf_CreateFromVectorAngle( - const XrVector3f axis, - const float angle) { - XrQuaternionf r; - if (XrVector3f_LengthSquared(axis) == 0.0f) { - r.x = 0; - r.y = 0; - r.z = 0; - r.w = 1; - return r; - } - - XrVector3f unitAxis = XrVector3f_Normalized(axis); - float sinHalfAngle = sinf(angle * 0.5f); - - r.w = cosf(angle * 0.5f); - r.x = unitAxis.x * sinHalfAngle; - r.y = unitAxis.y * sinHalfAngle; - r.z = unitAxis.z * sinHalfAngle; - return r; -} - -static inline XrQuaternionf XrQuaternionf_Multiply(const XrQuaternionf a, const XrQuaternionf b) { - XrQuaternionf c; - c.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y; - c.y = a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x; - c.z = a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w; - c.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z; - return c; -} - -static inline XrQuaternionf XrQuaternionf_Inverse(const XrQuaternionf q) { - XrQuaternionf r; - r.x = -q.x; - r.y = -q.y; - r.z = -q.z; - r.w = q.w; - return r; -} - -static inline XrVector3f XrQuaternionf_Rotate(const XrQuaternionf a, const XrVector3f v) { - XrVector3f r; - XrQuaternionf q = {v.x, v.y, v.z, 0.0f}; - XrQuaternionf aq = XrQuaternionf_Multiply(a, q); - XrQuaternionf aInv = XrQuaternionf_Inverse(a); - XrQuaternionf aqaInv = XrQuaternionf_Multiply(aq, aInv); - r.x = aqaInv.x; - r.y = aqaInv.y; - r.z = aqaInv.z; - return r; -} - -static inline 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; -} - -static inline XrVector3f XrPosef_Transform(const XrPosef a, const XrVector3f v) { - XrVector3f r0 = XrQuaternionf_Rotate(a.orientation, v); - return XrVector3f_Add(r0, a.position); -} - -static inline 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; -} - -static inline XrPosef XrPosef_Inverse(const XrPosef a) { - XrPosef b; - b.orientation = XrQuaternionf_Inverse(a.orientation); - b.position = XrQuaternionf_Rotate(b.orientation, XrVector3f_ScalarMultiply(a.position, -1.0f)); - return b; -} diff --git a/Common/VR/VRInput.cpp b/Common/VR/VRInput.cpp index 46044a9907..93125604a0 100644 --- a/Common/VR/VRInput.cpp +++ b/Common/VR/VRInput.cpp @@ -40,9 +40,6 @@ XrActionStateVector2f moveJoystickState[2]; float vibration_channel_duration[2] = {0.0f, 0.0f}; float vibration_channel_intensity[2] = {0.0f, 0.0f}; -float radians(float deg) { - return (deg * M_PI) / 180.0; -} unsigned long sys_timeBase = 0; int milliseconds(void) { @@ -58,84 +55,8 @@ int milliseconds(void) { return (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000; } -#ifndef EPSILON -#define EPSILON 0.001f -#endif - -XrVector3f normalizeVec(XrVector3f vec) { - float xxyyzz = vec.x*vec.x + vec.y*vec.y + vec.z*vec.z; - - XrVector3f result; - float invLength = 1.0f / sqrtf(xxyyzz); - result.x = vec.x * invLength; - result.y = vec.y * invLength; - result.z = vec.z * invLength; - return result; -} - -void GetAnglesFromVectors(const XrVector3f forward, const XrVector3f right, const XrVector3f up, vec3_t angles) { - float sr, sp, sy, cr, cp, cy; - - sp = -forward.z; - - float cp_x_cy = forward.x; - float cp_x_sy = forward.y; - float cp_x_sr = -right.z; - float cp_x_cr = up.z; - - float yaw = atan2(cp_x_sy, cp_x_cy); - float roll = atan2(cp_x_sr, cp_x_cr); - - cy = cos(yaw); - sy = sin(yaw); - cr = cos(roll); - sr = sin(roll); - - if (fabs(cy) > EPSILON) { - cp = cp_x_cy / cy; - } else if (fabs(sy) > EPSILON) { - cp = cp_x_sy / sy; - } else if (fabs(sr) > EPSILON) { - cp = cp_x_sr / sr; - } else if (fabs(cr) > EPSILON) { - cp = cp_x_cr / cr; - } else { - cp = cos(asin(sp)); - } - - float pitch = atan2(sp, cp); - - angles[0] = pitch / (M_PI*2.f / 360.f); - angles[1] = yaw / (M_PI*2.f / 360.f); - angles[2] = roll / (M_PI*2.f / 360.f); -} - -void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out) { - - ovrMatrix4f mat = ovrMatrix4f_CreateFromQuaternion( &q ); - - if (rotation[0] != 0.0f || rotation[1] != 0.0f || rotation[2] != 0.0f) { - ovrMatrix4f rot = ovrMatrix4f_CreateRotation(radians(rotation[0]), radians(rotation[1]), radians(rotation[2])); - mat = ovrMatrix4f_Multiply(&mat, &rot); - } - - XrVector4f v1 = {0, 0, -1, 0}; - XrVector4f v2 = {1, 0, 0, 0}; - XrVector4f v3 = {0, 1, 0, 0}; - - XrVector4f forwardInVRSpace = XrVector4f_MultiplyMatrix4f(&mat, &v1); - XrVector4f rightInVRSpace = XrVector4f_MultiplyMatrix4f(&mat, &v2); - XrVector4f upInVRSpace = XrVector4f_MultiplyMatrix4f(&mat, &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 = normalizeVec(forward); - XrVector3f rightNormal = normalizeVec(right); - XrVector3f upNormal = normalizeVec(up); - - GetAnglesFromVectors(forwardNormal, rightNormal, upNormal, out); +XrTime ToXrTime(const double timeInSeconds) { + return (timeInSeconds * 1e9); } void VR_Vibrate( int duration, int chan, float intensity ) { diff --git a/Common/VR/VRInput.h b/Common/VR/VRInput.h index a59d71744d..36b6b37373 100644 --- a/Common/VR/VRInput.h +++ b/Common/VR/VRInput.h @@ -2,13 +2,6 @@ #include "VRBase.h" -// angle indexes -#define PITCH 0 -#define YAW 1 -#define ROLL 2 - -typedef float vec3_t[3]; - typedef enum ovrButton_ { ovrButton_A = 0x00000001, // Set for trigger pulled on the Gear VR and Go Controllers ovrButton_B = 0x00000002, @@ -39,5 +32,3 @@ void IN_VRInit( engine_t *engine ); void IN_VRInputFrame( engine_t* engine ); uint32_t IN_VRGetButtonState( int controllerIndex ); XrVector2f IN_VRGetJoystickState( int controllerIndex ); - -void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out); diff --git a/Common/VR/VRMath.cpp b/Common/VR/VRMath.cpp new file mode 100644 index 0000000000..204e591fad --- /dev/null +++ b/Common/VR/VRMath.cpp @@ -0,0 +1,415 @@ +#include "VRMath.h" + +float ToDegrees(float rad) { + return (float)(rad / M_PI * 180.0f); +} + +float ToRadians(float deg) { + return (float)(deg * M_PI / 180.0f); +} + +/* +================================================================================ + +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 XrPosef_Inverse(const XrPosef a) { + XrPosef b; + b.orientation = XrQuaternionf_Inverse(a.orientation); + b.position = XrQuaternionf_Rotate(b.orientation, XrVector3f_ScalarMultiply(a.position, -1.0f)); + 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); +} + +/* +================================================================================ + +XrQuaternionf + +================================================================================ +*/ + +XrQuaternionf XrQuaternionf_CreateFromVectorAngle(const XrVector3f axis, const float angle) { + XrQuaternionf r; + if (XrVector3f_LengthSquared(axis) == 0.0f) { + r.x = 0; + r.y = 0; + r.z = 0; + r.w = 1; + return r; + } + + XrVector3f unitAxis = XrVector3f_Normalized(axis); + float sinHalfAngle = sinf(angle * 0.5f); + + r.w = cosf(angle * 0.5f); + r.x = unitAxis.x * sinHalfAngle; + r.y = unitAxis.y * sinHalfAngle; + r.z = unitAxis.z * sinHalfAngle; + return r; +} + +XrQuaternionf XrQuaternionf_Inverse(const XrQuaternionf q) { + XrQuaternionf r; + r.x = -q.x; + r.y = -q.y; + r.z = -q.z; + r.w = q.w; + return r; +} + +XrQuaternionf XrQuaternionf_Multiply(const XrQuaternionf a, const XrQuaternionf b) { + XrQuaternionf c; + c.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y; + c.y = a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x; + c.z = a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w; + c.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z; + return c; +} + +XrVector3f XrQuaternionf_Rotate(const XrQuaternionf a, const XrVector3f v) { + XrVector3f r; + XrQuaternionf q = {v.x, v.y, v.z, 0.0f}; + XrQuaternionf aq = XrQuaternionf_Multiply(a, q); + XrQuaternionf aInv = XrQuaternionf_Inverse(a); + XrQuaternionf aqaInv = XrQuaternionf_Multiply(aq, aInv); + r.x = aqaInv.x; + r.y = aqaInv.y; + r.z = aqaInv.z; + return r; +} + +XrVector3f XrQuaternionf_ToEulerAngles(const XrQuaternionf q) { + ovrMatrix4f m = ovrMatrix4f_CreateFromQuaternion( &q ); + return ovrMatrix4f_ToEulerAngles(&m); +} + +/* +================================================================================ + +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; + + sp = -forward.z; + + float cp_x_cy = forward.x; + float cp_x_sy = forward.y; + float cp_x_sr = -right.z; + float cp_x_cr = up.z; + + float yaw = atan2(cp_x_sy, cp_x_cy); + float roll = atan2(cp_x_sr, cp_x_cr); + + cy = cos(yaw); + sy = sin(yaw); + cr = cos(roll); + sr = sin(roll); + + if (fabs(cy) > EPSILON) { + cp = cp_x_cy / cy; + } else if (fabs(sy) > EPSILON) { + cp = cp_x_sy / sy; + } else if (fabs(sr) > EPSILON) { + cp = cp_x_sr / sr; + } else if (fabs(cr) > EPSILON) { + cp = cp_x_cr / cr; + } else { + cp = cos(asin(sp)); + } + + float pitch = atan2(sp, cp); + + XrVector3f angles; + angles.x = ToDegrees(pitch); + angles.y = ToDegrees(yaw); + angles.z = ToDegrees(roll); + return angles; +} + +XrVector3f XrVector3f_Normalized(const XrVector3f v) { + float rcpLen = 1.0f / XrVector3f_Length(v); + return XrVector3f_ScalarMultiply(v, rcpLen); +} + +XrVector3f XrVector3f_ScalarMultiply(const XrVector3f v, float scale) { + XrVector3f u; + u.x = v.x * scale; + u.y = v.y * scale; + u.z = v.z * scale; + return u; +} + +XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v) { + 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; + return out; +} diff --git a/Common/VR/VRMath.h b/Common/VR/VRMath.h new file mode 100644 index 0000000000..c0ccb36aac --- /dev/null +++ b/Common/VR/VRMath.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +#ifndef EPSILON +#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 fovDegreesX, const float fovDegreesY, const float offsetX, const float offsetY, 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); +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); + +// 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); diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index bf08e126a7..3cf9b9c5ac 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -18,10 +18,8 @@ int vrConfig[VR_CONFIG_MAX] = {}; float menuYaw = 0; float recenterYaw = 0; -vec3_t hmdorientation; -vec3_t hmdposition; - -extern float radians(float deg); +XrVector3f hmdorientation; +XrVector3f hmdposition; void VR_UpdateStageBounds(ovrApp* pappState) { XrExtent2Df stageBounds = {}; @@ -135,10 +133,9 @@ void VR_Recenter(engine_t* engine) { XrSpaceLocation loc = {}; loc.type = XR_TYPE_SPACE_LOCATION; OXR(xrLocateSpace(engine->appState.HeadSpace, engine->appState.CurrentSpace, engine->predictedDisplayTime, &loc)); - vec3_t rotation = {0, 0, 0}; - QuatToYawPitchRoll(loc.pose.orientation, rotation, hmdorientation); + hmdorientation = XrQuaternionf_ToEulerAngles(loc.pose.orientation); - recenterYaw += radians(hmdorientation[YAW]); + recenterYaw += ToRadians(hmdorientation.y); spaceCreateInfo.poseInReferenceSpace.orientation.x = 0; spaceCreateInfo.poseInReferenceSpace.orientation.y = sin(recenterYaw / 2); spaceCreateInfo.poseInReferenceSpace.orientation.z = 0; @@ -301,11 +298,8 @@ void VR_BeginFrame( engine_t* engine ) { } // Update HMD and controllers - vec3_t rotation = {0, 0, 0}; - QuatToYawPitchRoll(invViewTransform[0].orientation, rotation, hmdorientation); - hmdposition[0] = invViewTransform[0].position.x; - hmdposition[1] = invViewTransform[0].position.y; - hmdposition[2] = invViewTransform[0].position.z; + hmdorientation = XrQuaternionf_ToEulerAngles(invViewTransform[0].orientation); + hmdposition = invViewTransform[0].position; IN_VRInputFrame(engine); engine->appState.LayerCount = 0; @@ -339,7 +333,7 @@ void VR_EndFrame( engine_t* engine ) { XrCompositionLayerProjectionView projection_layer_elements[2] = {}; int vrMode = vrConfig[VR_CONFIG_MODE]; if ((vrMode == VR_MODE_MONO_6DOF) || (vrMode == VR_MODE_STEREO_6DOF)) { - menuYaw = hmdorientation[YAW]; + menuYaw = hmdorientation.y; for (int eye = 0; eye < ovrMaxNumEyes; eye++) { XrFovf fov = projections[eye].fov; @@ -391,14 +385,14 @@ void VR_EndFrame( engine_t* engine ) { cylinder_layer.subImage.imageArrayIndex = 0; const XrVector3f axis = {0.0f, 1.0f, 0.0f}; XrVector3f pos = { - invViewTransform[0].position.x - sin(radians(menuYaw)) * 6.0f, + invViewTransform[0].position.x - sin(ToRadians(menuYaw)) * 6.0f, invViewTransform[0].position.y, - invViewTransform[0].position.z - cos(radians(menuYaw)) * 6.0f + invViewTransform[0].position.z - cos(ToRadians(menuYaw)) * 6.0f }; - cylinder_layer.pose.orientation = XrQuaternionf_CreateFromVectorAngle(axis, radians(menuYaw)); + cylinder_layer.pose.orientation = XrQuaternionf_CreateFromVectorAngle(axis, ToRadians(menuYaw)); cylinder_layer.pose.position = pos; cylinder_layer.radius = 12.0f; - cylinder_layer.centralAngle = MATH_PI * 0.5f; + cylinder_layer.centralAngle = M_PI * 0.5f; cylinder_layer.aspectRatio = height / (float)width; engine->appState.Layers[engine->appState.LayerCount++].Cylinder = cylinder_layer; @@ -446,7 +440,7 @@ void VR_BindFramebuffer( engine_t* engine, int eye ) { ovrMatrix4f VR_GetMatrix( VRMatrix matrix ) { ovrMatrix4f output; if (matrix == VR_PROJECTION_MATRIX_HUD) { - float hudScale = radians(15.0f); + float hudScale = ToRadians(15.0f); output = ovrMatrix4f_CreateProjectionFov(-hudScale, hudScale, hudScale, -hudScale, 1.0f, 0.0f ); } else if ((matrix == VR_PROJECTION_MATRIX_LEFT_EYE) || (matrix == VR_PROJECTION_MATRIX_RIGHT_EYE)) { XrFovf fov = matrix == VR_PROJECTION_MATRIX_LEFT_EYE ? projections[0].fov : projections[1].fov; @@ -474,20 +468,19 @@ ovrMatrix4f VR_GetMatrix( VRMatrix matrix ) { } // create updated quaternion - if (mx + my + mz < 3 - 0.001f) { - vec3_t rotation = {0, 0, 0}; - QuatToYawPitchRoll(invView.orientation, rotation, rotation); - XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mx * radians(rotation[0])); - XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, my * radians(rotation[1])); - XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mz * radians(rotation[2])); + if (mx + my + mz < 3 - EPSILON) { + XrVector3f rotation = XrQuaternionf_ToEulerAngles(invView.orientation); + XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mx * ToRadians(rotation.x)); + XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, my * ToRadians(rotation.y)); + XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mz * ToRadians(rotation.z)); invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw)); } output = ovrMatrix4f_CreateFromQuaternion(&invView.orientation); if (vrConfig[VR_CONFIG_6DOF]) { - output.M[0][3] -= hmdposition[0] * (vrConfig[VR_CONFIG_MIRROR_AXIS_X] ? -1.0f : 1.0f); - output.M[1][3] -= hmdposition[1] * (vrConfig[VR_CONFIG_MIRROR_AXIS_Y] ? -1.0f : 1.0f); - output.M[2][3] -= hmdposition[2] * (vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f); + output.M[0][3] -= hmdposition.x * (vrConfig[VR_CONFIG_MIRROR_AXIS_X] ? -1.0f : 1.0f); + output.M[1][3] -= hmdposition.y * (vrConfig[VR_CONFIG_MIRROR_AXIS_Y] ? -1.0f : 1.0f); + output.M[2][3] -= hmdposition.z * (vrConfig[VR_CONFIG_MIRROR_AXIS_Z] ? -1.0f : 1.0f); } } else { assert(false); diff --git a/Common/VR/VRRenderer.h b/Common/VR/VRRenderer.h index d417dce09d..70ac5b288c 100644 --- a/Common/VR/VRRenderer.h +++ b/Common/VR/VRRenderer.h @@ -1,6 +1,7 @@ #pragma once #include "VRFramebuffer.h" +#include "VRMath.h" enum VRConfig { VR_CONFIG_MODE,