diff --git a/src/Camera.cpp b/src/Camera.cpp
index 45e12d31e..72f2de11b 100644
--- a/src/Camera.cpp
+++ b/src/Camera.cpp
@@ -18,6 +18,41 @@
namespace Magnum {
Camera::Camera(AbstractObject* parent): AbstractObject(parent), viewportWidth(0), viewportHeight(0), _aspectRatioPolicy(Extend) {
+ setOrthographic(2, 1, 1000);
+}
+
+void Camera::setOrthographic(GLfloat size, GLfloat near, GLfloat 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);
+
+ /* Move the volume on z into (-1, 1) range */
+ rawProjectionMatrix = Matrix4::translation(0, 0, -1-near*zScale)*rawProjectionMatrix;
+
+ fixAspectRatio();
+}
+
+void Camera::setPerspective(GLfloat fov, GLfloat near, GLfloat far) {
+ /* First move the volume on z in (-1, 1) range */
+ rawProjectionMatrix = Matrix4::translation(0, 0, 2*far*near/(far+near));
+
+ /* Then apply magic perspective matrix (with reversed Z) */
+ static GLfloat a[] = { 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, -1, -1,
+ 0, 0, 0, 0 };
+ rawProjectionMatrix = Matrix4(a)*rawProjectionMatrix;
+
+ /* Then scale the volume down so it fits in (-1, 1) in all directions */
+ GLfloat xyScale = 1/tan(fov/2);
+ GLfloat zScale = 1+2*near/(far-near);
+ rawProjectionMatrix = Matrix4::scaling(xyScale, xyScale, zScale)*rawProjectionMatrix;
+
+ /* And... another magic */
+ rawProjectionMatrix.set(3, 3, 0);
+
+ fixAspectRatio();
}
Matrix4 Camera::cameraMatrix() const {
diff --git a/src/Camera.h b/src/Camera.h
index 417bb5fd9..085699ee1 100644
--- a/src/Camera.h
+++ b/src/Camera.h
@@ -40,6 +40,8 @@ class Camera: public AbstractObject {
/**
* @brief Constructor
* @param parent Parent object
+ *
+ * Calls setOrthographic(2, 1, 1000).
*/
Camera(AbstractObject* parent = 0);
@@ -49,6 +51,25 @@ class Camera: public AbstractObject {
/** @brief Set aspect ratio policy */
void setAspectRatioPolicy(AspectRatioPolicy policy) { _aspectRatioPolicy = policy; }
+ /**
+ * @brief Set orthographic projection
+ * @param size Size of (square) view
+ * @param near Near clipping plane
+ * @param far Far clipping plane
+ *
+ * The volume of given size will be scaled down to range (-1, 1) on all
+ * directions.
+ */
+ void setOrthographic(GLfloat 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
+ */
+ void setPerspective(GLfloat fov, GLfloat near, GLfloat far);
+
/**
* @brief Camera matrix
*
diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt
index 17b1d14fa..4870d1582 100644
--- a/src/Test/CMakeLists.txt
+++ b/src/Test/CMakeLists.txt
@@ -1 +1,2 @@
magnum_add_test(AbstractObjectTest AbstractObjectTest.h AbstractObjectTest.cpp Magnum)
+magnum_add_test(CameraTest CameraTest.h CameraTest.cpp Magnum)
diff --git a/src/Test/CameraTest.cpp b/src/Test/CameraTest.cpp
new file mode 100644
index 000000000..40bb77e4e
--- /dev/null
+++ b/src/Test/CameraTest.cpp
@@ -0,0 +1,53 @@
+/*
+ Copyright © 2010 Vladimír Vondruš
+
+ This file is part of Magnum.
+
+ Magnum is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 3
+ only, as published by the Free Software Foundation.
+
+ Magnum is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License version 3 for more details.
+*/
+
+#include "CameraTest.h"
+#include "Camera.h"
+
+#include
+
+QTEST_APPLESS_MAIN(Magnum::Test::CameraTest)
+
+namespace Magnum { namespace Test {
+
+void CameraTest::orthographic() {
+ Camera camera;
+ camera.setOrthographic(5, 1, 9);
+
+ GLfloat a[] = {
+ 0.4f, 0, 0, 0,
+ 0, 0.4f, 0, 0,
+ 0, 0, -0.25f, 0,
+ 0, 0, -1.25f, 1
+ };
+
+ QVERIFY(camera.projectionMatrix() == a);
+}
+
+void CameraTest::perspective() {
+ Camera camera;
+ camera.setPerspective(27*PI/180, 32.0f, 100);
+
+ GLfloat a[] = {
+ 4.1652994f, 0, 0, 0,
+ 0, 4.1652994f, 0, 0,
+ 0, 0, -1.9411764f, -1,
+ 0, 0, -94.1176452f, 0
+ };
+
+ QVERIFY(camera.projectionMatrix() == Matrix4(a));
+}
+
+}}
diff --git a/src/Test/CameraTest.h b/src/Test/CameraTest.h
new file mode 100644
index 000000000..d3ce17513
--- /dev/null
+++ b/src/Test/CameraTest.h
@@ -0,0 +1,32 @@
+#ifndef Magnum_CameraTest_h
+#define Magnum_CameraTest_h
+/*
+ Copyright © 2010 Vladimír Vondruš
+
+ This file is part of Magnum.
+
+ Magnum is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 3
+ only, as published by the Free Software Foundation.
+
+ Magnum is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License version 3 for more details.
+*/
+
+#include
+
+namespace Magnum { namespace Test {
+
+class CameraTest: public QObject {
+ Q_OBJECT
+
+ private slots:
+ void orthographic();
+ void perspective();
+};
+
+}}
+
+#endif