From 789dca2ab369a003b35186c4218a44e68c86e2e5 Mon Sep 17 00:00:00 2001 From: Christopher Bruns Date: Sat, 31 Oct 2015 07:46:36 -0400 Subject: [PATCH] Refactor stereo 3d projection matrix calculations to use VSMatrix. --- src/gl/renderer/gl_renderer.h | 2 +- src/gl/scene/gl_scene.cpp | 9 ++++----- src/gl/stereo3d/gl_stereo3d.cpp | 26 ++++++------------------- src/gl/stereo3d/gl_stereo3d.h | 2 +- src/gl/stereo3d/gl_stereo_leftright.cpp | 21 ++++++-------------- src/gl/stereo3d/gl_stereo_leftright.h | 2 +- 6 files changed, 19 insertions(+), 43 deletions(-) diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 3374c904a..a388ced35 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -121,7 +121,7 @@ public: void Flush() {} void SetProjection(float fov, float ratio, float fovratio); - void SetProjection(FLOATTYPE matrix[4][4]); // raw matrix input from stereo 3d modes + void SetProjection(VSMatrix matrix); // raw matrix input from stereo 3d modes void SetViewMatrix(fixed_t viewx, fixed_t viewy, fixed_t viewz, bool mirror, bool planemirror); void ProcessScene(bool toscreen = false); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 6c04b9e39..d94748f6d 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -257,9 +257,10 @@ void FGLRenderer::SetProjection(float fov, float ratio, float fovratio) } // raw matrix input from stereo 3d modes -void FGLRenderer::SetProjection(FLOATTYPE matrix[4][4]) +void FGLRenderer::SetProjection(VSMatrix matrix) { - gl_RenderState.mProjectionMatrix.loadMatrix(&matrix[0][0]); + gl_RenderState.mProjectionMatrix.loadIdentity(); + gl_RenderState.mProjectionMatrix.multMatrix(matrix); gl_RenderState.Set2DMode(false); } @@ -812,7 +813,6 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo retval = viewsector; // Render (potentially) multiple views for stereo 3d - FLOATTYPE projectionMatrix[4][4]; float viewShift[3]; const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode(); stereo3dMode.SetUp(); @@ -824,8 +824,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo SetViewport(bounds); mCurrentFoV = fov; // Stereo mode specific perspective projection - (*eye)->GetProjection(fov, ratio, fovratio, projectionMatrix); - SetProjection(projectionMatrix); + SetProjection( (*eye)->GetProjection(fov, ratio, fovratio) ); // SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper SetViewAngle(viewangle); // Stereo mode specific viewpoint adjustment - temporarily shifts global viewx, viewy, viewz diff --git a/src/gl/stereo3d/gl_stereo3d.cpp b/src/gl/stereo3d/gl_stereo3d.cpp index e053266b7..bc006a2f9 100644 --- a/src/gl/stereo3d/gl_stereo3d.cpp +++ b/src/gl/stereo3d/gl_stereo3d.cpp @@ -6,29 +6,15 @@ namespace s3d { /* virtual */ -void EyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE m[4][4]) const +VSMatrix EyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio) const { + VSMatrix result; + // Lifted from gl_scene.cpp FGLRenderer::SetProjection() - double fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)); - const FLOATTYPE zNear = 5.0; - const FLOATTYPE zFar = 65536.0; + float fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)); + result.perspective(fovy, aspectRatio, 5.f, 65536.f); - double radians = fovy / 2 * M_PI / 180; - - FLOATTYPE deltaZ = zFar - zNear; - double sine = sin(radians); - if ((deltaZ == 0) || (sine == 0) || (aspectRatio == 0)) { - return; - } - FLOATTYPE cotangent = FLOATTYPE(cos(radians) / sine); - - memset(m, 0, 16*sizeof(FLOATTYPE)); - m[0][0] = cotangent / aspectRatio; - m[1][1] = cotangent; - m[2][2] = -(zFar + zNear) / deltaZ; - m[2][3] = -1; - m[3][2] = -2 * zNear * zFar / deltaZ; - m[3][3] = 0; + return result; } /* virtual */ diff --git a/src/gl/stereo3d/gl_stereo3d.h b/src/gl/stereo3d/gl_stereo3d.h index 6421b2a9e..8cfe886ac 100644 --- a/src/gl/stereo3d/gl_stereo3d.h +++ b/src/gl/stereo3d/gl_stereo3d.h @@ -24,7 +24,7 @@ class EyePose public: EyePose() {} virtual ~EyePose() {} - virtual void GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE outMatrix[4][4]) const; + virtual VSMatrix GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio) const; virtual Viewport GetViewport(const Viewport& fullViewport) const; virtual void GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const; virtual void SetUp() const {}; diff --git a/src/gl/stereo3d/gl_stereo_leftright.cpp b/src/gl/stereo3d/gl_stereo_leftright.cpp index 58cbb086e..f93edb38a 100644 --- a/src/gl/stereo3d/gl_stereo_leftright.cpp +++ b/src/gl/stereo3d/gl_stereo_leftright.cpp @@ -11,7 +11,7 @@ namespace s3d { /* virtual */ -void ShiftedEyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE m[4][4]) const +VSMatrix ShiftedEyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio) const { // Lifted from gl_scene.cpp FGLRenderer::SetProjection() FLOATTYPE fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)); @@ -20,10 +20,10 @@ void ShiftedEyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTY // For stereo 3D, use asymmetric frustum shift in projection matrix // Q: shouldn't shift vary with roll angle, at least for desktop display? - // A: (lab) roll is not measured on desktop display (yet) + // A: No. (lab) roll is not measured on desktop display (yet) double frustumShift = zNear * shift / vr_screendist; // meters cancel // double frustumShift = 0; // Turning off shift for debugging - double fH = tan(fovy / 360 * M_PI) * zNear; + double fH = tan(DEG2RAD(fovy/2)) * zNear; double fW = fH * aspectRatio; // Emulate glFrustum command: // glFrustum(-fW - frustumShift, fW - frustumShift, -fH, fH, zNear, zFar); @@ -31,19 +31,10 @@ void ShiftedEyePose::GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTY double right = fW - frustumShift; double bottom = -fH; double top = fH; - double deltaZ = zFar - zNear; - memset(m, 0, 16 * sizeof(FLOATTYPE)); // set all elements to zero, cleverly - - // https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml - m[0][0] = 2 * zNear / (right - left); - m[1][1] = 2 * zNear / (top - bottom); - m[2][2] = -(zFar + zNear) / deltaZ; - m[2][3] = -1; - m[3][2] = -2 * zNear * zFar / deltaZ; - // m[3][3] = 0; // redundant - // m[2][1] = (top + bottom) / (top - bottom); // zero for the cases I know of... - m[2][0] = (right + left) / (right - left); // asymmetric shift is in this term + VSMatrix result(1); + result.frustum(left, right, bottom, top, zNear, zFar); + return result; } diff --git a/src/gl/stereo3d/gl_stereo_leftright.h b/src/gl/stereo3d/gl_stereo_leftright.h index 228b6459f..f256ced33 100644 --- a/src/gl/stereo3d/gl_stereo_leftright.h +++ b/src/gl/stereo3d/gl_stereo_leftright.h @@ -12,7 +12,7 @@ public: ShiftedEyePose(FLOATTYPE shift) : shift(shift) {}; FLOATTYPE getShift() const { return shift; } void setShift(FLOATTYPE shift) { this->shift = shift; } - virtual void GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio, FLOATTYPE outMatrix[4][4]) const; + virtual VSMatrix GetProjection(FLOATTYPE fov, FLOATTYPE aspectRatio, FLOATTYPE fovRatio) const; virtual void GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const; protected: FLOATTYPE shift;