Browse Source

SceneGraph: Initial support for projections with aspect ratio != 1:1.

Orthographic projection done, perspective projection needs total rework,
leaving it for later.
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
c6e14dd348
  1. 23
      src/SceneGraph/Camera.cpp
  2. 13
      src/SceneGraph/Camera.h
  3. 40
      src/SceneGraph/Test/CameraTest.cpp

23
src/SceneGraph/Camera.cpp

@ -24,26 +24,28 @@ namespace Magnum { namespace SceneGraph {
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2<GLsizei>& viewport) {
template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2<GLsizei>& viewport) {
/* Don't divide by zero / don't preserve anything */
if(viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved)
if(projectionAspectRatio.x() == 0 || projectionAspectRatio.y() == 0 || viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved)
return MatrixType();
Vector2 relativeAspectRatio = Vector2::from(viewport)/projectionAspectRatio;
/* Extend on larger side = scale larger side down
Clip on smaller side = scale smaller side up */
return Camera<MatrixType::Size-1>::aspectRatioScale(
(viewport.x() > viewport.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ?
Vector2(GLfloat(viewport.y())/viewport.x(), 1.0f) :
Vector2(1.0f, GLfloat(viewport.x())/viewport.y()));
(relativeAspectRatio.x() > relativeAspectRatio.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ?
Vector2(relativeAspectRatio.y()/relativeAspectRatio.x(), 1.0f) :
Vector2(1.0f, relativeAspectRatio.x()/relativeAspectRatio.y()));
}
/* Explicitly instantiate the templates */
template Matrix4 aspectRatioFix<Matrix4>(AspectRatioPolicy, const Math::Vector2<GLsizei>&);
template Matrix4 aspectRatioFix<Matrix4>(AspectRatioPolicy, const Vector2&, const Math::Vector2<GLsizei>&);
}
#endif
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> Camera<MatrixType, VectorType, ObjectType, SceneType, CameraType>::Camera(ObjectType* parent): ObjectType(parent), _aspectRatioPolicy(AspectRatioPolicy::Extend) {}
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> Camera<MatrixType, VectorType, ObjectType, SceneType, CameraType>::Camera(ObjectType* parent): ObjectType(parent), projectionAspectRatio(1.0f), _aspectRatioPolicy(AspectRatioPolicy::Extend) {}
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> void Camera<MatrixType, VectorType, ObjectType, SceneType, CameraType>::setViewport(const Math::Vector2<GLsizei>& size) {
Framebuffer::setViewport({0, 0}, size);
@ -79,18 +81,18 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
}
}
void Camera3D::setOrthographic(GLfloat size, GLfloat near, GLfloat far) {
void Camera3D::setOrthographic(const Vector2& size, GLfloat near, GLfloat far) {
_near = near;
_far = far;
/* Scale the volume down so it fits in (-1, 1) in all directions */
GLfloat xyScale = 2/size;
GLfloat zScale = 2/(far-near);
rawProjectionMatrix = Matrix4::scaling({xyScale, xyScale, -zScale});
rawProjectionMatrix = Matrix4::scaling({2.0f/size, -zScale});
/* Move the volume on z into (-1, 1) range */
rawProjectionMatrix = Matrix4::translation(Vector3::zAxis(-1-near*zScale))*rawProjectionMatrix;
projectionAspectRatio = size;
fixAspectRatio();
}
@ -116,6 +118,7 @@ void Camera3D::setPerspective(GLfloat fov, GLfloat near, GLfloat far) {
/* And... another magic */
rawProjectionMatrix[3][3] = 0;
projectionAspectRatio = Vector2(xyScale);
fixAspectRatio();
}

13
src/SceneGraph/Camera.h

@ -38,10 +38,10 @@ namespace Implementation {
template<size_t dimensions> class Camera {};
template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2<GLsizei>& viewport);
template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2<GLsizei>& viewport);
/* These templates are instantiated in source file */
extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix<Matrix4>(AspectRatioPolicy, const Math::Vector2<GLsizei>&);
extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix<Matrix4>(AspectRatioPolicy, const Vector2&, const Math::Vector2<GLsizei>&);
}
#endif
@ -130,9 +130,10 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
#ifndef DOXYGEN_GENERATING_OUTPUT
inline void fixAspectRatio() {
_projectionMatrix = Implementation::aspectRatioFix<MatrixType>(_aspectRatioPolicy, _viewport)*rawProjectionMatrix;
_projectionMatrix = Implementation::aspectRatioFix<MatrixType>(_aspectRatioPolicy, projectionAspectRatio, _viewport)*rawProjectionMatrix;
}
Vector2 projectionAspectRatio;
MatrixType rawProjectionMatrix;
AspectRatioPolicy _aspectRatioPolicy;
#endif
@ -172,20 +173,22 @@ class SCENEGRAPH_EXPORT Camera3D: public Camera<Matrix4, Vector3, Object3D, Scen
/**
* @brief Set orthographic projection
* @param size Size of (square) view
* @param size Size of the view
* @param near Near clipping plane
* @param far Far clipping plane
*
* The volume of given size will be scaled down to range @f$ [-1; 1] @f$
* on all directions.
*/
void setOrthographic(GLfloat size, GLfloat near, GLfloat far);
void setOrthographic(const Vector2& size, GLfloat near, GLfloat far);
/**
* @brief Set perspective projection
* @param fov Field of view angle
* @param near Near clipping plane
* @param far Far clipping plane
*
* @todo Aspect ratio
*/
void setPerspective(GLfloat fov, GLfloat near, GLfloat far);

