Browse Source

Camera: computing projection scale directly from projection matrix.

Storing scale as independent (and inverted) value and updating it
separately from projection matrix is just plain wrong.
pull/279/head
Vladimír Vondruš 14 years ago
parent
commit
236e0abc58
  1. 11
      src/SceneGraph/Camera.cpp
  2. 5
      src/SceneGraph/Camera.h
  3. 24
      src/SceneGraph/Test/CameraTest.cpp

11
src/SceneGraph/Camera.cpp

@ -24,12 +24,12 @@ namespace Magnum { namespace SceneGraph {
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation { namespace Implementation {
template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2<GLsizei>& viewport) { template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionScale, const Math::Vector2<GLsizei>& viewport) {
/* Don't divide by zero / don't preserve anything */ /* Don't divide by zero / don't preserve anything */
if(projectionAspectRatio.x() == 0 || projectionAspectRatio.y() == 0 || viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved) if(projectionScale.x() == 0 || projectionScale.y() == 0 || viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved)
return MatrixType(); return MatrixType();
Vector2 relativeAspectRatio = Vector2::from(viewport)/projectionAspectRatio; Vector2 relativeAspectRatio = Vector2::from(viewport)*projectionScale;
/* 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 */
@ -46,7 +46,7 @@ template Matrix4 aspectRatioFix<Matrix4>(AspectRatioPolicy, const Vector2&, cons
} }
#endif #endif
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::NotPreserved) {} template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> Camera<MatrixType, VectorType, ObjectType, SceneType, CameraType>::Camera(ObjectType* parent): ObjectType(parent), _aspectRatioPolicy(AspectRatioPolicy::NotPreserved) {}
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);
@ -86,7 +86,6 @@ void Camera2D::setProjection(const Vector2& size) {
/* 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 */
rawProjectionMatrix = Matrix3::scaling(2.0f/size); rawProjectionMatrix = Matrix3::scaling(2.0f/size);
projectionAspectRatio = size;
fixAspectRatio(); fixAspectRatio();
} }
@ -104,7 +103,6 @@ void Camera3D::setOrthographic(const Vector2& size, GLfloat near, GLfloat far) {
0.0f, 0.0f, near*zScale-1, 1.0f 0.0f, 0.0f, near*zScale-1, 1.0f
); );
projectionAspectRatio = size;
fixAspectRatio(); fixAspectRatio();
} }
@ -122,7 +120,6 @@ void Camera3D::setPerspective(GLfloat fov, GLfloat near, GLfloat far) {
0.0f, 0.0f, (2*far*near)*zScale, 0.0f 0.0f, 0.0f, (2*far*near)*zScale, 0.0f
); );
projectionAspectRatio = Vector2(xyScale);
fixAspectRatio(); fixAspectRatio();
} }

5
src/SceneGraph/Camera.h

@ -38,7 +38,7 @@ namespace Implementation {
template<size_t dimensions> class Camera {}; template<size_t dimensions> class Camera {};
template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2<GLsizei>& viewport); template<class MatrixType> MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionScale, const Math::Vector2<GLsizei>& viewport);
/* These templates are instantiated in source file */ /* These templates are instantiated in source file */
extern template SCENEGRAPH_EXPORT Matrix3 aspectRatioFix<Matrix3>(AspectRatioPolicy, const Vector2&, const Math::Vector2<GLsizei>&); extern template SCENEGRAPH_EXPORT Matrix3 aspectRatioFix<Matrix3>(AspectRatioPolicy, const Vector2&, const Math::Vector2<GLsizei>&);
@ -131,10 +131,9 @@ 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, projectionAspectRatio, _viewport)*rawProjectionMatrix; _projectionMatrix = Implementation::aspectRatioFix<MatrixType>(_aspectRatioPolicy, {rawProjectionMatrix[0].x(), rawProjectionMatrix[1].y()}, _viewport)*rawProjectionMatrix;
} }
Vector2 projectionAspectRatio;
MatrixType rawProjectionMatrix; MatrixType rawProjectionMatrix;
AspectRatioPolicy _aspectRatioPolicy; AspectRatioPolicy _aspectRatioPolicy;
#endif #endif

24
src/SceneGraph/Test/CameraTest.cpp

@ -31,45 +31,45 @@ CameraTest::CameraTest() {
} }
void CameraTest::fixAspectRatio() { void CameraTest::fixAspectRatio() {
Vector2 projectionSize(2, 3); Vector2 projectionScale(0.5f, 1.0f/3.0f);
Math::Vector2<GLsizei> size(400, 300); Math::Vector2<GLsizei> size(400, 300);
/* Division by zero */ /* Division by zero */
Vector2 projectionSizeZeroY(2, 0); Vector2 projectionScaleZeroY(0.5f, 0.0f);
Vector2 projectionSizeZeroX(0, 2); Vector2 projectionScaleZeroX(0.0f, 0.5f);
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, projectionSizeZeroX, size), Matrix4()); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionScaleZeroX, size), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroY, size), Matrix4()); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionScaleZeroY, size), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionSize, sizeZeroY), Matrix4()); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionScale, sizeZeroY), Matrix4());
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, projectionSize, sizeZeroX), Matrix4()); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, projectionScale, sizeZeroX), Matrix4());
/* Not preserved */ /* Not preserved */
CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::NotPreserved, projectionSize, size), Matrix4()); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::NotPreserved, projectionScale, 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, Vector2(2.0f), size), expectedClip); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, Vector2(0.5f), size), expectedClip);
Matrix4 expectedClipRectangle(1.0f, 0.0f, 0.0f, 0.0f, Matrix4 expectedClipRectangle(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 2.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, 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, projectionSize, size), expectedClipRectangle); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Clip, projectionScale, 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, Vector2(2.0f), size), expectedExtend); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, Vector2(0.5f), size), expectedExtend);
Matrix4 expectedExtendRectangle(0.5f, 0.0f, 0.0f, 0.0f, Matrix4 expectedExtendRectangle(0.5f, 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, projectionSize, size), expectedExtendRectangle); CORRADE_COMPARE(Implementation::aspectRatioFix<Matrix4>(Implementation::AspectRatioPolicy::Extend, projectionScale, size), expectedExtendRectangle);
} }
void CameraTest::defaultProjection2D() { void CameraTest::defaultProjection2D() {

Loading…
Cancel
Save