From 8abafbc6863027afd02145534f05f82607e0ae20 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Thu, 26 Jun 2014 15:32:05 +0000 Subject: [PATCH] math: add Array3D template class. Happy, Touky? :-) --- src/Makefile.am | 2 +- src/lol/math/all.h | 1 + src/lol/math/array3d.h | 215 ++++++++++++++++++++++++++++++++++++ src/lolcore.vcxproj | 1 + src/lolcore.vcxproj.filters | 3 + test/Makefile.am | 7 +- test/testsuite.vcxproj | 2 + test/unit/array2d.cpp | 51 +++++++++ test/unit/array3d.cpp | 51 +++++++++ 9 files changed, 329 insertions(+), 4 deletions(-) create mode 100644 src/lol/math/array3d.h create mode 100644 test/unit/array2d.cpp create mode 100644 test/unit/array3d.cpp diff --git a/src/Makefile.am b/src/Makefile.am index f5bc3b15..0e448a5c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,7 +40,7 @@ liblolcore_headers = \ lol/math/all.h \ lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \ lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \ - lol/math/constants.h \ + lol/math/array3d.h lol/math/constants.h \ \ lol/algorithm/all.h \ lol/algorithm/sort.h lol/algorithm/portal.h lol/algorithm/aabb_tree.h \ diff --git a/src/lol/math/all.h b/src/lol/math/all.h index 7cd9fb2e..24cfe955 100644 --- a/src/lol/math/all.h +++ b/src/lol/math/all.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/src/lol/math/array3d.h b/src/lol/math/array3d.h new file mode 100644 index 00000000..391bec9c --- /dev/null +++ b/src/lol/math/array3d.h @@ -0,0 +1,215 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar +// (c) 2013-2014 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. +// + +// +// The Array3D class +// ----------------- +// A very simple 3D array class allowing var[i][j][k] indexing, with some nice +// additional features, eg. Array3D for automatic arrays of tuples. +// + +// +// FIXME: This file is in lol/math/ instead of lol/base/ because it +// uses ivec3. +// + +#if !defined __LOL_MATH_ARRAY3D_H__ +#define __LOL_MATH_ARRAY3D_H__ + +#include +#include + +namespace lol +{ + +template +class Array3D : protected Array +{ +public: + typedef Array Super; + typedef typename Super::Element Element; + + inline Array3D() + : m_size(0, 0, 0) + { + } + + inline Array3D(int w, int h, int d) + { + SetSize(ivec3(w, h, d)); + } + + inline Array3D(ivec3 size) + { + SetSize(size); + } + + /* Access elements directly using an ivec3 index */ + inline Element const &operator [](ivec3 pos) const + { + ASSERT(pos.x >= 0); + ASSERT(pos.y >= 0); + ASSERT(pos.z >= 0); + ASSERT(pos.x < m_size.x); + ASSERT(pos.y < m_size.y); + ASSERT(pos.z < m_size.z); + + int n = (pos.z * m_size.y + pos.y) * m_size.x + pos.x; + ASSERT(n >= 0); + ASSERT(n < this->m_count); + + return this->m_data[n]; + } + + inline Element &operator [](ivec3 pos) + { + ASSERT(pos.x >= 0); + ASSERT(pos.y >= 0); + ASSERT(pos.z >= 0); + ASSERT(pos.x < m_size.x); + ASSERT(pos.y < m_size.y); + ASSERT(pos.z < m_size.z); + + int n = (pos.z * m_size.y + pos.y) * m_size.x + pos.x; + ASSERT(n >= 0); + ASSERT(n < this->m_count); + + return this->m_data[n]; + } + + class Slice + { + public: + inline Slice(Array3D &array, int i) + : m_array(array), + m_slice(i) + { + } + + class Line + { + public: + inline Line(Array3D &array, ivec2 ij) + : m_array(array), + m_line(ij) + { + } + + inline Element &operator [](int k) + { + ASSERT(k >= 0); + ASSERT(k < m_array.m_size.z); + return m_array[ivec3(m_line, k)]; + } + + private: + Array3D &m_array; + ivec2 m_line; + }; + + inline class Line operator [](int j) + { + ASSERT(j >= 0); + ASSERT(j < m_array.m_size.y); + return Line(m_array, ivec2(m_slice, j)); + } + + private: + Array3D &m_array; + int m_slice; + }; + + class ConstSlice + { + public: + inline ConstSlice(Array3D const &array, int i) + : m_array(array), + m_slice(i) + { + } + + class Line + { + public: + inline Line(Array3D const &array, ivec2 ij) + : m_array(array), + m_line(ij) + { + } + + inline Element const &operator [](int k) const + { + ASSERT(k >= 0); + ASSERT(k < m_array.m_size.z); + return m_array[ivec3(m_line, k)]; + } + + private: + Array3D const &m_array; + ivec2 m_line; + }; + + inline class Line operator [](int j) const + { + ASSERT(j >= 0); + ASSERT(j < m_array.m_size.y); + return Line(m_array, ivec2(m_slice, j)); + } + + private: + Array3D const &m_array; + int m_slice; + }; + + /* Access addressable slices, allowing for array[i][j][k] syntax. */ + inline class Slice operator [](int i) + { + ASSERT(i >= 0); + ASSERT(i < m_size.x); + return Slice(*this, i); + } + + inline class ConstSlice operator [](int i) const + { + ASSERT(i >= 0); + ASSERT(i < m_size.x); + return ConstSlice(*this, i); + } + + /* Resize the array. + * FIXME: data gets scrambled; should we care? */ + inline void SetSize(ivec3 size, Element e = Element()) + { + this->Resize(size.x * size.y * size.z, e); + m_size = size; + } + + inline ivec3 GetSize() const + { + return m_size; + } + +public: + inline Element *Data() { return Super::Data(); } + inline Element const *Data() const { return Super::Data(); } + inline int Count() const { return Super::Count(); } + inline int Bytes() const { return Super::Bytes(); } + +private: + ivec3 m_size; +}; + +} /* namespace lol */ + +#endif // __LOL_MATH_ARRAY3D_H__ + diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index 708d85d0..ec7f5edd 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -316,6 +316,7 @@ + diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters index 83511936..5eed2457 100644 --- a/src/lolcore.vcxproj.filters +++ b/src/lolcore.vcxproj.filters @@ -615,6 +615,9 @@ lol\base + + lol\base + lol\math diff --git a/test/Makefile.am b/test/Makefile.am index e9b9878e..55157eba 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -18,9 +18,10 @@ endif testsuite_SOURCES = testsuite.cpp \ unit/vector.cpp unit/matrix.cpp unit/half.cpp unit/trig.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/camera.cpp unit/enum.cpp + unit/array.cpp unit/array2d.cpp unit/array3d.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/camera.cpp unit/enum.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 9b5e6c06..a2933aeb 100644 --- a/test/testsuite.vcxproj +++ b/test/testsuite.vcxproj @@ -45,6 +45,8 @@ + + diff --git a/test/unit/array2d.cpp b/test/unit/array2d.cpp new file mode 100644 index 00000000..22eead3b --- /dev/null +++ b/test/unit/array2d.cpp @@ -0,0 +1,51 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 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://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(Array2DTest) +{ + void SetUp() {} + + void TearDown() {} + + LOLUNIT_TEST(Array2DCreate) + { + Array2D a(ivec2(10, 10)); + + a[0][0] = 2; + a[9][0] = 4; + a[0][9] = 6; + a[9][9] = 8; + + LOLUNIT_ASSERT_EQUAL(a[0][0], 2); + LOLUNIT_ASSERT_EQUAL(a[9][0], 4); + LOLUNIT_ASSERT_EQUAL(a[0][9], 6); + LOLUNIT_ASSERT_EQUAL(a[9][9], 8); + + Array2D const &b = a; + + LOLUNIT_ASSERT_EQUAL(b[0][0], 2); + LOLUNIT_ASSERT_EQUAL(b[9][0], 4); + LOLUNIT_ASSERT_EQUAL(b[0][9], 6); + LOLUNIT_ASSERT_EQUAL(b[9][9], 8); + } +}; + +} /* namespace lol */ + diff --git a/test/unit/array3d.cpp b/test/unit/array3d.cpp new file mode 100644 index 00000000..727e3e3e --- /dev/null +++ b/test/unit/array3d.cpp @@ -0,0 +1,51 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 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://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(Array3DTest) +{ + void SetUp() {} + + void TearDown() {} + + LOLUNIT_TEST(Array3DCreate) + { + Array3D a(ivec3(10, 10, 10)); + + a[0][0][0] = 2; + a[9][0][0] = 4; + a[0][9][9] = 6; + a[9][9][9] = 8; + + LOLUNIT_ASSERT_EQUAL(a[0][0][0], 2); + LOLUNIT_ASSERT_EQUAL(a[9][0][0], 4); + LOLUNIT_ASSERT_EQUAL(a[0][9][9], 6); + LOLUNIT_ASSERT_EQUAL(a[9][9][9], 8); + + Array3D const &b = a; + + LOLUNIT_ASSERT_EQUAL(b[0][0][0], 2); + LOLUNIT_ASSERT_EQUAL(b[9][0][0], 4); + LOLUNIT_ASSERT_EQUAL(b[0][9][9], 6); + LOLUNIT_ASSERT_EQUAL(b[9][9][9], 8); + } +}; + +} /* namespace lol */ +