40
src/SceneGraph/Test/CameraTest.cpp

@ -28,35 +28,50 @@ CameraTest::CameraTest() {
}
void CameraTest::fixAspectRatio() {
Vector2 projectionSize(2, 3);
Math::Vector2<GLsizei> size(400, 300);
/* Division by zero */
Vector2 projectionSizeZeroY(2, 0);
Vector2 projectionSizeZeroX(0, 2);
Math::Vector2<GLsizei> sizeZeroY(400, 0);
Math::Vector2<GLsizei> sizeZeroX(0, 300);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, sizeZeroY), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, sizeZeroX), Matrix4());
Math::Vector2<GLsizei> size(400, 300);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroX, size), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroY, size), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionSize, sizeZeroY), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, projectionSize, sizeZeroX), Matrix4());
/* Not preserved */
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::NotPreserved, size), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::NotPreserved, projectionSize, size), Matrix4());
/* Clip */
Matrix4 expectedClip(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 4.0f/3.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, size), expectedClip);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, Vector2(2.0f), size), expectedClip);
Matrix4 expectedClipRectangle(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 2.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionSize, size), expectedClipRectangle);
/* Extend */
Matrix4 expectedExtend(3.0f/4.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, size), expectedExtend);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, Vector2(2.0f), size), expectedExtend);
Matrix4 expectedExtendRectangle(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, projectionSize, size), expectedExtendRectangle);
}
void CameraTest::orthographic() {
Camera3D camera;
camera.setOrthographic(5, 1, 9);
camera.setOrthographic(Vector2(5), 1, 9);
Matrix4 a(0.4f, 0.0f, 0.0f, 0.0f,
0.0f, 0.4f, 0.0f, 0.0f,
@ -64,6 +79,15 @@ void CameraTest::orthographic() {
0.0f, 0.0f, -1.25f, 1.0f);
CORRADE_COMPARE(camera.projectionMatrix(), a);
camera.setOrthographic(Vector2(5.0f, 4.0f), 1, 9);
Matrix4 rectangle(0.4f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, -0.25f, 0.0f,
0.0f, 0.0f, -1.25f, 1.0f);
CORRADE_COMPARE(camera.projectionMatrix(), rectangle);
}
void CameraTest::perspective() {

Loading…
Cancel
Save