Refactor stereo 3d projection matrix calculations to use VSMatrix.

This commit is contained in:
Christopher Bruns 2015-10-31 07:46:36 -04:00
parent d603999ee3
commit 789dca2ab3
6 changed files with 19 additions and 43 deletions

View file

@ -121,7 +121,7 @@ public:
void Flush() {} void Flush() {}
void SetProjection(float fov, float ratio, float fovratio); 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 SetViewMatrix(fixed_t viewx, fixed_t viewy, fixed_t viewz, bool mirror, bool planemirror);
void ProcessScene(bool toscreen = false); void ProcessScene(bool toscreen = false);

View file

@ -257,9 +257,10 @@ void FGLRenderer::SetProjection(float fov, float ratio, float fovratio)
} }
// raw matrix input from stereo 3d modes // 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); gl_RenderState.Set2DMode(false);
} }
@ -812,7 +813,6 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
retval = viewsector; retval = viewsector;
// Render (potentially) multiple views for stereo 3d // Render (potentially) multiple views for stereo 3d
FLOATTYPE projectionMatrix[4][4];
float viewShift[3]; float viewShift[3];
const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode(); const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode();
stereo3dMode.SetUp(); stereo3dMode.SetUp();
@ -824,8 +824,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
SetViewport(bounds); SetViewport(bounds);
mCurrentFoV = fov; mCurrentFoV = fov;
// Stereo mode specific perspective projection // Stereo mode specific perspective projection
(*eye)->GetProjection(fov, ratio, fovratio, projectionMatrix); SetProjection( (*eye)->GetProjection(fov, ratio, fovratio) );
SetProjection(projectionMatrix);
// SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper // SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper
SetViewAngle(viewangle); SetViewAngle(viewangle);
// Stereo mode specific viewpoint adjustment - temporarily shifts global viewx, viewy, viewz // Stereo mode specific viewpoint adjustment - temporarily shifts global viewx, viewy, viewz

View file

@ -6,29 +6,15 @@ namespace s3d {
/* virtual */ /* 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() // Lifted from gl_scene.cpp FGLRenderer::SetProjection()
double fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)); float fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio));
const FLOATTYPE zNear = 5.0; result.perspective(fovy, aspectRatio, 5.f, 65536.f);
const FLOATTYPE zFar = 65536.0;
double radians = fovy / 2 * M_PI / 180; return result;
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;
} }
/* virtual */ /* virtual */

View file

@ -24,7 +24,7 @@ class EyePose
public: public:
EyePose() {} EyePose() {}
virtual ~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 Viewport GetViewport(const Viewport& fullViewport) const;
virtual void GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const; virtual void GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const;
virtual void SetUp() const {}; virtual void SetUp() const {};

View file

@ -11,7 +11,7 @@ namespace s3d {
/* virtual */ /* 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() // Lifted from gl_scene.cpp FGLRenderer::SetProjection()
FLOATTYPE fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)); 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 // For stereo 3D, use asymmetric frustum shift in projection matrix
// Q: shouldn't shift vary with roll angle, at least for desktop display? // 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 = zNear * shift / vr_screendist; // meters cancel
// double frustumShift = 0; // Turning off shift for debugging // 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; double fW = fH * aspectRatio;
// Emulate glFrustum command: // Emulate glFrustum command:
// glFrustum(-fW - frustumShift, fW - frustumShift, -fH, fH, zNear, zFar); // 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 right = fW - frustumShift;
double bottom = -fH; double bottom = -fH;
double top = fH; double top = fH;
double deltaZ = zFar - zNear;
memset(m, 0, 16 * sizeof(FLOATTYPE)); // set all elements to zero, cleverly VSMatrix result(1);
result.frustum(left, right, bottom, top, zNear, zFar);
// https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml return result;
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
} }

View file

@ -12,7 +12,7 @@ public:
ShiftedEyePose(FLOATTYPE shift) : shift(shift) {}; ShiftedEyePose(FLOATTYPE shift) : shift(shift) {};
FLOATTYPE getShift() const { return shift; } FLOATTYPE getShift() const { return shift; }
void setShift(FLOATTYPE shift) { this->shift = 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; virtual void GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const;
protected: protected:
FLOATTYPE shift; FLOATTYPE shift;