Skip to content
Snippets Groups Projects
Commit 0c93d51c authored by Robert Menzel's avatar Robert Menzel
Browse files

worked on camera, parallel shift mode should work (untested)

parent 6d8697b6
No related branches found
No related tags found
No related merge requests found
/***********************************************************************
* Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#ifndef ACGL_SCENE_CAMERA_HH
#define ACGL_SCENE_CAMERA_HH
#ifdef ACGL_INCLUDE_DEPRECATED_FUNCTIONALITY
/*
* A generic camera class.
*/
#include <ACGL/ACGL.hh>
#include <ACGL/Math/Math.hh>
namespace ACGL{
namespace Scene{
class Camera
{
public:
Camera(void)
: mRight (),
mUp (),
mForward (),
mWidth (800),
mHeight (600),
mFOV (75.0f),
mNear (0.1f),
mFar (10000.0f),
mPitch (0.0f),
mYaw (0.0f),
mRoll (0.0f),
mPosition (3.0f, 2.0f, 3.0f),
mTarget (0.0f, 0.0f, 0.0f)
{
updateLocalCoordinateSystemByTarget();
updateOrientationByLocalCoordinateSystem();
}
Camera(
int_t _width,
int_t _height,
float _fov,
float _near,
float _far,
const glm::vec3& _position,
const glm::vec3& _target)
: mRight (),
mUp (),
mForward (),
mWidth (_width),
mHeight (_height),
mFOV (_fov),
mNear (_near),
mFar (_far),
mPitch (0.0f),
mYaw (0.0f),
mRoll (0.0f),
mPosition (_position),
mTarget (_target)
{
updateLocalCoordinateSystemByTarget();
updateOrientationByLocalCoordinateSystem();
}
Camera(const Camera& other)
: mRight (other.mRight),
mUp (other.mUp),
mForward (other.mForward),
mWidth (other.mWidth),
mHeight (other.mHeight),
mFOV (other.mFOV),
mNear (other.mNear),
mFar (other.mFar),
mPitch (other.mPitch),
mYaw (other.mYaw),
mRoll (other.mRoll),
mPosition (other.mPosition),
mTarget (other.mTarget)
{
}
~Camera(void) {}
inline float getAspectRatio (void) const { return (float)mWidth / (float)mHeight; }
inline const glm::vec3& getUpDirection (void) const { return mUp; }
inline const glm::vec3& getRightDirection (void) const { return mRight; }
inline const glm::vec3& getForwardDirection (void) const { return mForward; }
inline int_t getWidth (void) const { return mWidth; }
inline int_t getHeight (void) const { return mHeight; }
inline float getFOV (void) const { return mFOV; }
inline float getNear (void) const { return mNear; }
inline float getFar (void) const { return mFar; }
inline float getPitch (void) const { return mPitch; }
inline float getYaw (void) const { return mYaw; }
inline float getRoll (void) const { return mRoll; }
inline const glm::vec3& getPosition (void) const { return mPosition; }
inline const glm::vec3& getTarget (void) const { return mTarget; }
inline void setWidth (int_t _width) { mWidth = _width; }
inline void setHeight (int_t _height) { mHeight = _height; }
inline void setFOV (float _fov) { mFOV = _fov; }
inline void setNear (float _near) { mNear = _near; }
inline void setFar (float _far) { mFar = _far; }
inline void setPosition(const glm::vec3& _position, bool _moveTarget = true)
{
if(_moveTarget)
mTarget += _position - mPosition;
mPosition = _position;
if(!_moveTarget)
updateLocalCoordinateSystemByTarget(mUp);
}
inline void setPosition(const glm::vec3& _position, const glm::vec3& _up, bool _moveTarget = true)
{
if(_moveTarget)
mTarget += _position - mPosition;
mPosition = _position;
updateLocalCoordinateSystemByTarget(_up);
}
inline void setTarget(const glm::vec3& _target, bool _movePosition = true)
{
if(_movePosition)
mPosition += _target - mTarget;
mTarget = _target;
if(!_movePosition)
updateLocalCoordinateSystemByTarget(mUp);
}
inline void setPitch(float _pitch)
{
mPitch = _pitch;
updateLocalCoordinateSystemByOrientation();
mTarget = mPosition + glm::length(mTarget - mPosition) * mForward;
}
inline void setYaw(float _yaw)
{
mYaw = _yaw;
updateLocalCoordinateSystemByOrientation();
mTarget = mPosition + glm::length(mTarget - mPosition) * mForward;
}
inline void setRoll(float _roll)
{
mRoll = _roll;
}
inline void setPitchAroundTarget(float pitch)
{
mPitch = pitch;
updateLocalCoordinateSystemByOrientation();
mPosition = mTarget - glm::length(mTarget - mPosition) * mForward;
}
inline void setYawAroundTarget(float yaw)
{
mYaw = yaw;
updateLocalCoordinateSystemByOrientation();
mPosition = mTarget - glm::length(mTarget - mPosition) * mForward;
}
inline void setOrientation(float _pitch, float _yaw, float _roll)
{
mPitch = _pitch;
mYaw = _yaw;
mRoll = _roll;
updateLocalCoordinateSystemByOrientation();
}
glm::mat4 getProjectionMatrix() const;
glm::mat4 getViewMatrix() const;
glm::mat4 getInverseViewMatrix() const;
private:
void updateLocalCoordinateSystemByTarget(const glm::vec3& _up = glm::vec3(0.0f, 1.0f, 0.0f));
void updateLocalCoordinateSystemByOrientation(void);
void updateOrientationByLocalCoordinateSystem(void);
glm::vec3 mRight;
glm::vec3 mUp;
glm::vec3 mForward;
int_t mWidth;
int_t mHeight;
float mFOV;
float mNear;
float mFar;
float mPitch;
float mYaw;
float mRoll;
glm::vec3 mPosition;
glm::vec3 mTarget;
};
} // Scene
} // ACGL
#endif
#endif // ACGL_SCENE_CAMERA_HH
This diff is collapsed.
/***********************************************************************
* Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#include <ACGL/Scene/Camera.hh>
#ifdef ACGL_INCLUDE_DEPRECATED_FUNCTIONALITY
using namespace ACGL;
using namespace ACGL::Scene;
glm::mat4 Camera::getProjectionMatrix(void) const
{
// returns a projection matrix as gluPerspective would do
return glm::perspective( mFOV, getAspectRatio(), mNear, mFar );
}
glm::mat4 Camera::getViewMatrix(void) const
{
glm::mat4 mView;
mView[0][0] = mRight.x;
mView[0][1] = mUp.x;
mView[0][2] = -mForward.x;
mView[1][0] = mRight.y;
mView[1][1] = mUp.y;
mView[1][2] = -mForward.y;
mView[2][0] = mRight.z;
mView[2][1] = mUp.z;
mView[2][2] = -mForward.z;
mView[3][0] = -(mRight.x * mPosition.x + mRight.y * mPosition.y + mRight.z * mPosition.z);
mView[3][1] = -(mUp.x * mPosition.x + mUp.y * mPosition.y + mUp.z * mPosition.z);
mView[3][2] = (mForward.x * mPosition.x + mForward.y * mPosition.y + mForward.z * mPosition.z);
return mView;
}
glm::mat4 Camera::getInverseViewMatrix(void) const
{
glm::mat4 mView;
mView[0][0] = mRight.x;
mView[0][1] = mRight.y;
mView[0][2] = mRight.z;
mView[1][0] = mUp.x;
mView[1][1] = mUp.y;
mView[1][2] = mUp.z;
mView[2][0] = -mForward.x;
mView[2][1] = -mForward.y;
mView[2][2] = -mForward.z;
mView[3][0] = mPosition.x;
mView[3][1] = mPosition.y;
mView[3][2] = mPosition.z;
return mView;
}
void Camera::updateLocalCoordinateSystemByTarget(const glm::vec3& _up)
{
mForward = glm::normalize( mTarget - mPosition );
mRight = glm::normalize( glm::cross( mForward, _up) );
mUp = glm::normalize( glm::cross( mRight, mForward) );
updateOrientationByLocalCoordinateSystem();
}
void Camera::updateLocalCoordinateSystemByOrientation(void)
{
//Calculate the full rotation in the right order:
//rot => 1. mYaw (y) -> 2. mPitch (x) -> 3. mRoll (z)
glm::mat3 rx = Math::Functions::rotationMatrixX(mPitch);
glm::mat3 ry = Math::Functions::rotationMatrixY(mYaw);
glm::mat3 rz = Math::Functions::rotationMatrixZ(mRoll);
glm::mat3 rotation = ry * rx * rz;
mRight = rotation * glm::vec3(1.0f, 0.0f, 0.0f);
mUp = rotation * glm::vec3(0.0f, 1.0f, 0.0f);
mForward = rotation * glm::vec3(0.0f, 0.0f, -1.0f);
}
void Camera::updateOrientationByLocalCoordinateSystem(void)
{
if (mUp.x > 1.0f - Math::Constants::EPSILON_FLOAT)
{
mYaw = Math::Functions::atan2Deg(mForward.x, -mForward.z);
mPitch = 90.0f;
mRoll = 0.0f;
return;
}
if (mUp.x < Math::Constants::EPSILON_FLOAT - 1.0f)
{
mYaw = Math::Functions::atan2Deg(mForward.x, -mForward.z);
mPitch = -90.0f;
mRoll = 0.0f;
return;
}
mYaw = Math::Functions::atan2Deg(-mRight.z, mRight.x);
mPitch = Math::Functions::atan2Deg( mForward.y, mUp.y);
mRoll = Math::Functions::asinDeg( mRight.y);
}
#endif
......@@ -35,6 +35,11 @@ GenericCamera::GenericCamera() :
setRotationMatrix( glm::mat3(1.0f) );
}
GenericCamera::GenericCamera( const std::string &_state )
{
setStateFromString( _state );
}
void GenericCamera::FPSstyleLookAround( float _deltaX, float _deltaY )
{
float yaw = 0.0f;
......@@ -184,80 +189,73 @@ void GenericCamera::setLookAtDistance(float _distance)
mLookAtDistance = _distance;
}
//glm::mat4 FrescoCamera::getCameraMatrix( double _eyeShift, double _toeInValue )
//{
// cout << " TODO: getCameraMatrix" << endl;
/*
// we have to move to the left (eyeShift in meter) and tilt to the left (toeInValue)
// left of course is defined by the current rotation!
Rotation camRotation = rotation * Rotation( 0.0, 1.0, 0.0, toeInValue );
Vector3 camPosition = position + rotation * Vector3(eyeShift, 0.0, 0.0);
return HomogenousMatrix(camRotation, camPosition, Vector3(1.0,1.0,1.0));
*/
// glm::mat4 projectionMatrix; // all values are 0
// return projectionMatrix;
//}
//glm::mat4 FrescoCamera::getPerspectiveProjectionMatrix( double _eyeShift )
//{
// cout << " TODO: getPerspectiveProjectionMatrix" << endl;
//glm::mat4 projectionMatrix; // all values are 0
/*
double right = tan( degToRad(getHorizontalFieldOfView() * 0.5f) ) * nearClippingPlane;
double left = -right;
// we want the images to match on the screen == at the focalDistance
// not at the near clipping plane.
left += eyeShift * (nearClippingPlane/focalDistance);
right += eyeShift * (nearClippingPlane/focalDistance);
double top = tan( degToRad(getVerticalFieldOfView() * 0.5f) ) * nearClippingPlane;
double bottom = -top;
*/
/*
// we do the same here as a glFrustum call would do.
projectionMatrix[ 0][0] = 2.0*nearClippingPlane / (right - left);
projectionMatrix[ 1][1] = 2.0*nearClippingPlane / (top - bottom);
projectionMatrix[ 0][2] = (right + left) / (right - left);
projectionMatrix[ 1][2] = (top + bottom) / (top - bottom);
projectionMatrix[ 2][2] = -1.0*(farClippingPlane+nearClippingPlane) / (farClippingPlane - nearClippingPlane);
projectionMatrix[ 3][2] = -1.0;
projectionMatrix[ 2][3] = -2.0*farClippingPlane*nearClippingPlane / (farClippingPlane - nearClippingPlane);
return projectionMatrix;
*/
//return G3D::Matrix4::perspectiveProjection( left, right, bottom, top, nearClippingPlane, farClippingPlane );
//return glm::gtx::transform::perspective( (float)getHorizontalFieldOfView(), (float)getAspectRatio(), (float)mNearClippingPlane, (float)mFarClippingPlane );
//}
glm::mat4 GenericCamera::getProjectionMatrix() const
{
switch (this->mStereoMode)
glm::mat4 GenericCamera::getViewMatrix() const
{
case MONO: return getMonoProjectionMatrix();
default: assert( 0 && "unsupported stereo mode" );
return glm::mat4();
if (mStereoMode == MONO) {
return getMonoViewMatrix();
} else {
// all kinds of stereo
bool eyeIsLeftEye = (getEye() == EYE_LEFT);
return getStereoViewMatrix( eyeIsLeftEye, mStereoMode );
}
}
glm::mat4 GenericCamera::getViewMatrix() const
{
switch (this->mStereoMode)
glm::mat4 GenericCamera::getStereoViewMatrix( bool _leftEye, StereoMode _stereoMode ) const
{
case MONO: return getMonoViewMatrix();
default: assert( 0 && "unsupported stereo mode" );
return glm::mat4();
// The view matrix is independent of the projection mode (isometric or perspective)
// so only the stereo mode has to be checked.
assert( _stereoMode != MONO && "mono is not a stereo mode!" );
float cameraPositionShiftValue = (mEyeDistance*0.5f); // shift to the right
if (_leftEye) cameraPositionShiftValue *= -1.0f; // if left eye shift to the left
if ( (_stereoMode == PARALLEL_SHIFT) || (_stereoMode == OFF_AXIS) ) {
//
// parallel shift and off-axis have the same view matrices:
// just shift the camera position to the left/right by half the eye-distance
//
ACGL::Utils::debug() << "WARNING: getStereoViewMatrix() is not tested yet" << std::endl; // remove after testing
glm::mat3 inverseRotation = getInverseRotationMatrix3();
glm::vec3 eyePosition = mPosition + (inverseRotation * glm::vec3(cameraPositionShiftValue,0.0f,0.0f) );
glm::mat4 m(mRotationMatrix);
m[3][0] = -(m[0][0] * eyePosition.x + m[1][0] * eyePosition.y + m[2][0] * eyePosition.z);
m[3][1] = -(m[0][1] * eyePosition.x + m[1][1] * eyePosition.y + m[2][1] * eyePosition.z);
m[3][2] = -(m[0][2] * eyePosition.x + m[1][2] * eyePosition.y + m[2][2] * eyePosition.z);
return m;
}
// else it has to be toe-in:
assert( _stereoMode == TOE_IN && "unsupported stereo mode!" );
//
// Toe-in: shift the camera position to the left/right by half the eye-distance and
// rotate a bit inwards so that the two cameras focus the same point
// at the look-at distance (focal point)
assert(0 && "getStereoViewMatrix() for TOE_IN is not implemented yet!");
return glm::mat4();
}
glm::mat4 GenericCamera::getInverseViewMatrix() const
{
switch (this->mStereoMode)
if (mStereoMode == MONO) {
return getMonoInverseViewMatrix();
}
glm::mat4 viewMatrix = getViewMatrix();
return glm::inverse( viewMatrix );
}
glm::mat4 GenericCamera::getProjectionMatrix() const
{
case MONO: return getMonoInverseViewMatrix();
default: assert( 0 && "unsupported stereo mode" );
return glm::mat4();
if (mStereoMode == MONO) {
return getMonoProjectionMatrix();
} else {
// all kinds of stereo
bool eyeIsLeftEye = (getEye() == EYE_LEFT);
return getStereoProjectionMatrix( eyeIsLeftEye, mStereoMode );
}
}
......@@ -317,61 +315,52 @@ glm::mat4 GenericCamera::getMonoInverseViewMatrix() const
assert( isApproxEqual( glm::inverse(getViewMatrix()), m ) );
return m;
}
/*
glm::mat4 GenericCamera::getStereoProjectionMatrix( bool _leftEye, StereoMode _stereoMode )
{
// ToeIn with parallel projection could work, but all the other modes wouldn't.
// But even this cambination would be very unusual, so it's not implemented.
assert( getProjectionMode() == PERSPECTIVE_PROJECTION );
glm::mat4 cameraMatrix;
glm::mat4 projectionMatrix; // all values are 0
double camRotation;
// set the rotation of the camera to the right/left and get the projection matrix
if (_stereoMode == PARALLEL_SHIFT)
{
camRotation = 0.0f;
projectionMatrix = getPerspectiveProjectionMatrix();
}
else if (_stereoMode == OFF_AXIS)
enum ProjectionMode
{
camRotation = 0.0f;
if (_leftEye == true)
{
projectionMatrix = getPerspectiveProjectionMatrix( mEyeDistance * -0.5f );
}
else
ISOMETRIC_PROJECTION = 0,
PERSPECTIVE_PROJECTION
};
enum StereoMode
{
projectionMatrix = getPerspectiveProjectionMatrix( mEyeDistance * 0.5f );
}
}
else if (_stereoMode == TOE_IN)
MONO = 0,
PARALLEL_SHIFT,
OFF_AXIS,
TOE_IN
};
glm::mat4 GenericCamera::getStereoProjectionMatrix( bool _leftEye, StereoMode _stereoMode ) const
{
camRotation = asin( mLookAtDistance * ACGL::Math::Functions::sqrt( mEyeDistance*mEyeDistance / 4.0 + mLookAtDistance*mLookAtDistance) );
projectionMatrix = getPerspectiveProjectionMatrix();
}
assert( _stereoMode != MONO && "mono is not a stereo mode!" );
// get the camera matrix
if (_leftEye == true)
if ( getProjectionMode() == ISOMETRIC_PROJECTION )
{
cameraMatrix = getCameraMatrix( mEyeDistance * -0.5f, camRotation );
// very unusual, prepare for headaches!
return getMonoProjectionMatrix();
}
else
if ((_stereoMode == PARALLEL_SHIFT) || (_stereoMode == TOE_IN))
{
cameraMatrix = getCameraMatrix( mEyeDistance * 0.5f, -1.0f * camRotation );
// the view matrix changes but the projection matrix stays the same
return getMonoProjectionMatrix();
}
return projectionMatrix;
}
// so off-axis it is!
assert( _stereoMode == OFF_AXIS && "unknown projection mode!" );
//
// In this mode the camera positions (view matrix) is shifted to the left/right still looking
// straight ahead. The projection is also looking ahead but the projection center is
// off (hence off-axis).
// There is one plane in front of the cameras where the view-frusta match.
// This should be the distance to the physical screen from the users position.
glm::mat4 GenericCamera::getStereoViewMatrix( bool _leftEye, StereoMode _stereoMode )
{
assert(0 && "getStereoViewMatrix() is not implemented for OFF_AXIS yet!");
return glm::mat4();
}
*/
/// Writes all internal state to one string
/// Elements are seperated by pipes ('|'), spaces can get ignored.
......@@ -454,19 +443,6 @@ void GenericCamera::setFocalLengthInPixel( float _focalLengthInPixel )
setHorizontalFieldOfView( calcRadToDeg( hFoVrad ) );
}
float GenericCamera::getFocalLenghtInMM() const
{
glm::vec2 sensorSize = glm::vec2( 36.0f/mAspectRatio, 24.0f ); // in mm
return ( sensorSize.x ) / ( 2.0f * tan( calcDegToRad(0.5f * mHorizontalFieldOfView) ) );
}
void GenericCamera::setFocalLengthInMM( float _focalLengthInMM )
{
glm::vec2 sensorSize = glm::vec2( 36.0f/mAspectRatio, 24.0f ); // in mm
float hFoVrad = 2.0f * atan( ( 0.5f * sensorSize.x ) * (1.0f / _focalLengthInMM ) );
setHorizontalFieldOfView( calcRadToDeg( hFoVrad ) );
}
/////////////// TESTS /////////////
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment