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 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);

View file

@ -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

View file

@ -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 */

View file

@ -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 {};

View file

@ -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;
}

View file

@ -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;