Browse Source

Moved projection matrix computation to Math namespace.

pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
7d0a523618
  1. 12
      src/Math/Matrix3.h
  2. 57
      src/Math/Matrix4.h
  3. 10
      src/Math/Test/Matrix3Test.cpp
  4. 32
      src/Math/Test/Matrix4Test.cpp
  5. 3
      src/SceneGraph/Camera2D.h
  6. 3
      src/SceneGraph/Camera2D.hpp
  7. 37
      src/SceneGraph/Camera3D.h
  8. 32
      src/SceneGraph/Camera3D.hpp
  9. 55
      src/SceneGraph/Test/CameraTest.cpp

12
src/Math/Matrix3.h

@ -25,7 +25,7 @@
namespace Magnum { namespace Math {
/**
@brief 3x3 matrix for affine transformations in 2D
@brief 3x3 matrix for transformations in 2D
@tparam T Data type
Provides functions for transformations in 2D. See Matrix4 for 3D
@ -96,6 +96,16 @@ template<class T> class Matrix3: public Matrix<3, T> {
return from(Matrix<2, T>() - T(2)*normal*normal.transposed(), {});
}
/**
* @brief 2D projection matrix
* @param size Size of the view
*
* @see Matrix4::orthographicProjection(), Matrix4::perspectiveProjection()
*/
static Matrix3<T> projection(const Vector2<T>& size) {
return scaling(2.0f/size);
}
/**
* @brief Create matrix from rotation/scaling part and translation part
* @param rotationScaling Rotation/scaling part (upper-left 2x2

57
src/Math/Matrix4.h

@ -25,7 +25,7 @@
namespace Magnum { namespace Math {
/**
@brief 4x4 matrix for affine transformations in 3D
@brief 4x4 matrix for transformations in 3D
@tparam T Data type
Provides functions for transformations in 3D. See Matrix3 for 2D
@ -182,6 +182,61 @@ template<class T> class Matrix4: public Matrix<4, T> {
return from(Matrix<3, T>() - T(2)*normal*normal.transposed(), {});
}
/**
* @brief 3D orthographic projection matrix
* @param size Size of the view
* @param near Near clipping plane
* @param far Far clipping plane
*
* @see perspectiveProjection(), Matrix3::projection()
*/
static Matrix4<T> orthographicProjection(const Vector2<T>& size, T near, T far) {
Vector2<T> xyScale = T(2.0)/size;
T zScale = T(2.0)/(near-far);
return Matrix4<T>( /* Column-major! */
xyScale.x(), T(0.0), T(0.0), T(0.0),
T(0.0), xyScale.y(), T(0.0), T(0.0),
T(0.0), T(0.0), zScale, T(0.0),
T(0.0), T(0.0), near*zScale-1, T(1.0)
);
}
/**
* @brief 3D perspective projection matrix
* @param size Size of near clipping plane
* @param near Near clipping plane
* @param far Far clipping plane
*
* @see orthographicProjection(), Matrix3::projection()
*/
static Matrix4<T> perspectiveProjection(const Vector2<T>& size, T near, T far) {
Vector2<T> xyScale = 2*near/size;
T zScale = T(1.0)/(near-far);
return Matrix4<T>( /* Column-major! */
xyScale.x(), T(0.0), T(0.0), T(0.0),
T(0.0), xyScale.y(), T(0.0), T(0.0),
T(0.0), T(0.0), (far+near)*zScale, T(-1.0),
T(0.0), T(0.0), (2*far*near)*zScale, T(0.0)
);
}
/**
* @brief 3D perspective projection matrix
* @param fov Field of view angle (horizontal, in radians)
* @param aspectRatio Aspect ratio
* @param near Near clipping plane
* @param far Far clipping plane
*
* @see orthographicProjection(), Matrix3::projection()
*/
static Matrix4<T> perspectiveProjection(T fov, T aspectRatio, T near, T far) {
T xyScale = 2*std::tan(fov/2)*near;
return perspectiveProjection(Vector2<T>(xyScale, xyScale/aspectRatio), near, far);
}
/**
* @brief Create matrix from rotation/scaling part and translation part
* @param rotationScaling Rotation/scaling part (upper-left 3x3

10
src/Math/Test/Matrix3Test.cpp

@ -34,6 +34,7 @@ class Matrix3Test: public Corrade::TestSuite::Tester {
void scaling();
void rotation();
void reflection();
void projection();
void fromParts();
void rotationScalingPart();
void rotationPart();
@ -54,6 +55,7 @@ Matrix3Test::Matrix3Test() {
&Matrix3Test::scaling,
&Matrix3Test::rotation,
&Matrix3Test::reflection,
&Matrix3Test::projection,
&Matrix3Test::fromParts,
&Matrix3Test::rotationScalingPart,
&Matrix3Test::rotationPart,
@ -136,6 +138,14 @@ void Matrix3Test::reflection() {
CORRADE_COMPARE(actual, expected);
}
void Matrix3Test::projection() {
Matrix3 expected(2.0f/4.0f, 0.0f, 0.0f,
0.0f, 2.0f/3.0f, 0.0f,
0.0f, 0.0f, 1.0f);
CORRADE_COMPARE(Matrix3::projection({4.0f, 3.0f}), expected);
}
void Matrix3Test::fromParts() {
Matrix2 rotationScaling(
3.0f, 5.0f,

32
src/Math/Test/Matrix4Test.cpp

@ -37,6 +37,9 @@ class Matrix4Test: public Corrade::TestSuite::Tester {
void rotationY();
void rotationZ();
void reflection();
void orthographicProjection();
void perspectiveProjection();
void perspectiveProjectionFov();
void fromParts();
void rotationScalingPart();
void rotationPart();
@ -60,6 +63,9 @@ Matrix4Test::Matrix4Test() {
&Matrix4Test::rotationY,
&Matrix4Test::rotationZ,
&Matrix4Test::reflection,
&Matrix4Test::orthographicProjection,
&Matrix4Test::perspectiveProjection,
&Matrix4Test::perspectiveProjectionFov,
&Matrix4Test::fromParts,
&Matrix4Test::rotationScalingPart,
&Matrix4Test::rotationPart,
@ -180,6 +186,32 @@ void Matrix4Test::reflection() {
CORRADE_COMPARE(actual, expected);
}
void Matrix4Test::orthographicProjection() {
Matrix4 expected(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(Matrix4::orthographicProjection({5.0f, 4.0f}, 1, 9), expected);
}
void Matrix4Test::perspectiveProjection() {
Matrix4 expected(4.0f, 0.0f, 0.0f, 0.0f,
0.0f, 7.111111f, 0.0f, 0.0f,
0.0f, 0.0f, -1.9411764f, -1.0f,
0.0f, 0.0f, -94.1176452f, 0.0f);
CORRADE_COMPARE(Matrix4::perspectiveProjection({16.0f, 9.0f}, 32.0f, 100), expected);
}
void Matrix4Test::perspectiveProjectionFov() {
Matrix4 expected(4.1652994f, 0.0f, 0.0f, 0.0f,
0.0f, 9.788454f, 0.0f, 0.0f,
0.0f, 0.0f, -1.9411764f, -1.0f,
0.0f, 0.0f, -94.1176452f, 0.0f);
CORRADE_COMPARE(Matrix4::perspectiveProjection(deg(27.0f), 2.35f, 32.0f, 100), expected);
}
void Matrix4Test::fromParts() {
Matrix3 rotationScaling(
3.0f, 5.0f, 8.0f,

3
src/SceneGraph/Camera2D.h

@ -66,8 +66,7 @@ class MAGNUM_SCENEGRAPH_EXPORT Camera2D: public AbstractCamera<2, T> {
* @param size Size of the view
* @return Pointer to self (for method chaining)
*
* The area of given size will be scaled down to range @f$ [-1; 1] @f$
* on all directions.
* @see Matrix3::projection()
*/
Camera2D<T>* setProjection(const Math::Vector2<T>& size);

3
src/SceneGraph/Camera2D.hpp

@ -27,8 +27,7 @@ using namespace std;
namespace Magnum { namespace SceneGraph {
template<class T> Camera2D<T>* Camera2D<T>::setProjection(const Math::Vector2<T>& size) {
/* Scale the volume down so it fits in (-1, 1) in all directions */
AbstractCamera<2, T>::rawProjectionMatrix = Math::Matrix3<T>::scaling(2.0f/size);
AbstractCamera<2, T>::rawProjectionMatrix = Math::Matrix3<T>::projection(size);
AbstractCamera<2, T>::fixAspectRatio();
return this;

37
src/SceneGraph/Camera3D.h

@ -36,7 +36,7 @@ OpenGL unit cube `[(-1, -1, -1); (1, 1, 1)]` with orthographic projection and
doesn't do any aspect ratio correction. Common setup example:
@code
SceneGraph::Camera3D<>* camera = new SceneGraph::Camera3D<>(&cameraObject);
camera->setPerspective(deg(35.0f), 0.001f, 100.0f)
camera->setPerspective({}, 0.001f, 100.0f)
->setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend);
@endcode
@ -60,35 +60,42 @@ class MAGNUM_SCENEGRAPH_EXPORT Camera3D: public AbstractCamera<3, T> {
/**
* @brief Constructor
* @param object %Object holding this feature
*
* Sets orthographic projection to the default OpenGL cube
* (range @f$ [-1; 1] @f$ in all directions).
* @see setOrthographic(), setPerspective()
*/
inline explicit Camera3D(AbstractObject<3, T>* object): AbstractCamera<3, T>(object), _near(0.0f), _far(0.0f) {}
/**
* @brief Set orthographic projection
* @param size Size of the view
* @param near Near clipping plane
* @param far Far clipping plane
* @param size Size of the view
* @param near Near clipping plane
* @param far Far clipping plane
* @return Pointer to self (for method chaining)
*
* The volume of given size will be scaled down to range @f$ [-1; 1] @f$
* on all directions.
* @see setPerspective(), Matrix4::orthographicProjection()
*/
Camera3D<T>* setOrthographic(const Math::Vector2<T>& size, T near, T far);
/**
* @brief Set perspective projection
* @param fov Field of view angle
* @param near Near clipping plane
* @param far Far clipping plane
* @param size Size of near clipping plane
* @param near Near clipping plane
* @param far Far clipping plane
* @return Pointer to self (for method chaining)
*
* @see setOrthographic(), Matrix4::perspectiveProjection()
*/
Camera3D<T>* setPerspective(const Math::Vector2<T>& size, T near, T far);
/**
* @brief Set perspective projection
* @param fov Field of view angle (horizontal, in radians)
* @param aspectRatio Aspect ratio
* @param near Near clipping plane
* @param far Far clipping plane
* @return Pointer to self (for method chaining)
*
* @todo Aspect ratio
* @see setOrthographic(), Matrix4::perspectiveProjection()
*/
Camera3D<T>* setPerspective(T fov, T near, T far);
Camera3D<T>* setPerspective(T fov, T aspectRatio, T near, T far);
/** @brief Near clipping plane */
inline T near() const { return _near; }

32
src/SceneGraph/Camera3D.hpp

@ -27,37 +27,31 @@ using namespace std;
namespace Magnum { namespace SceneGraph {
template<class T> Camera3D<T>* Camera3D<T>::setOrthographic(const Math::Vector2<T>& size, T near, T far) {
/** @todo Get near/far from the matrix */
_near = near;
_far = far;
Math::Vector2<T> xyScale = T(2.0)/size;
T zScale = T(2.0)/(near-far);
AbstractCamera<3, T>::rawProjectionMatrix = Math::Matrix4<T>(
xyScale.x(), T(0.0), T(0.0), T(0.0),
T(0.0), xyScale.y(), T(0.0), T(0.0),
T(0.0), T(0.0), zScale, T(0.0),
T(0.0), T(0.0), near*zScale-1, T(1.0)
);
AbstractCamera<3, T>::rawProjectionMatrix = Math::Matrix4<T>::orthographicProjection(size, near, far);
AbstractCamera<3, T>::fixAspectRatio();
return this;
}
template<class T> Camera3D<T>* Camera3D<T>::setPerspective(T fov, T near, T far) {
template<class T> Camera3D<T>* Camera3D<T>::setPerspective(const Math::Vector2<T>& size, T near, T far) {
/** @todo Get near/far from the matrix */
_near = near;
_far = far;
T xyScale = T(1.0)/tan(fov/2); /* == near/size */
T zScale = T(1.0)/(near-far);
AbstractCamera<3, T>::rawProjectionMatrix = Math::Matrix4<T>::perspectiveProjection(size, near, far);
AbstractCamera<3, T>::fixAspectRatio();
return this;
}
AbstractCamera<3, T>::rawProjectionMatrix = Matrix4(
xyScale, T(0.0), T(0.0), T(0.0),
T(0.0), xyScale, T(0.0), T(0.0),
T(0.0), T(0.0), (far+near)*zScale, T(-1.0),
T(0.0), T(0.0), (2*far*near)*zScale, T(0.0)
);
template<class T> Camera3D<T>* Camera3D<T>::setPerspective(T fov, T aspectRatio, T near, T far) {
/** @todo Get near/far from the matrix */
_near = near;
_far = far;
AbstractCamera<3, T>::rawProjectionMatrix = Math::Matrix4<T>::perspectiveProjection(fov, aspectRatio, near, far);
AbstractCamera<3, T>::fixAspectRatio();
return this;
}

55
src/SceneGraph/Test/CameraTest.cpp

@ -33,9 +33,9 @@ class CameraTest: public Corrade::TestSuite::Tester {
void fixAspectRatio();
void defaultProjection2D();
void defaultProjection3D();
void projection2D();
void orthographic();
void perspective();
void projectionSize2D();
void projectionSizeOrthographic();
void projectionSizePerspective();
void projectionSizeViewport();
void draw();
};
@ -50,9 +50,9 @@ CameraTest::CameraTest() {
addTests(&CameraTest::fixAspectRatio,
&CameraTest::defaultProjection2D,
&CameraTest::defaultProjection3D,
&CameraTest::projection2D,
&CameraTest::orthographic,
&CameraTest::perspective,
&CameraTest::projectionSize2D,
&CameraTest::projectionSizeOrthographic,
&CameraTest::projectionSizePerspective,
&CameraTest::projectionSizeViewport,
&CameraTest::draw);
}
@ -113,58 +113,27 @@ void CameraTest::defaultProjection3D() {
CORRADE_COMPARE(camera.projectionSize(), Vector2(2.0f));
}
void CameraTest::projection2D() {
void CameraTest::projectionSize2D() {
Vector2 projectionSize(4.0f, 3.0f);
Object2D o;
Camera2D camera(&o);
camera.setProjection(projectionSize);
Matrix3 a(2.0f/4.0f, 0.0f, 0.0f,
0.0f, 2.0f/3.0f, 0.0f,
0.0f, 0.0f, 1.0f);
CORRADE_COMPARE(camera.projectionMatrix(), a);
CORRADE_COMPARE(camera.projectionSize(), projectionSize);
}
void CameraTest::orthographic() {
Vector2 projectionSize(5);
void CameraTest::projectionSizeOrthographic() {
Vector2 projectionSizeRectangle(5.0f, 4.0f);
Object3D o;
Camera3D camera(&o);
camera.setOrthographic(projectionSize, 1, 9);
Matrix4 a(0.4f, 0.0f, 0.0f, 0.0f,
0.0f, 0.4f, 0.0f, 0.0f,
0.0f, 0.0f, -0.25f, 0.0f,
0.0f, 0.0f, -1.25f, 1.0f);
CORRADE_COMPARE(camera.projectionMatrix(), a);
CORRADE_COMPARE(camera.projectionSize(), projectionSize);
Vector2 projectionSizeRectangle(5.0f, 4.0f);
camera.setOrthographic(projectionSizeRectangle, 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);
CORRADE_COMPARE(camera.projectionSize(), projectionSizeRectangle);
}
void CameraTest::perspective() {
void CameraTest::projectionSizePerspective() {
Object3D o;
Camera3D camera(&o);
camera.setPerspective(deg(27.0f), 32.0f, 100);
Matrix4 a(4.1652994f, 0.0f, 0.0f, 0.0f,
0.0f, 4.1652994f, 0.0f, 0.0f,
0.0f, 0.0f, -1.9411764f, -1.0f,
0.0f, 0.0f, -94.1176452f, 0.0f);
CORRADE_COMPARE(camera.projectionMatrix(), a);
CORRADE_COMPARE(camera.projectionSize(), Vector2(0.48015756f));
camera.setPerspective(deg(27.0f), 2.35f, 32.0f, 100);
CORRADE_COMPARE(camera.projectionSize(), Vector2(0.48015756f, 0.204322f));
}
void CameraTest::projectionSizeViewport() {

Loading…
Cancel
Save