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

added more projection matrix types

parent b2ab869d
No related branches found
No related tags found
No related merge requests found
......@@ -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 )
{
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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment