source: trunk/src/matrix.h @ 1046

Last change on this file since 1046 was 1046, checked in by sam, 12 years ago

core: split vector operations into linear and non-linear so that we can
reuse the linear operations in quaternions. Also mark some constructors
explicit to better spot coding errors.

  • Property svn:keywords set to Id
File size: 12.5 KB
Line 
1//
2// Lol Engine
3//
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//
10
11//
12// The Matrix classes
13// ------------------
14//
15
16#if !defined __LOL_MATRIX_H__
17#define __LOL_MATRIX_H__
18
19#include <cmath>
20#if !defined __ANDROID__
21#   include <iostream>
22#endif
23
24namespace lol
25{
26
27#define VECTOR_OP(elems, op) \
28    template<typename U> \
29    inline Vec##elems<T> operator op(Vec##elems<U> const &val) const \
30    { \
31        Vec##elems<T> ret; \
32        for (int n = 0; n < elems; n++) \
33            ret[n] = (*this)[n] op val[n]; \
34        return ret; \
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; \
41    }
42
43#define BOOL_OP(elems, op, op2, ret) \
44    inline bool operator op(Vec##elems<T> const &val) const \
45    { \
46        for (int n = 0; n < elems; n++) \
47            if (!((*this)[n] op2 val[n])) \
48                return !ret; \
49        return ret; \
50    }
51
52#define SCALAR_OP(elems, op) \
53    inline Vec##elems<T> operator op(T const &val) const \
54    { \
55        Vec##elems<T> ret; \
56        for (int n = 0; n < elems; n++) \
57            ret[n] = (*this)[n] op val; \
58        return ret; \
59    } \
60    \
61    inline Vec##elems<T> operator op##=(T const &val) \
62    { \
63        return *this = (*this) op val; \
64    }
65
66#define LINEAR_OPS(elems) \
67    inline T& operator[](int n) { return *(&x + n); } \
68    inline T const& operator[](int n) const { return *(&x + n); } \
69    \
70    VECTOR_OP(elems, -) \
71    VECTOR_OP(elems, +) \
72    \
73    BOOL_OP(elems, ==, ==, true) \
74    BOOL_OP(elems, !=, ==, false) \
75    \
76    SCALAR_OP(elems, *) \
77    SCALAR_OP(elems, /) \
78    \
79    inline Vec##elems<T> operator -() const \
80    { \
81        Vec##elems<T> ret; \
82        for (int n = 0; n < elems; n++) \
83            ret[n] = -(*this)[n]; \
84        return ret; \
85    } \
86    \
87    inline T sqlen() const \
88    { \
89        T acc = 0; \
90        for (int n = 0; n < elems; n++) \
91            acc += (*this)[n] * (*this)[n]; \
92        return acc; \
93    } \
94    \
95    inline float len() const \
96    { \
97        using namespace std; \
98        return sqrtf((float)sqlen()); \
99    } \
100    \
101    template<typename U> \
102    friend Vec##elems<U> normalize(Vec##elems<U>); \
103    \
104    void printf() const;
105
106#define OTHER_OPS(elems) \
107    VECTOR_OP(elems, *) \
108    VECTOR_OP(elems, /) \
109    \
110    BOOL_OP(elems, <=, <=, true) \
111    BOOL_OP(elems, >=, >=, true) \
112    BOOL_OP(elems, <, <, true) \
113    BOOL_OP(elems, >, >, true) \
114    \
115    template<typename U> \
116    inline operator Vec##elems<U>() const \
117    { \
118        Vec##elems<U> ret; \
119        for (int n = 0; n < elems; n++) \
120            ret[n] = static_cast<U>((*this)[n]); \
121        return ret; \
122    } \
123    \
124    template<typename U> \
125    friend U dot(Vec##elems<U>, Vec##elems<U>);
126
127#define SWIZZLE2(e1, e2) \
128    inline Vec2<T> e1##e2() const \
129    { \
130        return Vec2<T>(this->e1, this->e2); \
131    }
132
133#define SWIZZLE3(e1, e2, e3) \
134    inline Vec3<T> e1##e2##e3() const \
135    { \
136        return Vec3<T>(this->e1, this->e2, this->e3); \
137    }
138
139#define SWIZZLE4(e1, e2, e3, e4) \
140    inline Vec4<T> e1##e2##e3##e4() const \
141    { \
142        return Vec4<T>(this->e1, this->e2, this->e3, this->e4); \
143    }
144
145#define SWIZZLE22(e1) \
146    SWIZZLE2(e1, x); SWIZZLE2(e1, y);
147#define SWIZZLE23(e1) \
148    SWIZZLE2(e1, x); SWIZZLE2(e1, y); SWIZZLE2(e1, z);
149#define SWIZZLE24(e1) \
150    SWIZZLE2(e1, x); SWIZZLE2(e1, y); SWIZZLE2(e1, z); SWIZZLE2(e1, w);
151
152#define SWIZZLE32(e1, e2) \
153    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y);
154#define SWIZZLE322(e1) \
155    SWIZZLE32(e1, x); SWIZZLE32(e1, y);
156#define SWIZZLE33(e1, e2) \
157    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y); SWIZZLE3(e1, e2, z);
158#define SWIZZLE333(e1) \
159    SWIZZLE33(e1, x); SWIZZLE33(e1, y); SWIZZLE33(e1, z);
160#define SWIZZLE34(e1, e2) \
161    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y); \
162    SWIZZLE3(e1, e2, z); SWIZZLE3(e1, e2, w);
163#define SWIZZLE344(e1) \
164    SWIZZLE34(e1, x); SWIZZLE34(e1, y); \
165    SWIZZLE34(e1, z); SWIZZLE34(e1, w);
166
167#define SWIZZLE42(e1, e2, e3) \
168    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y);
169#define SWIZZLE422(e1, e2) \
170    SWIZZLE42(e1, e2, x); SWIZZLE42(e1, e2, y);
171#define SWIZZLE4222(e1) \
172    SWIZZLE422(e1, x); SWIZZLE422(e1, y);
173#define SWIZZLE43(e1, e2, e3) \
174    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y); SWIZZLE4(e1, e2, e3, z);
175#define SWIZZLE433(e1, e2) \
176    SWIZZLE43(e1, e2, x); SWIZZLE43(e1, e2, y); SWIZZLE43(e1, e2, z);
177#define SWIZZLE4333(e1) \
178    SWIZZLE433(e1, x); SWIZZLE433(e1, y); SWIZZLE433(e1, z);
179#define SWIZZLE44(e1, e2, e3) \
180    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y); \
181    SWIZZLE4(e1, e2, e3, z); SWIZZLE4(e1, e2, e3, w);
182#define SWIZZLE444(e1, e2) \
183    SWIZZLE44(e1, e2, x); SWIZZLE44(e1, e2, y); \
184    SWIZZLE44(e1, e2, z); SWIZZLE44(e1, e2, w);
185#define SWIZZLE4444(e1) \
186    SWIZZLE444(e1, x); SWIZZLE444(e1, y); SWIZZLE444(e1, z); SWIZZLE444(e1, w);
187
188template <typename T> struct Vec2;
189template <typename T> struct Vec3;
190template <typename T> struct Vec4;
191
192/*
193 * 2-element vectors
194 */
195
196template <typename T> struct Vec2
197{
198    inline Vec2() { }
199    explicit inline Vec2(T val) { x = y = val; }
200    inline Vec2(T _x, T _y) { x = _x; y = _y; }
201
202    LINEAR_OPS(2)
203    OTHER_OPS(2)
204
205    SWIZZLE22(x); SWIZZLE22(y);
206    SWIZZLE322(x); SWIZZLE322(y);
207    SWIZZLE4222(x); SWIZZLE4222(y);
208
209#if !defined __ANDROID__
210    template<typename U>
211    friend std::ostream &operator<<(std::ostream &stream, Vec2<U> const &v);
212#endif
213
214    union { T x; T a; T i; };
215    union { T y; T b; T j; };
216};
217
218typedef Vec2<half> f16vec2;
219typedef Vec2<float> vec2;
220typedef Vec2<int8_t> i8vec2;
221typedef Vec2<uint8_t> u8vec2;
222typedef Vec2<int16_t> i16vec2;
223typedef Vec2<uint16_t> u16vec2;
224typedef Vec2<int32_t> ivec2;
225typedef Vec2<uint32_t> uvec2;
226typedef Vec2<int64_t> i64vec2;
227typedef Vec2<uint64_t> u64vec2;
228
229/*
230 * 3-element vectors
231 */
232
233template <typename T> struct Vec3
234{
235    inline Vec3() { }
236    explicit inline Vec3(T val) { x = y = z = val; }
237    inline Vec3(T _x, T _y, T _z) { x = _x; y = _y; z = _z; }
238    inline Vec3(Vec2<T> _xy, T _z) { x = _xy.x; y = _xy.y; z = _z; }
239    inline Vec3(T _x, Vec2<T> _yz) { x = _x; y = _yz.x; z = _yz.y; }
240
241    LINEAR_OPS(3)
242    OTHER_OPS(3)
243
244    SWIZZLE23(x); SWIZZLE23(y); SWIZZLE23(z);
245    SWIZZLE333(x); SWIZZLE333(y); SWIZZLE333(z);
246    SWIZZLE4333(x); SWIZZLE4333(y); SWIZZLE4333(z);
247
248    template<typename U>
249    friend Vec3<U> cross(Vec3<U>, Vec3<U>);
250
251#if !defined __ANDROID__
252    template<typename U>
253    friend std::ostream &operator<<(std::ostream &stream, Vec3<U> const &v);
254#endif
255
256    union { T x; T a; T i; };
257    union { T y; T b; T j; };
258    union { T z; T c; T k; };
259};
260
261typedef Vec3<half> f16vec3;
262typedef Vec3<float> vec3;
263typedef Vec3<int8_t> i8vec3;
264typedef Vec3<uint8_t> u8vec3;
265typedef Vec3<int16_t> i16vec3;
266typedef Vec3<uint16_t> u16vec3;
267typedef Vec3<int32_t> ivec3;
268typedef Vec3<uint32_t> uvec3;
269typedef Vec3<int64_t> i64vec3;
270typedef Vec3<uint64_t> u64vec3;
271
272/*
273 * 4-element vectors
274 */
275
276template <typename T> struct Vec4
277{
278    inline Vec4() { }
279    explicit inline Vec4(T val) : x(val), y(val), z(val), w(val) { }
280    inline Vec4(T _x, T _y, T _z, T _w) : x(_x), y(_y), z(_z), w(_w) { }
281    inline Vec4(Vec2<T> _xy, T _z, T _w) : x(_xy.x), y(_xy.y), z(_z), w(_w) { }
282    inline Vec4(T _x, Vec2<T> _yz, T _w) : x(_x), y(_yz.x), z(_yz.y), w(_w) { }
283    inline Vec4(T _x, T _y, Vec2<T> _zw) : x(_x), y(_y), z(_zw.x), w(_zw.y) { }
284    inline Vec4(Vec2<T> _xy, Vec2<T> _zw) : x(_xy.x), y(_xy.y), z(_zw.x), w(_zw.y) { }
285    inline Vec4(Vec3<T> _xyz, T _w) : x(_xyz.x), y(_xyz.y), z(_xyz.z), w(_w) { }
286    inline Vec4(T _x, Vec3<T> _yzw) : x(_x), y(_yzw.x), z(_yzw.y), w(_yzw.z) { }
287
288    LINEAR_OPS(4)
289    OTHER_OPS(4)
290
291    SWIZZLE24(x); SWIZZLE24(y); SWIZZLE24(z); SWIZZLE24(w);
292    SWIZZLE344(x); SWIZZLE344(y); SWIZZLE344(z); SWIZZLE344(w);
293    SWIZZLE4444(x); SWIZZLE4444(y); SWIZZLE4444(z); SWIZZLE4444(w);
294
295#if !defined __ANDROID__
296    template<typename U>
297    friend std::ostream &operator<<(std::ostream &stream, Vec4<U> const &v);
298#endif
299
300    union { T x; T a; T i; };
301    union { T y; T b; T j; };
302    union { T z; T c; T k; };
303    union { T w; T d; T l; };
304};
305
306typedef Vec4<half> f16vec4;
307typedef Vec4<float> vec4;
308typedef Vec4<int8_t> i8vec4;
309typedef Vec4<uint8_t> u8vec4;
310typedef Vec4<int16_t> i16vec4;
311typedef Vec4<uint16_t> u16vec4;
312typedef Vec4<int32_t> ivec4;
313typedef Vec4<uint32_t> uvec4;
314typedef Vec4<int64_t> i64vec4;
315typedef Vec4<uint64_t> u64vec4;
316
317#define SCALAR_GLOBAL(elems, op, U) \
318    template<typename T> \
319    static inline Vec##elems<U> operator op(U const &val, \
320                                            Vec##elems<T> const &that) \
321    { \
322        Vec##elems<U> ret; \
323        for (int n = 0; n < elems; n++) \
324            ret[n] = val op that[n]; \
325        return ret; \
326    }
327
328#define SCALAR_GLOBAL2(elems, op) \
329    SCALAR_GLOBAL(elems, op, int) \
330    SCALAR_GLOBAL(elems, op, float)
331
332#define GLOBALS(elems) \
333    SCALAR_GLOBAL2(elems, -) \
334    SCALAR_GLOBAL2(elems, +) \
335    SCALAR_GLOBAL2(elems, *) \
336    SCALAR_GLOBAL2(elems, /)
337
338GLOBALS(2)
339GLOBALS(3)
340GLOBALS(4)
341
342/*
343 * 4×4-element matrices
344 */
345
346template <typename T> struct Mat4
347{
348    inline Mat4() { }
349    explicit inline Mat4(T val)
350    {
351        for (int j = 0; j < 4; j++)
352            for (int i = 0; i < 4; i++)
353                v[i][j] = (i == j) ? val : 0;
354    }
355    inline Mat4(Vec4<T> v0, Vec4<T> v1, Vec4<T> v2, Vec4<T> v3)
356    {
357        v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3;
358    }
359
360    inline Vec4<T>& operator[](int n) { return v[n]; }
361    inline Vec4<T> const& operator[](int n) const { return v[n]; }
362
363    T det() const;
364    Mat4<T> invert() const;
365
366    /* Helpers for transformation matrices */
367    static Mat4<T> translate(T x, T y, T z);
368    static Mat4<T> translate(Vec3<T> v);
369    static Mat4<T> rotate(T angle, T x, T y, T z);
370    static Mat4<T> rotate(T angle, Vec3<T> v);
371
372    static inline Mat4<T> translate(Mat4<T> mat, Vec3<T> v)
373    {
374        return translate(v) * mat;
375    }
376
377    static inline Mat4<T> rotate(Mat4<T> mat, T angle, Vec3<T> v)
378    {
379        return rotate(angle, v) * mat;
380    }
381
382    /* Helpers for view matrices */
383    static Mat4<T> lookat(Vec3<T> eye, Vec3<T> center, Vec3<T> up);
384
385    /* Helpers for projection matrices */
386    static Mat4<T> ortho(T left, T right, T bottom, T top, T near, T far);
387    static Mat4<T> frustum(T left, T right, T bottom, T top, T near, T far);
388    static Mat4<T> perspective(T fov_y, T width, T height, T near, T far);
389
390    void printf() const;
391
392#if !defined __ANDROID__
393    template<class U>
394    friend std::ostream &operator<<(std::ostream &stream, Mat4<U> const &m);
395#endif
396
397    inline Mat4<T> operator +(Mat4<T> const val) const
398    {
399        Mat4<T> ret;
400        for (int j = 0; j < 4; j++)
401            for (int i = 0; i < 4; i++)
402                ret[i][j] = v[i][j] + val[i][j];
403        return ret;
404    }
405
406    inline Mat4<T> operator +=(Mat4<T> const val)
407    {
408        return *this = *this + val;
409    }
410
411    inline Mat4<T> operator -(Mat4<T> const val) const
412    {
413        Mat4<T> ret;
414        for (int j = 0; j < 4; j++)
415            for (int i = 0; i < 4; i++)
416                ret[i][j] = v[i][j] - val[i][j];
417        return ret;
418    }
419
420    inline Mat4<T> operator -=(Mat4<T> const val)
421    {
422        return *this = *this - val;
423    }
424
425    inline Mat4<T> operator *(Mat4<T> const val) const
426    {
427        Mat4<T> ret;
428        for (int j = 0; j < 4; j++)
429            for (int i = 0; i < 4; i++)
430            {
431                T tmp = 0;
432                for (int k = 0; k < 4; k++)
433                    tmp += v[k][j] * val[i][k];
434                ret[i][j] = tmp;
435            }
436        return ret;
437    }
438
439    inline Mat4<T> operator *=(Mat4<T> const val)
440    {
441        return *this = *this * val;
442    }
443
444    inline Vec4<T> operator *(Vec4<T> const val) const
445    {
446        Vec4<T> ret;
447        for (int j = 0; j < 4; j++)
448        {
449            T tmp = 0;
450            for (int i = 0; i < 4; i++)
451                tmp += v[i][j] * val[i];
452            ret[j] = tmp;
453        }
454        return ret;
455    }
456
457    Vec4<T> v[4];
458};
459
460typedef Mat4<half> f16mat4;
461typedef Mat4<float> mat4;
462typedef Mat4<int8_t> i8mat4;
463typedef Mat4<uint8_t> u8mat4;
464typedef Mat4<int16_t> i16mat4;
465typedef Mat4<uint16_t> u16mat4;
466typedef Mat4<int32_t> imat4;
467typedef Mat4<uint32_t> umat4;
468typedef Mat4<int64_t> i64mat4;
469typedef Mat4<uint64_t> u64mat4;
470
471} /* namespace lol */
472
473#endif // __LOL_MATRIX_H__
474
Note: See TracBrowser for help on using the repository browser.