source: trunk/src/matrix.h @ 1059

Last change on this file since 1059 was 1059, checked in by sam, 8 years ago

core: add a double complex type.

  • Property svn:keywords set to Id
File size: 14.6 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_TYPES(tname, suffix) \
28    template <typename T> struct tname; \
29    typedef tname<half> f16##suffix; \
30    typedef tname<float> suffix; \
31    typedef tname<double> f64##suffix; \
32    typedef tname<int8_t> i8##suffix; \
33    typedef tname<uint8_t> u8##suffix; \
34    typedef tname<int16_t> i16##suffix; \
35    typedef tname<uint16_t> u16##suffix; \
36    typedef tname<int32_t> i##suffix; \
37    typedef tname<uint32_t> u##suffix; \
38    typedef tname<int64_t> i64##suffix; \
39    typedef tname<uint64_t> u64##suffix;
40
41VECTOR_TYPES(Vec2, vec2)
42VECTOR_TYPES(Cmplx, cmplx)
43VECTOR_TYPES(Vec3, vec3)
44VECTOR_TYPES(Vec4, vec4)
45VECTOR_TYPES(Quat, quat)
46VECTOR_TYPES(Mat4, mat4)
47
48#define VECTOR_OP(op) \
49    inline type_t operator op(type_t const &val) const \
50    { \
51        type_t ret; \
52        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
53            ret[n] = (*this)[n] op val[n]; \
54        return ret; \
55    } \
56    \
57    inline type_t operator op##=(type_t const &val) \
58    { \
59        return *this = (*this) op val; \
60    }
61
62#define BOOL_OP(op, op2, ret) \
63    inline bool operator op(type_t const &val) const \
64    { \
65        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
66            if (!((*this)[n] op2 val[n])) \
67                return !ret; \
68        return ret; \
69    }
70
71#define SCALAR_OP(op) \
72    inline type_t operator op(T const &val) const \
73    { \
74        type_t ret; \
75        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
76            ret[n] = (*this)[n] op val; \
77        return ret; \
78    } \
79    \
80    inline type_t operator op##=(T const &val) \
81    { \
82        return *this = (*this) op val; \
83    }
84
85#define LINEAR_OPS() \
86    inline T& operator[](int n) { return *(&x + n); } \
87    inline T const& operator[](int n) const { return *(&x + n); } \
88    \
89    VECTOR_OP(-) \
90    VECTOR_OP(+) \
91    \
92    BOOL_OP(==, ==, true) \
93    BOOL_OP(!=, ==, false) \
94    \
95    SCALAR_OP(*) \
96    SCALAR_OP(/) \
97    \
98    inline type_t operator -() const \
99    { \
100        type_t ret; \
101        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
102            ret[n] = -(*this)[n]; \
103        return ret; \
104    } \
105    \
106    inline T sqlen() const \
107    { \
108        T acc = 0; \
109        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
110            acc += (*this)[n] * (*this)[n]; \
111        return acc; \
112    } \
113    \
114    inline double len() const \
115    { \
116        using namespace std; \
117        return sqrt((double)sqlen()); \
118    } \
119    \
120    void printf() const;
121
122#define COMPLEX_OPS() \
123    inline type_t operator *(type_t const &val) const \
124    { \
125        return type_t(x * val.x - y * val.y, x * val.y + y * val.x); \
126    } \
127    \
128    inline type_t operator *=(type_t const &val) \
129    { \
130        return *this = (*this) * val; \
131    } \
132    \
133    inline type_t operator ~() const \
134    { \
135        return type_t(x, -y); \
136    } \
137    \
138    inline T norm() const { return len(); }
139
140#define QUATERNION_OPS() \
141    inline type_t operator *(type_t const &val) const \
142    { \
143        type_t ret; \
144        Vec3<T> v1(x, y, z); \
145        Vec3<T> v2(val.x, val.y, val.z); \
146        Vec3<T> v3 = cross(v1, v2) + w * v2 + val.w * v1; \
147        ret.x = v3.x; \
148        ret.y = v3.y; \
149        ret.z = v3.z; \
150        ret.w = w * val.w - dot(v1, v2); \
151        return ret; \
152    } \
153    \
154    inline type_t operator *=(type_t const &val) \
155    { \
156        return *this = (*this) * val; \
157    } \
158    \
159    inline type_t operator ~() const \
160    { \
161        type_t ret; \
162        for (int n = 0; n < 3; n++) \
163            ret[n] = -(*this)[n]; \
164        ret[3] = (*this)[3]; \
165        return ret; \
166    } \
167    \
168    inline T norm() const { return sqlen(); }
169
170#define OTHER_OPS(tname) \
171    VECTOR_OP(*) \
172    VECTOR_OP(/) \
173    \
174    BOOL_OP(<=, <=, true) \
175    BOOL_OP(>=, >=, true) \
176    BOOL_OP(<, <, true) \
177    BOOL_OP(>, >, true) \
178    \
179    template<typename U> \
180    inline operator tname<U>() const \
181    { \
182        tname<U> ret; \
183        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
184            ret[n] = static_cast<U>((*this)[n]); \
185        return ret; \
186    } \
187    \
188    template<typename U> \
189    friend U dot(tname<U>, tname<U>);
190
191#define SWIZZLE2(e1, e2) \
192    inline Vec2<T> e1##e2() const \
193    { \
194        return Vec2<T>(this->e1, this->e2); \
195    }
196
197#define SWIZZLE3(e1, e2, e3) \
198    inline Vec3<T> e1##e2##e3() const \
199    { \
200        return Vec3<T>(this->e1, this->e2, this->e3); \
201    }
202
203#define SWIZZLE4(e1, e2, e3, e4) \
204    inline Vec4<T> e1##e2##e3##e4() const \
205    { \
206        return Vec4<T>(this->e1, this->e2, this->e3, this->e4); \
207    }
208
209#define SWIZZLE22(e1) \
210    SWIZZLE2(e1, x); SWIZZLE2(e1, y);
211#define SWIZZLE23(e1) \
212    SWIZZLE2(e1, x); SWIZZLE2(e1, y); SWIZZLE2(e1, z);
213#define SWIZZLE24(e1) \
214    SWIZZLE2(e1, x); SWIZZLE2(e1, y); SWIZZLE2(e1, z); SWIZZLE2(e1, w);
215
216#define SWIZZLE32(e1, e2) \
217    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y);
218#define SWIZZLE322(e1) \
219    SWIZZLE32(e1, x); SWIZZLE32(e1, y);
220#define SWIZZLE33(e1, e2) \
221    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y); SWIZZLE3(e1, e2, z);
222#define SWIZZLE333(e1) \
223    SWIZZLE33(e1, x); SWIZZLE33(e1, y); SWIZZLE33(e1, z);
224#define SWIZZLE34(e1, e2) \
225    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y); \
226    SWIZZLE3(e1, e2, z); SWIZZLE3(e1, e2, w);
227#define SWIZZLE344(e1) \
228    SWIZZLE34(e1, x); SWIZZLE34(e1, y); \
229    SWIZZLE34(e1, z); SWIZZLE34(e1, w);
230
231#define SWIZZLE42(e1, e2, e3) \
232    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y);
233#define SWIZZLE422(e1, e2) \
234    SWIZZLE42(e1, e2, x); SWIZZLE42(e1, e2, y);
235#define SWIZZLE4222(e1) \
236    SWIZZLE422(e1, x); SWIZZLE422(e1, y);
237#define SWIZZLE43(e1, e2, e3) \
238    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y); SWIZZLE4(e1, e2, e3, z);
239#define SWIZZLE433(e1, e2) \
240    SWIZZLE43(e1, e2, x); SWIZZLE43(e1, e2, y); SWIZZLE43(e1, e2, z);
241#define SWIZZLE4333(e1) \
242    SWIZZLE433(e1, x); SWIZZLE433(e1, y); SWIZZLE433(e1, z);
243#define SWIZZLE44(e1, e2, e3) \
244    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y); \
245    SWIZZLE4(e1, e2, e3, z); SWIZZLE4(e1, e2, e3, w);
246#define SWIZZLE444(e1, e2) \
247    SWIZZLE44(e1, e2, x); SWIZZLE44(e1, e2, y); \
248    SWIZZLE44(e1, e2, z); SWIZZLE44(e1, e2, w);
249#define SWIZZLE4444(e1) \
250    SWIZZLE444(e1, x); SWIZZLE444(e1, y); SWIZZLE444(e1, z); SWIZZLE444(e1, w);
251
252/*
253 * 2-element vectors
254 */
255
256template <typename T> struct Vec2
257{
258    typedef Vec2<T> type_t;
259
260    inline Vec2() { }
261    explicit inline Vec2(T val) { x = y = val; }
262    inline Vec2(T _x, T _y) { x = _x; y = _y; }
263
264    LINEAR_OPS()
265    OTHER_OPS(Vec2)
266
267    SWIZZLE22(x); SWIZZLE22(y);
268    SWIZZLE322(x); SWIZZLE322(y);
269    SWIZZLE4222(x); SWIZZLE4222(y);
270
271#if !defined __ANDROID__
272    template<typename U>
273    friend std::ostream &operator<<(std::ostream &stream, Vec2<U> const &v);
274#endif
275
276    union { T x; T a; T i; };
277    union { T y; T b; T j; };
278};
279
280/*
281 * 2-element complexes
282 */
283
284template <typename T> struct Cmplx
285{
286    typedef Cmplx<T> type_t;
287
288    inline Cmplx() { }
289    inline Cmplx(T val) : x(val), y(0) { }
290    inline Cmplx(T _x, T _y) : x(_x), y(_y) { }
291
292    LINEAR_OPS()
293    COMPLEX_OPS()
294
295#if !defined __ANDROID__
296    template<typename U>
297    friend std::ostream &operator<<(std::ostream &stream, Cmplx<U> const &v);
298#endif
299
300    T x, y;
301};
302
303template<typename T>
304static inline Cmplx<T> re(Cmplx<T> const &val)
305{
306    return ~val / val.sqlen();
307}
308
309template<typename T>
310static inline Cmplx<T> operator /(T x, Cmplx<T> const &y)
311{
312    return x * re(y);
313}
314
315template<typename T>
316static inline Cmplx<T> operator /(Cmplx<T> x, Cmplx<T> const &y)
317{
318    return x * re(y);
319}
320
321/*
322 * 3-element vectors
323 */
324
325template <typename T> struct Vec3
326{
327    typedef Vec3<T> type_t;
328
329    inline Vec3() { }
330    explicit inline Vec3(T val) { x = y = z = val; }
331    inline Vec3(T _x, T _y, T _z) { x = _x; y = _y; z = _z; }
332    inline Vec3(Vec2<T> _xy, T _z) { x = _xy.x; y = _xy.y; z = _z; }
333    inline Vec3(T _x, Vec2<T> _yz) { x = _x; y = _yz.x; z = _yz.y; }
334
335    LINEAR_OPS()
336    OTHER_OPS(Vec3)
337
338    SWIZZLE23(x); SWIZZLE23(y); SWIZZLE23(z);
339    SWIZZLE333(x); SWIZZLE333(y); SWIZZLE333(z);
340    SWIZZLE4333(x); SWIZZLE4333(y); SWIZZLE4333(z);
341
342    template<typename U>
343    friend Vec3<U> cross(Vec3<U>, Vec3<U>);
344
345#if !defined __ANDROID__
346    template<typename U>
347    friend std::ostream &operator<<(std::ostream &stream, Vec3<U> const &v);
348#endif
349
350    union { T x; T a; T i; };
351    union { T y; T b; T j; };
352    union { T z; T c; T k; };
353};
354
355/*
356 * 4-element vectors
357 */
358
359template <typename T> struct Vec4
360{
361    typedef Vec4<T> type_t;
362
363    inline Vec4() { }
364    explicit inline Vec4(T val) : x(val), y(val), z(val), w(val) { }
365    inline Vec4(T _x, T _y, T _z, T _w) : x(_x), y(_y), z(_z), w(_w) { }
366    inline Vec4(Vec2<T> _xy, T _z, T _w) : x(_xy.x), y(_xy.y), z(_z), w(_w) { }
367    inline Vec4(T _x, Vec2<T> _yz, T _w) : x(_x), y(_yz.x), z(_yz.y), w(_w) { }
368    inline Vec4(T _x, T _y, Vec2<T> _zw) : x(_x), y(_y), z(_zw.x), w(_zw.y) { }
369    inline Vec4(Vec2<T> _xy, Vec2<T> _zw) : x(_xy.x), y(_xy.y), z(_zw.x), w(_zw.y) { }
370    inline Vec4(Vec3<T> _xyz, T _w) : x(_xyz.x), y(_xyz.y), z(_xyz.z), w(_w) { }
371    inline Vec4(T _x, Vec3<T> _yzw) : x(_x), y(_yzw.x), z(_yzw.y), w(_yzw.z) { }
372
373    LINEAR_OPS()
374    OTHER_OPS(Vec4)
375
376    SWIZZLE24(x); SWIZZLE24(y); SWIZZLE24(z); SWIZZLE24(w);
377    SWIZZLE344(x); SWIZZLE344(y); SWIZZLE344(z); SWIZZLE344(w);
378    SWIZZLE4444(x); SWIZZLE4444(y); SWIZZLE4444(z); SWIZZLE4444(w);
379
380#if !defined __ANDROID__
381    template<typename U>
382    friend std::ostream &operator<<(std::ostream &stream, Vec4<U> const &v);
383#endif
384
385    union { T x; T a; T i; };
386    union { T y; T b; T j; };
387    union { T z; T c; T k; };
388    union { T w; T d; T l; };
389};
390
391/*
392 * 4-element quaternions
393 */
394
395template <typename T> struct Quat
396{
397    typedef Quat<T> type_t;
398
399    inline Quat() { }
400    inline Quat(T val) : x(0), y(0), z(0), w(val) { }
401    inline Quat(T _x, T _y, T _z, T _w) : x(_x), y(_y), z(_z), w(_w) { }
402
403    Quat(Mat4<T> const &m);
404
405    LINEAR_OPS()
406    QUATERNION_OPS()
407
408#if !defined __ANDROID__
409    template<typename U>
410    friend std::ostream &operator<<(std::ostream &stream, Quat<U> const &v);
411#endif
412
413    T x, y, z, w;
414};
415
416template<typename T>
417static inline Quat<T> re(Quat<T> const &val)
418{
419    return ~val / val.norm();
420}
421
422template<typename T>
423static inline Quat<T> operator /(T x, Quat<T> const &y)
424{
425    return x * re(y);
426}
427
428template<typename T>
429static inline Quat<T> operator /(Quat<T> x, Quat<T> const &y)
430{
431    return x * re(y);
432}
433
434/*
435 * Common operators for all vector types, including quaternions
436 */
437
438#define SCALAR_GLOBAL(tname, op, U) \
439    template<typename T> \
440    static inline tname<U> operator op(U const &val, tname<T> const &that) \
441    { \
442        tname<U> ret; \
443        for (size_t n = 0; n < sizeof(that) / sizeof(that[0]); n++) \
444            ret[n] = val op that[n]; \
445        return ret; \
446    }
447
448#define SCALAR_GLOBAL2(tname, op) \
449    SCALAR_GLOBAL(tname, op, int) \
450    SCALAR_GLOBAL(tname, op, float) \
451    SCALAR_GLOBAL(tname, op, double)
452
453#define GLOBALS(tname) \
454    SCALAR_GLOBAL2(tname, *) \
455    \
456    template<typename T> \
457    static inline tname<T> normalize(tname<T> const &val) \
458    { \
459        T norm = val.len(); \
460        return norm ? val / norm : val * 0; \
461    }
462
463GLOBALS(Vec2)
464GLOBALS(Cmplx)
465GLOBALS(Vec3)
466GLOBALS(Vec4)
467GLOBALS(Quat)
468
469/*
470 * 4×4-element matrices
471 */
472
473template <typename T> struct Mat4
474{
475    typedef Mat4<T> type_t;
476
477    inline Mat4() { }
478    explicit inline Mat4(T val)
479    {
480        for (int j = 0; j < 4; j++)
481            for (int i = 0; i < 4; i++)
482                v[i][j] = (i == j) ? val : 0;
483    }
484    inline Mat4(Vec4<T> v0, Vec4<T> v1, Vec4<T> v2, Vec4<T> v3)
485    {
486        v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3;
487    }
488
489    inline Vec4<T>& operator[](int n) { return v[n]; }
490    inline Vec4<T> const& operator[](int n) const { return v[n]; }
491
492    T det() const;
493    Mat4<T> invert() const;
494
495    /* Helpers for transformation matrices */
496    static Mat4<T> translate(T x, T y, T z);
497    static Mat4<T> translate(Vec3<T> v);
498    static Mat4<T> rotate(T angle, T x, T y, T z);
499    static Mat4<T> rotate(T angle, Vec3<T> v);
500    static Mat4<T> rotate(Quat<T> q);
501
502    static inline Mat4<T> translate(Mat4<T> mat, Vec3<T> v)
503    {
504        return translate(v) * mat;
505    }
506
507    static inline Mat4<T> rotate(Mat4<T> mat, T angle, Vec3<T> v)
508    {
509        return rotate(angle, v) * mat;
510    }
511
512    /* Helpers for view matrices */
513    static Mat4<T> lookat(Vec3<T> eye, Vec3<T> center, Vec3<T> up);
514
515    /* Helpers for projection matrices */
516    static Mat4<T> ortho(T left, T right, T bottom, T top, T near, T far);
517    static Mat4<T> frustum(T left, T right, T bottom, T top, T near, T far);
518    static Mat4<T> perspective(T fov_y, T width, T height, T near, T far);
519
520    void printf() const;
521
522#if !defined __ANDROID__
523    template<class U>
524    friend std::ostream &operator<<(std::ostream &stream, Mat4<U> const &m);
525#endif
526
527    inline Mat4<T> operator +(Mat4<T> const val) const
528    {
529        Mat4<T> ret;
530        for (int j = 0; j < 4; j++)
531            for (int i = 0; i < 4; i++)
532                ret[i][j] = v[i][j] + val[i][j];
533        return ret;
534    }
535
536    inline Mat4<T> operator +=(Mat4<T> const val)
537    {
538        return *this = *this + val;
539    }
540
541    inline Mat4<T> operator -(Mat4<T> const val) const
542    {
543        Mat4<T> ret;
544        for (int j = 0; j < 4; j++)
545            for (int i = 0; i < 4; i++)
546                ret[i][j] = v[i][j] - val[i][j];
547        return ret;
548    }
549
550    inline Mat4<T> operator -=(Mat4<T> const val)
551    {
552        return *this = *this - val;
553    }
554
555    inline Mat4<T> operator *(Mat4<T> const val) const
556    {
557        Mat4<T> ret;
558        for (int j = 0; j < 4; j++)
559            for (int i = 0; i < 4; i++)
560            {
561                T tmp = 0;
562                for (int k = 0; k < 4; k++)
563                    tmp += v[k][j] * val[i][k];
564                ret[i][j] = tmp;
565            }
566        return ret;
567    }
568
569    inline Mat4<T> operator *=(Mat4<T> const val)
570    {
571        return *this = *this * val;
572    }
573
574    inline Vec4<T> operator *(Vec4<T> const val) const
575    {
576        Vec4<T> ret;
577        for (int j = 0; j < 4; j++)
578        {
579            T tmp = 0;
580            for (int i = 0; i < 4; i++)
581                tmp += v[i][j] * val[i];
582            ret[j] = tmp;
583        }
584        return ret;
585    }
586
587    Vec4<T> v[4];
588};
589
590} /* namespace lol */
591
592#endif // __LOL_MATRIX_H__
593
Note: See TracBrowser for help on using the repository browser.