source: trunk/src/matrix.h @ 1044

Last change on this file since 1044 was 1044, checked in by gary, 12 years ago

core: fix bugs in mat4::lookat() and mat4::perspective(), and ensure these
function use degrees rather than radians.

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