Browse Source

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

Orthographic projection done, perspective projection needs total rework,
leaving it for later.
pull/279/head
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 #ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation { 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 */ /* 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(); return MatrixType();
Vector2 relativeAspectRatio = Vector2::from(viewport)/projectionAspectRatio;
/* Extend on larger side = scale larger side down /* Extend on larger side = scale larger side down
Clip on smaller side = scale smaller side up */ Clip on smaller side = scale smaller side up */
return Camera<MatrixType::Size-1>::aspectRatioScale( return Camera<MatrixType::Size-1>::aspectRatioScale(
(viewport.x() > viewport.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ? (relativeAspectRatio.x() > relativeAspectRatio.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ?
Vector2(GLfloat(viewport.y())/viewport.x(), 1.0f) : Vector2(relativeAspectRatio.y()/relativeAspectRatio.x(), 1.0f) :
Vector2(1.0f, GLfloat(viewport.x())/viewport.y())); Vector2(1.0f, relativeAspectRatio.x()/relativeAspectRatio.y()));
} }
/* Explicitly instantiate the templates */ /* 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 #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) { 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); 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; _near = near;
_far = far; _far = far;
/* Scale the volume down so it fits in (-1, 1) in all directions */ /* Scale the volume down so it fits in (-1, 1) in all directions */
GLfloat xyScale = 2/size;
GLfloat zScale = 2/(far-near); 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 */ /* Move the volume on z into (-1, 1) range */
rawProjectionMatrix = Matrix4::translation(Vector3::zAxis(-1-near*zScale))*rawProjectionMatrix; rawProjectionMatrix = Matrix4::translation(Vector3::zAxis(-1-near*zScale))*rawProjectionMatrix;
projectionAspectRatio = size;
fixAspectRatio(); fixAspectRatio();
} }
@ -116,6 +118,7 @@ void Camera3D::setPerspective(GLfloat fov, GLfloat near, GLfloat far) {
/* And... another magic */ /* And... another magic */
rawProjectionMatrix[3][3] = 0; rawProjectionMatrix[3][3] = 0;
projectionAspectRatio = Vector2(xyScale);
fixAspectRatio(); fixAspectRatio();
} }

13
src/SceneGraph/Camera.h

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

40
src/SceneGraph/Test/CameraTest.cpp

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

Loading…
Cancel
Save