From c6e14dd348eb82c80240f9340b75c2aad0e6c0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 02:42:34 +0200 Subject: [PATCH] SceneGraph: Initial support for projections with aspect ratio != 1:1. Orthographic projection done, perspective projection needs total rework, leaving it for later. --- src/SceneGraph/Camera.cpp | 23 +++++++++-------- src/SceneGraph/Camera.h | 13 ++++++---- src/SceneGraph/Test/CameraTest.cpp | 40 ++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 32fba23f8..5726e9596 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -24,26 +24,28 @@ namespace Magnum { namespace SceneGraph { #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { -template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport) { +template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& 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::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(AspectRatioPolicy, const Math::Vector2&); +template Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); } #endif -template Camera::Camera(ObjectType* parent): ObjectType(parent), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} +template Camera::Camera(ObjectType* parent): ObjectType(parent), projectionAspectRatio(1.0f), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} template void Camera::setViewport(const Math::Vector2& size) { Framebuffer::setViewport({0, 0}, size); @@ -79,18 +81,18 @@ template class Camera {}; - template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport); + template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& viewport); /* These templates are instantiated in source file */ - extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix(AspectRatioPolicy, const Math::Vector2&); + extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); } #endif @@ -130,9 +130,10 @@ template(_aspectRatioPolicy, _viewport)*rawProjectionMatrix; + _projectionMatrix = Implementation::aspectRatioFix(_aspectRatioPolicy, projectionAspectRatio, _viewport)*rawProjectionMatrix; } + Vector2 projectionAspectRatio; MatrixType rawProjectionMatrix; AspectRatioPolicy _aspectRatioPolicy; #endif @@ -172,20 +173,22 @@ class SCENEGRAPH_EXPORT Camera3D: public Camera size(400, 300); + /* Division by zero */ + Vector2 projectionSizeZeroY(2, 0); + Vector2 projectionSizeZeroX(0, 2); Math::Vector2 sizeZeroY(400, 0); Math::Vector2 sizeZeroX(0, 300); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, sizeZeroY), Matrix4()); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, sizeZeroX), Matrix4()); - - Math::Vector2 size(400, 300); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroX, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroY, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSize, sizeZeroY), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionSize, sizeZeroX), Matrix4()); /* Not preserved */ - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::NotPreserved, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(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(Implementation::AspectRatioPolicy::Clip, size), expectedClip); + CORRADE_COMPARE(Implementation::aspectRatioFix(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(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(Implementation::AspectRatioPolicy::Extend, size), expectedExtend); + CORRADE_COMPARE(Implementation::aspectRatioFix(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(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() {