diff --git a/src/camera.cpp b/src/camera.cpp
index d5d453c5..533a4e0d 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -31,7 +31,7 @@ Camera::Camera()
m_gamegroup = GAMEGROUP_BEFORE;
m_drawgroup = DRAWGROUP_CAMERA;
- ivec2 screen_size = Video::GetSize();
+ ivec2 screen_size = (g_renderer)?(Video::GetSize()):(ivec2(0));
m_fov = 45.f;
m_near = -1000.f;
m_far = 1000.f;
diff --git a/test/Makefile.am b/test/Makefile.am
index 45795d1b..04f8f7aa 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -20,7 +20,7 @@ testsuite_SOURCES = testsuite.cpp \
unit/build.cpp unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp \
unit/array.cpp unit/rotation.cpp unit/string.cpp unit/map.cpp \
unit/color.cpp unit/atomic.cpp unit/interp.cpp unit/box.cpp \
- unit/rand.cpp unit/thread.cpp
+ unit/rand.cpp unit/thread.cpp unit/camera.cpp
testsuite_CPPFLAGS = $(AM_CPPFLAGS)
testsuite_DEPENDENCIES = @LOL_DEPS@
noinst_DATA = data/gradient.png
diff --git a/test/testsuite.vcxproj b/test/testsuite.vcxproj
index 55214223..47371548 100644
--- a/test/testsuite.vcxproj
+++ b/test/testsuite.vcxproj
@@ -47,6 +47,7 @@
+
@@ -94,4 +95,4 @@
-
+
\ No newline at end of file
diff --git a/test/unit/camera.cpp b/test/unit/camera.cpp
new file mode 100644
index 00000000..b090ff54
--- /dev/null
+++ b/test/unit/camera.cpp
@@ -0,0 +1,191 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2013 Sam Hocevar
+// (c) 2013 Benjamin "Touky" Huet
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the Do What The Fuck You Want To
+// Public License, Version 2, as published by Sam Hocevar. See
+// http://www.wtfpl.net/ for more details.
+//
+
+#if defined HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "core.h"
+#include "lol/unit.h"
+
+namespace lol
+{
+
+LOLUNIT_FIXTURE(CameraTest)
+{
+ Camera tc;
+ vec3 eye;
+ vec3 target;
+ vec3 up;
+ mat4 m_lookat;
+ quat q_lookat;
+ vec3 v_lookat;
+ float fov;
+ float screen_size;
+ float screen_ratio;
+ float near;
+ float far;
+ bool is_shifted;
+
+ void SetUp()
+ {
+ eye = vec3(0.f, 50.f, 50.f);
+ target = vec3(0.f);
+ up = vec3(0.f, 1.f, 0.f);
+ m_lookat = mat4::lookat(eye, target, up);
+ q_lookat = quat(m_lookat);
+ v_lookat = vec3::toeuler(q_lookat);
+ fov = 90.f;
+ screen_size = 800.f;
+ screen_ratio = 1.0f;
+ near = 1.f;
+ far = 1000.f;
+ is_shifted = false;
+ }
+
+ void TearDown() {}
+
+#define TEST_VECTOR(v0, v1) \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(v0.x, v1.x, 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(v0.y, v1.y, 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(v0.z, v1.z, 1.e-5f);
+
+ LOLUNIT_TEST(SetViewTest)
+ {
+ tc.SetView(eye, target, up);
+ TEST_VECTOR(eye, tc.GetPosition());
+ TEST_VECTOR(target, tc.GetTarget());
+ TEST_VECTOR(up, tc.GetUp());
+
+ tc.SetView(eye, q_lookat);
+ TEST_VECTOR(eye, tc.GetPosition());
+ TEST_VECTOR(target, tc.GetTarget());
+ TEST_VECTOR(up, tc.GetUp());
+
+ tc.SetView(eye, v_lookat);
+ TEST_VECTOR(eye, tc.GetPosition());
+ TEST_VECTOR(target, tc.GetTarget());
+ TEST_VECTOR(up, tc.GetUp());
+
+ tc.SetView(m_lookat);
+ TEST_VECTOR(eye, tc.GetPosition());
+ TEST_VECTOR(target, tc.GetTarget());
+ TEST_VECTOR(up, tc.GetUp());
+ }
+
+#define TEST_MATRIX(m0, m1) \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[0][0], m1[0][0], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[1][0], m1[1][0], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[2][0], m1[2][0], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[3][0], m1[3][0], 1.e-5f); \
+ \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[0][1], m1[0][1], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[1][1], m1[1][1], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[2][1], m1[2][1], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[3][1], m1[3][1], 1.e-5f); \
+ \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[0][2], m1[0][2], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[1][2], m1[1][2], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[2][2], m1[2][2], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[3][2], m1[3][2], 1.e-5f); \
+ \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[0][3], m1[0][3], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[1][3], m1[1][3], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[2][3], m1[2][3], 1.e-5f); \
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(m0[3][3], m1[3][3], 1.e-5f);
+
+
+ LOLUNIT_TEST(SetProjectionTest)
+ {
+ mat4 refmx = mat4::perspective(fov, screen_size, screen_ratio, near, far);
+
+ tc.SetProjection(refmx);
+ TEST_MATRIX(refmx, tc.GetProjection());
+
+ tc.SetProjection(fov, near, far);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+
+ tc.SetProjection(fov, near, far, screen_size, screen_ratio);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+
+ tc.SetFov(fov);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+
+ tc.SetScreenInfos(screen_size);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+
+ tc.SetScreenInfos(screen_size, screen_ratio);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+
+ tc.SetDrawInfos(far);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+
+ tc.SetDrawInfos(near, far);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+
+ is_shifted = true;
+ refmx = mat4::shifted_perspective(fov, screen_size, screen_ratio, far - near);
+
+ tc.UseShift(is_shifted);
+ TEST_MATRIX(refmx, tc.GetProjection());
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(fov, tc.GetFov(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_size, tc.GetScreenSize(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(screen_ratio, tc.GetScreenRatio(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(near, tc.GetNear(), 1.e-5f);
+ LOLUNIT_ASSERT_DOUBLES_EQUAL(far, tc.GetFar(), 1.e-5f);
+ LOLUNIT_ASSERT(is_shifted != tc.IsShifted());
+ }
+};
+
+} /* namespace lol */
+