Commit 26d2c589 authored by Robert Menzel's avatar Robert Menzel

added more projection matrix types

parent b2ab869d
...@@ -45,6 +45,17 @@ public: ...@@ -45,6 +45,17 @@ public:
* @return the 2-dimensional size of the viewport * @return the 2-dimensional size of the viewport
*/ */
virtual glm::uvec2 getViewportSize() const = 0; virtual glm::uvec2 getViewportSize() const = 0;
/**
* @brief Gets the near clipping plane as a distance from the camera.
* @return the near clipping plane
*/
virtual float getNearClippingPlane() const = 0;
/**
* @brief Gets the far clipping plane as a distance from the camera. Note that it could be inf!
* Not all projection matrices have a real far plane but some are unlimited!
* @return the near clipping plane
*/
virtual float getFarClippingPlane() const = 0;
}; };
} }
......
...@@ -6,7 +6,8 @@ namespace ACGL{ ...@@ -6,7 +6,8 @@ namespace ACGL{
namespace Scene{ namespace Scene{
/** /**
* @brief A fixed camera * @brief A fixed camera where all attributes are set explicitly except for the near/far plane
* which are derrived from the projection matrix.
*/ */
class FixedCamera : public CameraBase class FixedCamera : public CameraBase
{ {
...@@ -17,6 +18,11 @@ private: ...@@ -17,6 +18,11 @@ private:
glm::mat4 mProjectionMatrix; glm::mat4 mProjectionMatrix;
glm::uvec2 mViewportSize; glm::uvec2 mViewportSize;
// will get calculated based on the projection matrix
// so there are no explicit setters for this!
float mNearPlane;
float mFarPlane;
public: public:
/// CAUTION: default ctor with zero values /// CAUTION: default ctor with zero values
FixedCamera(); FixedCamera();
...@@ -32,11 +38,15 @@ public: ...@@ -32,11 +38,15 @@ public:
// Getter, Setter for Camera ProjectionMatrix // Getter, Setter for Camera ProjectionMatrix
virtual glm::mat4 getProjectionMatrix() const { return mProjectionMatrix; } virtual glm::mat4 getProjectionMatrix() const { return mProjectionMatrix; }
virtual void setProjectionMatrix(glm::mat4 const& _val) { mProjectionMatrix = _val; } virtual void setProjectionMatrix(glm::mat4 const& _val);
// Getter, Setter for Camera ViewportSize // Getter, Setter for Camera ViewportSize
virtual glm::uvec2 getViewportSize() const { return mViewportSize; } virtual glm::uvec2 getViewportSize() const { return mViewportSize; }
virtual void setViewportSize(glm::uvec2 const& _val) { mViewportSize = _val; } virtual void setViewportSize(glm::uvec2 const& _val) { mViewportSize = _val; }
// getters for near/far plane (far can be inf!)
virtual float getNearClippingPlane() const { return mNearPlane; }
virtual float getFarClippingPlane() const { return mFarPlane; }
}; };
} }
......
...@@ -57,10 +57,23 @@ class GenericCamera : public CameraBase, public MoveableObject ...@@ -57,10 +57,23 @@ class GenericCamera : public CameraBase, public MoveableObject
// Helping enums: // Helping enums:
// //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// use the DX reverse mode with:
/// * an infinite far plane
/// * a float z-buffer
/// * glClearDepth(0.0)
/// * glDepthFunc(GL_GREATER)
/// * either:
/// * glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE) (DX style mapping of the Z values)
/// or:
/// * glDepthRangedNV(-1.0, 1.0)
///
/// this way near will get mapped to 1.0 and infinite to 0.0
enum ProjectionMode enum ProjectionMode
{ {
ISOMETRIC_PROJECTION = 0, ISOMETRIC_PROJECTION = 0,
PERSPECTIVE_PROJECTION PERSPECTIVE_PROJECTION_OPENGL, // maps to -1..1
PERSPECTIVE_PROJECTION_DX_REVERSE // maps to 1..0
}; };
enum StereoMode enum StereoMode
...@@ -172,16 +185,17 @@ class GenericCamera : public CameraBase, public MoveableObject ...@@ -172,16 +185,17 @@ class GenericCamera : public CameraBase, public MoveableObject
*/ */
void setNearClippingPlane( float _plane ); void setNearClippingPlane( float _plane );
/// Gets the near clip distance /// Gets the near clip distance
float getNearClippingPlane() const { return mNearClippingPlane; } virtual float getNearClippingPlane() const { return mNearClippingPlane; }
/** /**
* Set the far clipping plane of the camera. * Set the far clipping plane of the camera.
* The plane is defined only by a distance from the camera. * The plane is defined only by a distance from the camera.
* This distance might be inf!
* @param _plane New far clipping plane of the camera. * @param _plane New far clipping plane of the camera.
*/ */
void setFarClippingPlane( float _plane ); void setFarClippingPlane( float _plane );
/// Gets the far clip distance /// Gets the far clip distance
float getFarClippingPlane() const { return mFarClippingPlane; } virtual float getFarClippingPlane() const { return mFarClippingPlane; }
/// Gets size of the viewport /// Gets size of the viewport
virtual glm::uvec2 getViewportSize() const { return mViewportSize; } virtual glm::uvec2 getViewportSize() const { return mViewportSize; }
...@@ -237,7 +251,6 @@ class GenericCamera : public CameraBase, public MoveableObject ...@@ -237,7 +251,6 @@ class GenericCamera : public CameraBase, public MoveableObject
/// Gets the currently active projection matrix (depends on stereo mode and current eye) /// Gets the currently active projection matrix (depends on stereo mode and current eye)
virtual glm::mat4 getProjectionMatrix() const; virtual glm::mat4 getProjectionMatrix() const;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// //
// Explicit view and projection matrices. These DON'T obey the set stereo/eye settings. // Explicit view and projection matrices. These DON'T obey the set stereo/eye settings.
......
...@@ -16,9 +16,72 @@ FixedCamera::FixedCamera() ...@@ -16,9 +16,72 @@ FixedCamera::FixedCamera()
FixedCamera::FixedCamera(const glm::vec3 &_pos, const glm::mat4 &_view, const glm::mat4 &_proj, const glm::uvec2 &_viewport) : FixedCamera::FixedCamera(const glm::vec3 &_pos, const glm::mat4 &_view, const glm::mat4 &_proj, const glm::uvec2 &_viewport) :
mPosition(_pos), mPosition(_pos),
mViewMatrix(_view), mViewMatrix(_view),
mProjectionMatrix(_proj),
mViewportSize(_viewport) mViewportSize(_viewport)
{ {
setProjectionMatrix( _proj );
}
void FixedCamera::setProjectionMatrix(glm::mat4 const& _val)
{
mProjectionMatrix = _val;
//
// Calculate near and far plane from the matrix
// As the matrix does not have to be a standard OpenGL
// projection matrix, we can't derrive the values from
// the matrix entries directly but we have to reproject
// points from the NDC cube... ...but as some matrices
// project to -1..1 and others to 0..1 we have to figure
// this out first... ...keeping in mind, that some also
// invert the range inside of the Z buffer, so Z=1 might
// be the near plane while Z=0 is the far plane...
// ...oh, and the far plane might be at infinity...
//
//
// First step, figure out which values project to
// -1, 0 and 1:
//
glm::mat4 invProj = glm::inverse(mProjectionMatrix);
glm::vec4 tmp = invProj * glm::vec4( 0.0f, 0.0f, -1.0f, 1.0f);
float reproj_minusOne = tmp.z / tmp.w;
tmp = invProj * glm::vec4( 0.0f, 0.0f, 0.0f, 1.0f);
float reproj_Zero = tmp.z / tmp.w;
tmp = invProj * glm::vec4( 0.0f, 0.0f, 1.0f, 1.0f);
float reproj_One = tmp.z / tmp.w;
//
// Next step, figure out which value is the near plane and which is the far plane.
//
// right handed coordinate system -> the camera was looking along the negative Z axis
// if it was an OpenGL matrix, the projections will result in -near, -something, -far
// if it was an OpenGL matrix with infinit far plane, the projections will result in -near, -something, -inf
// if it was a reverse DX style matrix it will result in +near, -inf, -near
if (reproj_minusOne > 0.0f) {
// near,far mapped to 1,0 or 0,1 as -1 was mapped to a positive value which is behind the camera
// if we assume we are looking along the negative Z axis!
if (-reproj_Zero > -reproj_One) {
// the far plane is mapped to 0 -> inverse DX style
mFarPlane = -reproj_Zero;
mNearPlane = -reproj_One;
} else {
// the near plane is mapped to zero -> DX style
mFarPlane = -reproj_One;
mNearPlane = -reproj_Zero;
}
} else {
// OpenGL style, mapping to -1..1 or 1..-1
if (-reproj_minusOne > -reproj_One) {
// the far plane is mapped to -1 -> inverse GL style
mFarPlane = -reproj_minusOne;
mNearPlane = -reproj_One;
} else {
// the near plane is mapped to -1 -> GL style
mFarPlane = -reproj_One;
mNearPlane = -reproj_minusOne;
}
}
} }
} }
......
...@@ -21,7 +21,7 @@ using namespace ACGL::Utils::StringHelpers; ...@@ -21,7 +21,7 @@ using namespace ACGL::Utils::StringHelpers;
using namespace std; using namespace std;
GenericCamera::GenericCamera() : GenericCamera::GenericCamera() :
mProjectionMode(PERSPECTIVE_PROJECTION), mProjectionMode(PERSPECTIVE_PROJECTION_OPENGL),
mStereoMode(MONO), mStereoMode(MONO),
mCurrentEye(EYE_LEFT), mCurrentEye(EYE_LEFT),
mHorizontalFieldOfView(75.0), mHorizontalFieldOfView(75.0),
...@@ -247,10 +247,42 @@ glm::mat4 GenericCamera::getMonoProjectionMatrix() const ...@@ -247,10 +247,42 @@ glm::mat4 GenericCamera::getMonoProjectionMatrix() const
projectionMatrix[ 2][3] = -(mFarClippingPlane+mNearClippingPlane)/(mFarClippingPlane-mNearClippingPlane); projectionMatrix[ 2][3] = -(mFarClippingPlane+mNearClippingPlane)/(mFarClippingPlane-mNearClippingPlane);
projectionMatrix[ 3][3] = 1.0; projectionMatrix[ 3][3] = 1.0;
} }
else if ( mProjectionMode == PERSPECTIVE_PROJECTION ) else if ( mProjectionMode == PERSPECTIVE_PROJECTION_OPENGL )
{ {
projectionMatrix = glm::perspective( glm::radians( (float)getHorizontalFieldOfView()), (float)getAspectRatio(), (float)mNearClippingPlane, (float)mFarClippingPlane ); if (std::isinf(mFarClippingPlane)) {
float e = 1.0f / tan(ACGL::Math::Functions::calcDegToRad( getVerticalFieldOfView()*0.5f ));
const float a = getAspectRatio();
// infinite Perspective matrix reversed mapping to 1..-1
projectionMatrix = {
e/a, 0.0f, 0.0f, 0.0f,
0.0f, e, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, -1.0f,
0.0f, 0.0f, -2.0*mNearClippingPlane, 0.0f
};
} else {
projectionMatrix = glm::perspective( glm::radians( (float)getHorizontalFieldOfView()), (float)getAspectRatio(), (float)mNearClippingPlane, (float)mFarClippingPlane );
}
} else if ( mProjectionMode == PERSPECTIVE_PROJECTION_DX_REVERSE )
{
if (std::isinf(mFarClippingPlane)) {
float e = 1.0f / tan(ACGL::Math::Functions::calcDegToRad( getVerticalFieldOfView()*0.5f ));
const float a = getAspectRatio();
// infinite Perspective matrix reversed mapping to 1..0
projectionMatrix = {
e/a, 0.0f, 0.0f, 0.0f,
0.0f, e, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, -1.0f,
0.0f, 0.0f, mNearClippingPlane, 0.0f
};
} else {
assert(0 && "unsupported projection mode");
}
} }
else assert(0 && "unsupported projection mode"); else assert(0 && "unsupported projection mode");
return projectionMatrix; return projectionMatrix;
...@@ -320,7 +352,7 @@ std::string GenericCamera::storeStateToString() const ...@@ -320,7 +352,7 @@ std::string GenericCamera::storeStateToString() const
state += toString( mPosition ) + " | "; state += toString( mPosition ) + " | ";
state += toString( mRotationMatrix ) + " | "; state += toString( mRotationMatrix ) + " | ";
if ( mProjectionMode == ISOMETRIC_PROJECTION ) state += "ISOMETRIC_PROJECTION | "; if ( mProjectionMode == ISOMETRIC_PROJECTION ) state += "ISOMETRIC_PROJECTION | ";
if ( mProjectionMode == PERSPECTIVE_PROJECTION ) state += "PERSPECTIVE_PROJECTION | "; if ( mProjectionMode == PERSPECTIVE_PROJECTION_OPENGL ) state += "PERSPECTIVE_PROJECTION | ";
if ( mStereoMode == MONO) state += "MONO | "; if ( mStereoMode == MONO) state += "MONO | ";
if ( mStereoMode == PARALLEL_SHIFT) state += "PARALLEL_SHIFT | "; if ( mStereoMode == PARALLEL_SHIFT) state += "PARALLEL_SHIFT | ";
if ( mStereoMode == OFF_AXIS) state += "OFF_AXIS | "; if ( mStereoMode == OFF_AXIS) state += "OFF_AXIS | ";
...@@ -358,7 +390,7 @@ void GenericCamera::setStateFromString( const std::string &_state ) ...@@ -358,7 +390,7 @@ void GenericCamera::setStateFromString( const std::string &_state )
mPosition = toVec3( token[pos++] ); mPosition = toVec3( token[pos++] );
mRotationMatrix = toMat3( token[pos++] ); mRotationMatrix = toMat3( token[pos++] );
if ( token[pos] == "ISOMETRIC_PROJECTION" ) mProjectionMode = ISOMETRIC_PROJECTION; if ( token[pos] == "ISOMETRIC_PROJECTION" ) mProjectionMode = ISOMETRIC_PROJECTION;
if ( token[pos] == "PERSPECTIVE_PROJECTION" ) mProjectionMode = PERSPECTIVE_PROJECTION; if ( token[pos] == "PERSPECTIVE_PROJECTION" ) mProjectionMode = PERSPECTIVE_PROJECTION_OPENGL;
pos++; pos++;
if ( token[pos] == "MONO") mStereoMode = MONO; if ( token[pos] == "MONO") mStereoMode = MONO;
if ( token[pos] == "PARALLEL_SHIFT") mStereoMode = PARALLEL_SHIFT; if ( token[pos] == "PARALLEL_SHIFT") mStereoMode = PARALLEL_SHIFT;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment