diff --git a/src/Makefile.am b/src/Makefile.am index 8468c936..06cb3a20 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,13 +2,14 @@ noinst_LIBRARIES = liblol.a liblol_a_SOURCES = \ - core.h matrix.h tiler.cpp tiler.h dict.cpp dict.h audio.cpp audio.h \ - scene.cpp scene.h font.cpp font.h layer.cpp layer.h map.cpp map.h \ - entity.cpp entity.h ticker.cpp ticker.h tileset.cpp tileset.h \ - forge.cpp forge.h video.cpp video.h timer.cpp timer.h bitfield.h \ - profiler.cpp profiler.h input.h input.cpp world.cpp world.h \ - sample.cpp sample.h sampler.cpp sampler.h text.cpp text.h \ - emitter.cpp emitter.h numeric.h worldentity.cpp worldentity.h \ + core.h matrix.cpp matrix.h tiler.cpp tiler.h dict.cpp dict.h \ + audio.cpp audio.h scene.cpp scene.h font.cpp font.h layer.cpp layer.h \ + map.cpp map.h entity.cpp entity.h ticker.cpp ticker.h \ + tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h \ + timer.cpp timer.h bitfield.h profiler.cpp profiler.h input.h input.cpp \ + world.cpp world.h sample.cpp sample.h sampler.cpp sampler.h \ + text.cpp text.h emitter.cpp emitter.h numeric.h \ + worldentity.cpp worldentity.h \ \ sdlinput.cpp sdlinput.h \ \ diff --git a/src/matrix.cpp b/src/matrix.cpp new file mode 100644 index 00000000..16b36d73 --- /dev/null +++ b/src/matrix.cpp @@ -0,0 +1,64 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2011 Sam Hocevar +// 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://sam.zoy.org/projects/COPYING.WTFPL for more details. +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include /* free() */ +#include /* strdup() */ + +#include "core.h" + +static inline float det3(float a, float b, float c, + float d, float e, float f, + float g, float h, float i) +{ + return a * (e * i - h * f) + + b * (f * g - i * d) + + c * (d * h - g * e); +} + +static inline float cofact3(float4x4 const &mat, int i, int j) +{ + return det3(mat[(i + 1) & 3][(j + 1) & 3], + mat[(i + 2) & 3][(j + 1) & 3], + mat[(i + 3) & 3][(j + 1) & 3], + mat[(i + 1) & 3][(j + 2) & 3], + mat[(i + 2) & 3][(j + 2) & 3], + mat[(i + 3) & 3][(j + 2) & 3], + mat[(i + 1) & 3][(j + 3) & 3], + mat[(i + 2) & 3][(j + 3) & 3], + mat[(i + 3) & 3][(j + 3) & 3]) * (((i + j) & 1) ? -1.0f : 1.0f); +} + +template<> float float4x4::det() const +{ + float ret = 0; + for (int n = 0; n < 4; n++) + ret += (*this)[n][0] * cofact3(*this, n, 0); + return ret; +} + +template<> float4x4 float4x4::invert() const +{ + float4x4 ret; + float d = det(); + if (d) + { + d = 1.0f / d; + for (int j = 0; j < 4; j++) + for (int i = 0; i < 4; i++) + ret[j][i] = cofact3(*this, i, j) * d; + } + return ret; +} + diff --git a/src/matrix.h b/src/matrix.h index f58de454..8bd99494 100644 --- a/src/matrix.h +++ b/src/matrix.h @@ -175,37 +175,49 @@ GLOBALS(2) GLOBALS(3) GLOBALS(4) -template struct Vec4x4 +template struct Mat4 { - inline Vec4x4() { } - inline Vec4x4(T val) { v[0] = v[1] = v[2] = v[3] = val; } - inline Vec4x4(Vec4 v0, Vec4 v1, Vec4 v2, Vec4 v3) + inline Mat4() { } + inline Mat4(T val) { for (int i = 0; i < 4; i++) v[i] = val; } + inline Mat4(Vec4 v0, Vec4 v1, Vec4 v2, Vec4 v3) { v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; } inline Vec4& operator[](int n) { return v[n]; } inline Vec4 const& operator[](int n) const { return v[n]; } - inline Vec4x4 operator +(Vec4x4 const val) const + static inline Mat4 identity() { - Vec4x4 ret; + Mat4 ret; + for (int j = 0; j < 4; j++) + for (int i = 0; i < 4; i++) + ret[i][j] = i == j; + return ret; + } + + T det() const; + Mat4 invert() const; + + inline Mat4 operator +(Mat4 const val) const + { + Mat4 ret; for (int j = 0; j < 4; j++) for (int i = 0; i < 4; i++) ret[i][j] = v[i][j] + val[i][j]; return ret; } - inline Vec4x4 operator -(Vec4x4 const val) const + inline Mat4 operator -(Mat4 const val) const { - Vec4x4 ret; + Mat4 ret; for (int j = 0; j < 4; j++) for (int i = 0; i < 4; i++) ret[i][j] = v[i][j] - val[i][j]; return ret; } - inline Vec4x4 operator *(Vec4x4 const val) const + inline Mat4 operator *(Mat4 const val) const { - Vec4x4 ret; + Mat4 ret; for (int j = 0; j < 4; j++) for (int i = 0; i < 4; i++) { @@ -233,8 +245,8 @@ template struct Vec4x4 Vec4 v[4]; }; -typedef Vec4x4 float4x4; -typedef Vec4x4 int4x4; +typedef Mat4 float4x4; +typedef Mat4 int4x4; #endif // __DH_MATRIX_H__ diff --git a/test/matrix.cpp b/test/matrix.cpp index 4cb33587..097c7e9d 100644 --- a/test/matrix.cpp +++ b/test/matrix.cpp @@ -22,31 +22,94 @@ class MatrixTest : public CppUnit::TestCase { CPPUNIT_TEST_SUITE(MatrixTest); + CPPUNIT_TEST(test_mat_det); CPPUNIT_TEST(test_mat_mul); + CPPUNIT_TEST(test_mat_inv); CPPUNIT_TEST_SUITE_END(); public: MatrixTest() : CppUnit::TestCase("Matrix Test") {} - void setUp() {} + void setUp() + { + identity = float4x4::identity(); + triangular = float4x4(float4(1.0f, 0.0f, 0.0f, 0.0f), + float4(7.0f, 2.0f, 0.0f, 0.0f), + float4(1.0f, 5.0f, 3.0f, 0.0f), + float4(8.0f, 9.0f, 2.0f, 4.0f)); + invertible = float4x4(float4( 1.0f, 1.0f, 2.0f, -1.0f), + float4(-2.0f, -1.0f, -2.0f, 2.0f), + float4( 4.0f, 2.0f, 5.0f, -4.0f), + float4( 5.0f, -3.0f, -7.0f, -6.0f)); + } void tearDown() {} + void test_mat_det() + { + float d1 = triangular.det(); + CPPUNIT_ASSERT(d1 == 24.0f); + float d2 = invertible.det(); + CPPUNIT_ASSERT(d2 == -1.0f); + } + void test_mat_mul() { - float4 v0(1.0f, 0.0f, 0.0f, 0.0f); - float4 v1(0.0f, 1.0f, 0.0f, 0.0f); - float4 v2(0.0f, 0.0f, 1.0f, 0.0f); - float4 v3(0.0f, 0.0f, 0.0f, 1.0f); - float4x4 m0(v0, v1, v2, v3); - float4x4 m1(v0, v1, v2, v3); + float4x4 m0 = identity; + float4x4 m1 = identity; + float4x4 m2 = m0 * m1; + + CPPUNIT_ASSERT(m2[0][0] == 1.0f); + CPPUNIT_ASSERT(m2[1][0] == 0.0f); + CPPUNIT_ASSERT(m2[2][0] == 0.0f); + CPPUNIT_ASSERT(m2[3][0] == 0.0f); + + CPPUNIT_ASSERT(m2[0][1] == 0.0f); + CPPUNIT_ASSERT(m2[1][1] == 1.0f); + CPPUNIT_ASSERT(m2[2][1] == 0.0f); + CPPUNIT_ASSERT(m2[3][1] == 0.0f); + + CPPUNIT_ASSERT(m2[0][2] == 0.0f); + CPPUNIT_ASSERT(m2[1][2] == 0.0f); + CPPUNIT_ASSERT(m2[2][2] == 1.0f); + CPPUNIT_ASSERT(m2[3][2] == 0.0f); + + CPPUNIT_ASSERT(m2[0][3] == 0.0f); + CPPUNIT_ASSERT(m2[1][3] == 0.0f); + CPPUNIT_ASSERT(m2[2][3] == 0.0f); + CPPUNIT_ASSERT(m2[3][3] == 1.0f); + } + + void test_mat_inv() + { + float4x4 m0 = invertible; + float4x4 m1 = m0.invert(); + float4x4 m2 = m0 * m1; CPPUNIT_ASSERT(m2[0][0] == 1.0f); + CPPUNIT_ASSERT(m2[1][0] == 0.0f); + CPPUNIT_ASSERT(m2[2][0] == 0.0f); + CPPUNIT_ASSERT(m2[3][0] == 0.0f); + + CPPUNIT_ASSERT(m2[0][1] == 0.0f); CPPUNIT_ASSERT(m2[1][1] == 1.0f); + CPPUNIT_ASSERT(m2[2][1] == 0.0f); + CPPUNIT_ASSERT(m2[3][1] == 0.0f); + + CPPUNIT_ASSERT(m2[0][2] == 0.0f); + CPPUNIT_ASSERT(m2[1][2] == 0.0f); CPPUNIT_ASSERT(m2[2][2] == 1.0f); + CPPUNIT_ASSERT(m2[3][2] == 0.0f); + + CPPUNIT_ASSERT(m2[0][3] == 0.0f); + CPPUNIT_ASSERT(m2[1][3] == 0.0f); + CPPUNIT_ASSERT(m2[2][3] == 0.0f); CPPUNIT_ASSERT(m2[3][3] == 1.0f); } + +private: + float4x4 triangular, identity, invertible; }; CPPUNIT_TEST_SUITE_REGISTRATION(MatrixTest); diff --git a/win32/deushax.vcxproj b/win32/deushax.vcxproj index 6ebcfa03..733e0462 100644 --- a/win32/deushax.vcxproj +++ b/win32/deushax.vcxproj @@ -61,6 +61,7 @@ + diff --git a/win32/deushax.vcxproj.filters b/win32/deushax.vcxproj.filters index 674d5f3e..01f3d03f 100644 --- a/win32/deushax.vcxproj.filters +++ b/win32/deushax.vcxproj.filters @@ -136,6 +136,9 @@ lolengine + + lolengine + lolengine diff --git a/win32/editor.vcxproj b/win32/editor.vcxproj index feee25fe..d4018e8a 100644 --- a/win32/editor.vcxproj +++ b/win32/editor.vcxproj @@ -61,6 +61,7 @@ + diff --git a/win32/editor.vcxproj.filters b/win32/editor.vcxproj.filters index f11cc135..7ab417be 100644 --- a/win32/editor.vcxproj.filters +++ b/win32/editor.vcxproj.filters @@ -136,6 +136,9 @@ lolengine + + lolengine + lolengine @@ -182,4 +185,4 @@ - \ No newline at end of file + diff --git a/win32/monsterz.vcxproj b/win32/monsterz.vcxproj index 3b92ece2..b9fcdc41 100644 --- a/win32/monsterz.vcxproj +++ b/win32/monsterz.vcxproj @@ -70,6 +70,7 @@ + diff --git a/win32/monsterz.vcxproj.filters b/win32/monsterz.vcxproj.filters index 83ca1083..2a1e434b 100644 --- a/win32/monsterz.vcxproj.filters +++ b/win32/monsterz.vcxproj.filters @@ -141,6 +141,9 @@ lolengine + + lolengine + lolengine