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

added more projection matrix types

parent b2ab869d
......@@ -45,6 +45,17 @@ public:
* @return the 2-dimensional size of the viewport
*/
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{
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
{
......@@ -17,6 +18,11 @@ private:
glm::mat4 mProjectionMatrix;
glm::uvec2 mViewportSize;
// will get calculated based on the projection matrix
// so there are no explicit setters for this!
float mNearPlane;
float mFarPlane;
public:
/// CAUTION: default ctor with zero values
FixedCamera();
......@@ -32,11 +38,15 @@ public:
// Getter, Setter for Camera ProjectionMatrix
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
virtual glm::uvec2 getViewportSize() const { return mViewportSize; }
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
// 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
{
ISOMETRIC_PROJECTION = 0,
PERSPECTIVE_PROJECTION
PERSPECTIVE_PROJECTION_OPENGL, // maps to -1..1
PERSPECTIVE_PROJECTION_DX_REVERSE // maps to 1..0
};
enum StereoMode
......@@ -172,16 +185,17 @@ class GenericCamera : public CameraBase, public MoveableObject
*/
void setNearClippingPlane( float _plane );
/// Gets the near clip distance
float getNearClippingPlane() const { return mNearClippingPlane; }
virtual float getNearClippingPlane() const { return mNearClippingPlane; }
/**
* Set the far clipping plane of 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.
*/
void setFarClippingPlane( float _plane );
/// Gets the far clip distance
float getFarClippingPlane() const { return mFarClippingPlane; }
virtual float getFarClippingPlane() const { return mFarClippingPlane; }
/// Gets size of the viewport
virtual glm::uvec2 getViewportSize() const { return mViewportSize; }
......@@ -237,7 +251,6 @@ class GenericCamera : public CameraBase, public MoveableObject
/// Gets the currently active projection matrix (depends on stereo mode and current eye)
virtual glm::mat4 getProjectionMatrix() const;
///////////////////////////////////////////////////////////////////////////////////////////
//
// Explicit view and projection matrices. These DON'T obey the set stereo/eye settings.
......
......@@ -16,9 +16,72 @@ FixedCamera::FixedCamera()
FixedCamera::FixedCamera(const glm::vec3 &_pos, const glm::mat4 &_view, const glm::mat4 &_proj, const glm::uvec2 &_viewport) :
mPosition(_pos),
mViewMatrix(_view),
mProjectionMatrix(_proj),
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;
using namespace std;
GenericCamera::GenericCamera() :
mProjectionMode(PERSPECTIVE_PROJECTION),
mProjectionMode(PERSPECTIVE_PROJECTION_OPENGL),
mStereoMode(MONO),
mCurrentEye(EYE_LEFT),
mHorizontalFieldOfView(75.0),
......@@ -247,10 +247,42 @@ glm::mat4 GenericCamera::getMonoProjectionMatrix() const
projectionMatrix[ 2][3] = -(mFarClippingPlane+mNearClippingPlane)/(mFarClippingPlane-mNearClippingPlane);
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");
return projectionMatrix;
......@@ -320,7 +352,7 @@ std::string GenericCamera::storeStateToString() const
state += toString( mPosition ) + " | ";
state += toString( mRotationMatrix ) + " | ";
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 == PARALLEL_SHIFT) state += "PARALLEL_SHIFT | ";
if ( mStereoMode == OFF_AXIS) state += "OFF_AXIS | ";
......@@ -358,7 +390,7 @@ void GenericCamera::setStateFromString( const std::string &_state )
mPosition = toVec3( token[pos++] );
mRotationMatrix = toMat3( token[pos++] );
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++;
if ( token[pos] == "MONO") mStereoMode = MONO;
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