From 3ed99f40a6f73853e272109fa9fc73d57d4b9542 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 17 May 2013 10:17:21 -0700 Subject: [PATCH] Working on support for off-axis projection. --- interface/src/Application.cpp | 45 +++++++++++++++++++++++++--- interface/src/Camera.cpp | 10 +++++++ interface/src/Camera.h | 7 +++++ libraries/shared/src/SharedUtil.cpp | 15 ++++++++++ libraries/shared/src/SharedUtil.h | 3 ++ libraries/voxels/src/ViewFrustum.cpp | 11 +++++++ libraries/voxels/src/ViewFrustum.h | 24 ++++++++++----- 7 files changed, 103 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c70b674f38..7d21cdcaa0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -447,7 +447,12 @@ void Application::resizeGL(int width, int height) { } // On window reshape, we need to tell OpenGL about our new setting - gluPerspective(fov,aspectRatio,nearClip,farClip); + float left, right, bottom, top, nearVal, farVal; + glm::vec3 eyeOffset = camera.getEyeOffsetPosition(); + computeOffsetFrustum(fov, aspectRatio, nearClip, farClip, eyeOffset.x, eyeOffset.y, eyeOffset.z, + left, right, bottom, top, nearVal, farVal); + glFrustum(left, right, bottom, top, nearVal, farVal); + glTranslatef(-eyeOffset.x, -eyeOffset.y, -eyeOffset.z); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -542,9 +547,9 @@ void Application::keyPressEvent(QKeyEvent* event) { _audio.startEchoTest(); break; - case Qt::Key_L: - _displayLevels = !_displayLevels; - break; + //case Qt::Key_L: + // _displayLevels = !_displayLevels; + // break; case Qt::Key_E: _myAvatar.setDriveKeys(UP, 1); @@ -598,6 +603,36 @@ void Application::keyPressEvent(QKeyEvent* event) { _myAvatar.setDriveKeys(shifted ? RIGHT : ROT_RIGHT, 1); break; + case Qt::Key_I: + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0.001, 0)); + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_K: + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, -0.001, 0)); + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_J: + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_L: + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_U: + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, 0.001)); + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_Y: + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, -0.001)); + resizeGL(_glWidget->width(), _glWidget->height()); + break; + default: event->ignore(); break; @@ -1412,6 +1447,8 @@ void Application::loadViewFrustum(ViewFrustum& viewFrustum) { viewFrustum.setFieldOfView(fov); viewFrustum.setNearClip(nearClip); viewFrustum.setFarClip(farClip); + viewFrustum.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition()); + viewFrustum.setEyeOffsetOrientation(_myCamera.getEyeOffsetOrientation()); // Ask the ViewFrustum class to calculate our corners viewFrustum.calculate(); diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 4cd66521f0..14eeace22c 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -153,6 +153,16 @@ void Camera::setFarClip (float f) { _frustumNeedsReshape = true; } +void Camera::setEyeOffsetPosition (const glm::vec3& p) { + _eyeOffsetPosition = p; + _frustumNeedsReshape = true; +} + +void Camera::setEyeOffsetOrientation (const glm::quat& o) { + _eyeOffsetOrientation = o; + _frustumNeedsReshape = true; +} + void Camera::initialize() { _needsToInitialize = true; } diff --git a/interface/src/Camera.h b/interface/src/Camera.h index 52c577e88a..2f3ce7f099 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -10,6 +10,7 @@ #include "Orientation.h" #include +#include enum CameraMode { @@ -53,6 +54,8 @@ public: void setAspectRatio ( float a ); void setNearClip ( float n ); void setFarClip ( float f ); + void setEyeOffsetPosition ( const glm::vec3& p); + void setEyeOffsetOrientation ( const glm::quat& o); float getYaw () { return _yaw; } float getPitch () { return _pitch; } @@ -64,6 +67,8 @@ public: float getAspectRatio() { return _aspectRatio; } float getNearClip () { return _nearClip; } float getFarClip () { return _farClip; } + glm::vec3 getEyeOffsetPosition () { return _eyeOffsetPosition; } + glm::quat getEyeOffsetOrientation () { return _eyeOffsetOrientation; } bool getFrustumNeedsReshape(); // call to find out if the view frustum needs to be reshaped void setFrustumWasReshaped(); // call this after reshaping the view frustum. @@ -79,6 +84,8 @@ private: float _aspectRatio; float _nearClip; float _farClip; + glm::vec3 _eyeOffsetPosition; + glm::quat _eyeOffsetOrientation; float _yaw; float _pitch; float _roll; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index d6820897b8..f30026bfa0 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -409,3 +409,18 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex, return -1; // error case } +// Takes a set of perspective parameters (as one would pass to gluPerspective) and an eye offset (in view space) and writes +// out the parameters to pass to glFrustum to effect the possibly skewed view frustum +void computeOffsetFrustum(float fovy, float aspect, float zNear, float zFar, float xOffset, float yOffset, float zOffset, + float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal) { + // adjust near and far distances by z offset + nearVal = zNear + zOffset; + farVal = zFar + zOffset; + + float hheight = zNear * tanf(fovy * 0.5f * PI_OVER_180); + top = hheight - yOffset; + bottom = -hheight - yOffset; + float hwidth = aspect * hheight; + left = -hwidth - xOffset; + right = hwidth - xOffset; +} diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 98baa5488a..721f6aff97 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -78,4 +78,7 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex, void** valueArray, float* keyArray, int* originalIndexArray, int currentCount, int maxCount); +void computeOffsetFrustum(float fovy, float aspect, float zNear, float zFar, float xOffset, float yOffset, float zOffset, + float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal); + #endif /* defined(__hifi__SharedUtil__) */ diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index 25022ae521..355729e762 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -9,6 +9,7 @@ // #include "ViewFrustum.h" +#include "SharedUtil.h" #include "voxels_Log.h" using voxels_lib::printLog; @@ -52,6 +53,16 @@ void ViewFrustum::calculate() { glm::vec3 front = _direction; + float left, right, bottom, top, nearVal, farVal; + computeOffsetFrustum(_fieldOfView, _aspectRatio, _nearClip, _farClip, + _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z, + left, right, bottom, top, nearVal, farVal); + + _nearHeight = top - bottom; + _nearWidth = right - left; + _farHeight = _nearHeight * (farVal / nearVal); + _farWidth = _nearWidth * (farVal / nearVal); + // Calculating field of view. float fovInRadians = _fieldOfView * PI_OVER_180; diff --git a/libraries/voxels/src/ViewFrustum.h b/libraries/voxels/src/ViewFrustum.h index aadb1f86e8..dae62352b0 100644 --- a/libraries/voxels/src/ViewFrustum.h +++ b/libraries/voxels/src/ViewFrustum.h @@ -12,6 +12,7 @@ #define __hifi__ViewFrustum__ #include +#include #include "Plane.h" #include "AABox.h" @@ -29,6 +30,8 @@ private: float _aspectRatio; float _nearClip; float _farClip; + glm::vec3 _eyeOffsetPosition; + glm::quat _eyeOffsetOrientation; // Calculated values float _nearHeight; @@ -63,16 +66,21 @@ public: const glm::vec3& getRight() const { return _right; }; // setters for lens attributes - void setFieldOfView ( float f ) { _fieldOfView = f; } - void setAspectRatio ( float a ) { _aspectRatio = a; } - void setNearClip ( float n ) { _nearClip = n; } - void setFarClip ( float f ) { _farClip = f; } + void setFieldOfView ( float f ) { _fieldOfView = f; } + void setAspectRatio ( float a ) { _aspectRatio = a; } + void setNearClip ( float n ) { _nearClip = n; } + void setFarClip ( float f ) { _farClip = f; } + void setEyeOffsetPosition (const glm::vec3& p) { _eyeOffsetPosition = p; } + void setEyeOffsetOrientation (const glm::quat& o) { _eyeOffsetOrientation = o; } + // getters for lens attributes - float getFieldOfView() const { return _fieldOfView; }; - float getAspectRatio() const { return _aspectRatio; }; - float getNearClip() const { return _nearClip; }; - float getFarClip() const { return _farClip; }; + float getFieldOfView() const { return _fieldOfView; }; + float getAspectRatio() const { return _aspectRatio; }; + float getNearClip() const { return _nearClip; }; + float getFarClip() const { return _farClip; }; + const glm::vec3& getEyeOffsetPosition() const { return _eyeOffsetPosition; }; + const glm::quat& getEyeOffsetOrientation() const { return _eyeOffsetOrientation;}; const glm::vec3& getFarCenter() const { return _farCenter; }; const glm::vec3& getFarTopLeft() const { return _farTopLeft; };