[150] | 1 | // |
---|
[221] | 2 | // Lol Engine |
---|
[150] | 3 | // |
---|
[221] | 4 | // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> |
---|
| 5 | // This program is free software; you can redistribute it and/or |
---|
| 6 | // modify it under the terms of the Do What The Fuck You Want To |
---|
| 7 | // Public License, Version 2, as published by Sam Hocevar. See |
---|
| 8 | // http://sam.zoy.org/projects/COPYING.WTFPL for more details. |
---|
| 9 | // |
---|
[150] | 10 | |
---|
| 11 | // |
---|
| 12 | // The Matrix classes |
---|
| 13 | // ------------------ |
---|
| 14 | // |
---|
| 15 | |
---|
[748] | 16 | #if !defined __LOL_MATRIX_H__ |
---|
| 17 | #define __LOL_MATRIX_H__ |
---|
[150] | 18 | |
---|
[239] | 19 | #include <cmath> |
---|
[939] | 20 | #if !defined __ANDROID__ |
---|
| 21 | # include <iostream> |
---|
| 22 | #endif |
---|
[239] | 23 | |
---|
[686] | 24 | namespace lol |
---|
| 25 | { |
---|
| 26 | |
---|
[239] | 27 | #define VECTOR_OP(elems, op) \ |
---|
[240] | 28 | template<typename U> \ |
---|
| 29 | inline Vec##elems<T> operator op(Vec##elems<U> const &val) const \ |
---|
[237] | 30 | { \ |
---|
| 31 | Vec##elems<T> ret; \ |
---|
| 32 | for (int n = 0; n < elems; n++) \ |
---|
[239] | 33 | ret[n] = (*this)[n] op val[n]; \ |
---|
[237] | 34 | return ret; \ |
---|
[663] | 35 | } \ |
---|
| 36 | \ |
---|
| 37 | template<typename U> \ |
---|
| 38 | inline Vec##elems<T> operator op##=(Vec##elems<U> const &val) \ |
---|
| 39 | { \ |
---|
| 40 | return *this = (*this) op val; \ |
---|
[239] | 41 | } |
---|
| 42 | |
---|
[757] | 43 | #define BOOL_OP(elems, op, op2, ret) \ |
---|
[244] | 44 | inline bool operator op(Vec##elems<T> const &val) const \ |
---|
| 45 | { \ |
---|
| 46 | for (int n = 0; n < elems; n++) \ |
---|
[757] | 47 | if (!((*this)[n] op2 val[n])) \ |
---|
| 48 | return !ret; \ |
---|
| 49 | return ret; \ |
---|
[244] | 50 | } |
---|
| 51 | |
---|
[239] | 52 | #define SCALAR_OP(elems, op) \ |
---|
| 53 | inline Vec##elems<T> operator op(T const &val) const \ |
---|
[237] | 54 | { \ |
---|
| 55 | Vec##elems<T> ret; \ |
---|
| 56 | for (int n = 0; n < elems; n++) \ |
---|
[239] | 57 | ret[n] = (*this)[n] op val; \ |
---|
[237] | 58 | return ret; \ |
---|
[663] | 59 | } \ |
---|
| 60 | \ |
---|
| 61 | inline Vec##elems<T> operator op##=(T const &val) \ |
---|
| 62 | { \ |
---|
| 63 | return *this = (*this) op val; \ |
---|
[237] | 64 | } |
---|
| 65 | |
---|
[295] | 66 | #define CAST_OP(elems, dest) \ |
---|
| 67 | inline operator Vec##dest<T>() const \ |
---|
| 68 | { \ |
---|
| 69 | Vec##dest<T> ret; \ |
---|
| 70 | for (int n = 0; n < elems && n < dest; n++) \ |
---|
| 71 | ret[n] = (*this)[n]; \ |
---|
[815] | 72 | for (int n = elems; n < dest; n++) \ |
---|
| 73 | ret[n] = 0; \ |
---|
[295] | 74 | return ret; \ |
---|
| 75 | } |
---|
| 76 | |
---|
[239] | 77 | #define OPERATORS(elems) \ |
---|
[240] | 78 | inline T& operator[](int n) { return *(&x + n); } \ |
---|
| 79 | inline T const& operator[](int n) const { return *(&x + n); } \ |
---|
[239] | 80 | \ |
---|
| 81 | VECTOR_OP(elems, -) \ |
---|
| 82 | VECTOR_OP(elems, +) \ |
---|
| 83 | VECTOR_OP(elems, *) \ |
---|
| 84 | VECTOR_OP(elems, /) \ |
---|
| 85 | \ |
---|
[757] | 86 | BOOL_OP(elems, ==, ==, true) \ |
---|
| 87 | BOOL_OP(elems, !=, ==, false) \ |
---|
| 88 | BOOL_OP(elems, <=, <=, true) \ |
---|
| 89 | BOOL_OP(elems, >=, >=, true) \ |
---|
| 90 | BOOL_OP(elems, <, <, true) \ |
---|
| 91 | BOOL_OP(elems, >, >, true) \ |
---|
[244] | 92 | \ |
---|
[239] | 93 | SCALAR_OP(elems, -) \ |
---|
| 94 | SCALAR_OP(elems, +) \ |
---|
| 95 | SCALAR_OP(elems, *) \ |
---|
| 96 | SCALAR_OP(elems, /) \ |
---|
| 97 | \ |
---|
[295] | 98 | CAST_OP(elems, 2) \ |
---|
| 99 | CAST_OP(elems, 3) \ |
---|
| 100 | CAST_OP(elems, 4) \ |
---|
| 101 | \ |
---|
[240] | 102 | template<typename U> \ |
---|
| 103 | inline operator Vec##elems<U>() const \ |
---|
| 104 | { \ |
---|
| 105 | Vec##elems<U> ret; \ |
---|
| 106 | for (int n = 0; n < elems; n++) \ |
---|
| 107 | ret[n] = static_cast<U>((*this)[n]); \ |
---|
| 108 | return ret; \ |
---|
| 109 | } \ |
---|
| 110 | \ |
---|
[768] | 111 | inline Vec##elems<T> operator -() const \ |
---|
| 112 | { \ |
---|
| 113 | Vec##elems<T> ret; \ |
---|
| 114 | for (int n = 0; n < elems; n++) \ |
---|
| 115 | ret[n] = -(*this)[n]; \ |
---|
| 116 | return ret; \ |
---|
| 117 | } \ |
---|
| 118 | \ |
---|
[242] | 119 | inline T sqlen() const \ |
---|
[239] | 120 | { \ |
---|
| 121 | T acc = 0; \ |
---|
| 122 | for (int n = 0; n < elems; n++) \ |
---|
| 123 | acc += (*this)[n] * (*this)[n]; \ |
---|
[242] | 124 | return acc; \ |
---|
| 125 | } \ |
---|
| 126 | \ |
---|
| 127 | inline float len() const \ |
---|
| 128 | { \ |
---|
[761] | 129 | using namespace std; \ |
---|
| 130 | return sqrtf((float)sqlen()); \ |
---|
[939] | 131 | } |
---|
[239] | 132 | |
---|
[295] | 133 | template <typename T> struct Vec2; |
---|
| 134 | template <typename T> struct Vec3; |
---|
| 135 | template <typename T> struct Vec4; |
---|
| 136 | |
---|
[237] | 137 | template <typename T> struct Vec2 |
---|
[150] | 138 | { |
---|
[643] | 139 | inline Vec2() { } |
---|
[240] | 140 | inline Vec2(T val) { x = y = val; } |
---|
| 141 | inline Vec2(T _x, T _y) { x = _x; y = _y; } |
---|
[150] | 142 | |
---|
[237] | 143 | OPERATORS(2) |
---|
| 144 | |
---|
[939] | 145 | #if !defined __ANDROID__ |
---|
| 146 | template<typename U> |
---|
| 147 | friend std::ostream &operator<<(std::ostream &stream, Vec2<U> const &v); |
---|
| 148 | #endif |
---|
| 149 | |
---|
[232] | 150 | union { T x; T a; T i; }; |
---|
| 151 | union { T y; T b; T j; }; |
---|
[150] | 152 | }; |
---|
| 153 | |
---|
[663] | 154 | typedef Vec2<float> vec2; |
---|
[863] | 155 | typedef Vec2<int> ivec2; |
---|
[232] | 156 | |
---|
[237] | 157 | template <typename T> struct Vec3 |
---|
[150] | 158 | { |
---|
[643] | 159 | inline Vec3() { } |
---|
[240] | 160 | inline Vec3(T val) { x = y = z = val; } |
---|
| 161 | inline Vec3(T _x, T _y, T _z) { x = _x; y = _y; z = _z; } |
---|
[152] | 162 | |
---|
[237] | 163 | OPERATORS(3) |
---|
| 164 | |
---|
[939] | 165 | #if !defined __ANDROID__ |
---|
| 166 | template<typename U> |
---|
| 167 | friend std::ostream &operator<<(std::ostream &stream, Vec3<U> const &v); |
---|
| 168 | #endif |
---|
| 169 | |
---|
[232] | 170 | union { T x; T a; T i; }; |
---|
| 171 | union { T y; T b; T j; }; |
---|
| 172 | union { T z; T c; T k; }; |
---|
[150] | 173 | }; |
---|
| 174 | |
---|
[663] | 175 | typedef Vec3<float> vec3; |
---|
[866] | 176 | typedef Vec3<int> ivec3; |
---|
[232] | 177 | |
---|
[294] | 178 | template <typename T> struct Vec4 |
---|
| 179 | { |
---|
[643] | 180 | inline Vec4() { } |
---|
[294] | 181 | inline Vec4(T val) { x = y = z = w = val; } |
---|
| 182 | inline Vec4(T _x, T _y, T _z, T _w) { x = _x; y = _y; z = _z; w = _w; } |
---|
| 183 | |
---|
| 184 | OPERATORS(4) |
---|
| 185 | |
---|
[939] | 186 | #if !defined __ANDROID__ |
---|
| 187 | template<typename U> |
---|
| 188 | friend std::ostream &operator<<(std::ostream &stream, Vec4<U> const &v); |
---|
| 189 | #endif |
---|
| 190 | |
---|
[294] | 191 | union { T x; T a; T i; }; |
---|
| 192 | union { T y; T b; T j; }; |
---|
| 193 | union { T z; T c; T k; }; |
---|
| 194 | union { T w; T d; T l; }; |
---|
| 195 | }; |
---|
| 196 | |
---|
[663] | 197 | typedef Vec4<float> vec4; |
---|
[866] | 198 | typedef Vec4<int> ivec4; |
---|
[294] | 199 | |
---|
[240] | 200 | #define SCALAR_GLOBAL(elems, op, U) \ |
---|
| 201 | template<typename T> \ |
---|
| 202 | static inline Vec##elems<U> operator op(U const &val, \ |
---|
| 203 | Vec##elems<T> const &that) \ |
---|
| 204 | { \ |
---|
| 205 | Vec##elems<U> ret; \ |
---|
| 206 | for (int n = 0; n < elems; n++) \ |
---|
| 207 | ret[n] = val op that[n]; \ |
---|
| 208 | return ret; \ |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | #define SCALAR_GLOBAL2(elems, op) \ |
---|
| 212 | SCALAR_GLOBAL(elems, op, int) \ |
---|
| 213 | SCALAR_GLOBAL(elems, op, float) |
---|
| 214 | |
---|
| 215 | #define GLOBALS(elems) \ |
---|
| 216 | SCALAR_GLOBAL2(elems, -) \ |
---|
| 217 | SCALAR_GLOBAL2(elems, +) \ |
---|
| 218 | SCALAR_GLOBAL2(elems, *) \ |
---|
| 219 | SCALAR_GLOBAL2(elems, /) |
---|
| 220 | |
---|
| 221 | GLOBALS(2) |
---|
| 222 | GLOBALS(3) |
---|
[294] | 223 | GLOBALS(4) |
---|
[240] | 224 | |
---|
[648] | 225 | template <typename T> struct Mat4 |
---|
[641] | 226 | { |
---|
[648] | 227 | inline Mat4() { } |
---|
[651] | 228 | inline Mat4(T val) |
---|
| 229 | { |
---|
| 230 | for (int j = 0; j < 4; j++) |
---|
| 231 | for (int i = 0; i < 4; i++) |
---|
| 232 | v[i][j] = (i == j) ? val : 0; |
---|
| 233 | } |
---|
[648] | 234 | inline Mat4(Vec4<T> v0, Vec4<T> v1, Vec4<T> v2, Vec4<T> v3) |
---|
[651] | 235 | { |
---|
| 236 | v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; |
---|
| 237 | } |
---|
[641] | 238 | |
---|
| 239 | inline Vec4<T>& operator[](int n) { return v[n]; } |
---|
| 240 | inline Vec4<T> const& operator[](int n) const { return v[n]; } |
---|
| 241 | |
---|
[648] | 242 | T det() const; |
---|
| 243 | Mat4<T> invert() const; |
---|
| 244 | |
---|
[660] | 245 | static Mat4<T> ortho(T left, T right, T bottom, T top, T near, T far); |
---|
[652] | 246 | static Mat4<T> frustum(T left, T right, T bottom, T top, T near, T far); |
---|
| 247 | static Mat4<T> perspective(T theta, T width, T height, T near, T far); |
---|
[660] | 248 | static Mat4<T> translate(T x, T y, T z); |
---|
[661] | 249 | static Mat4<T> rotate(T theta, T x, T y, T z); |
---|
[652] | 250 | |
---|
[708] | 251 | void printf() const; |
---|
| 252 | |
---|
[939] | 253 | #if !defined __ANDROID__ |
---|
[929] | 254 | template<class U> |
---|
| 255 | friend std::ostream &operator<<(std::ostream &stream, Mat4<U> const &m); |
---|
[939] | 256 | #endif |
---|
[929] | 257 | |
---|
[648] | 258 | inline Mat4<T> operator +(Mat4<T> const val) const |
---|
| 259 | { |
---|
| 260 | Mat4<T> ret; |
---|
| 261 | for (int j = 0; j < 4; j++) |
---|
| 262 | for (int i = 0; i < 4; i++) |
---|
[641] | 263 | ret[i][j] = v[i][j] + val[i][j]; |
---|
| 264 | return ret; |
---|
| 265 | } |
---|
| 266 | |
---|
[663] | 267 | inline Mat4<T> operator +=(Mat4<T> const val) |
---|
| 268 | { |
---|
| 269 | return *this = *this + val; |
---|
| 270 | } |
---|
| 271 | |
---|
[648] | 272 | inline Mat4<T> operator -(Mat4<T> const val) const |
---|
[641] | 273 | { |
---|
[648] | 274 | Mat4<T> ret; |
---|
[641] | 275 | for (int j = 0; j < 4; j++) |
---|
| 276 | for (int i = 0; i < 4; i++) |
---|
| 277 | ret[i][j] = v[i][j] - val[i][j]; |
---|
| 278 | return ret; |
---|
| 279 | } |
---|
| 280 | |
---|
[663] | 281 | inline Mat4<T> operator -=(Mat4<T> const val) |
---|
| 282 | { |
---|
| 283 | return *this = *this - val; |
---|
| 284 | } |
---|
| 285 | |
---|
[648] | 286 | inline Mat4<T> operator *(Mat4<T> const val) const |
---|
[641] | 287 | { |
---|
[648] | 288 | Mat4<T> ret; |
---|
[641] | 289 | for (int j = 0; j < 4; j++) |
---|
| 290 | for (int i = 0; i < 4; i++) |
---|
| 291 | { |
---|
| 292 | T tmp = 0; |
---|
| 293 | for (int k = 0; k < 4; k++) |
---|
| 294 | tmp += v[k][j] * val[i][k]; |
---|
| 295 | ret[i][j] = tmp; |
---|
| 296 | } |
---|
| 297 | return ret; |
---|
| 298 | } |
---|
| 299 | |
---|
[663] | 300 | inline Mat4<T> operator *=(Mat4<T> const val) |
---|
| 301 | { |
---|
| 302 | return *this = *this * val; |
---|
| 303 | } |
---|
| 304 | |
---|
[641] | 305 | inline Vec4<T> operator *(Vec4<T> const val) const |
---|
| 306 | { |
---|
| 307 | Vec4<T> ret; |
---|
| 308 | for (int j = 0; j < 4; j++) |
---|
| 309 | { |
---|
| 310 | T tmp = 0; |
---|
| 311 | for (int i = 0; i < 4; i++) |
---|
| 312 | tmp += v[i][j] * val[i]; |
---|
| 313 | ret[j] = tmp; |
---|
| 314 | } |
---|
| 315 | return ret; |
---|
| 316 | } |
---|
| 317 | |
---|
| 318 | Vec4<T> v[4]; |
---|
| 319 | }; |
---|
| 320 | |
---|
[663] | 321 | typedef Mat4<float> mat4; |
---|
[866] | 322 | typedef Mat4<int> imat4; |
---|
[663] | 323 | |
---|
[686] | 324 | } /* namespace lol */ |
---|
| 325 | |
---|
[748] | 326 | #endif // __LOL_MATRIX_H__ |
---|
[150] | 327 | |
---|