source: trunk/src/matrix.h @ 1035

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

core: disallow casting eg. a vec3 into a vec2. Use the xy() getter instead.

  • Property svn:keywords set to Id
File size: 10.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_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#define SWIZZLE2(e1, e2) \
119    inline Vec2<T> e1##e2() const \
120    { \
121        return Vec2<T>(e1, e2); \
122    }
123
124#define SWIZZLE3(e1, e2, e3) \
125    inline Vec3<T> e1##e2##e3() const \
126    { \
127        return Vec3<T>(e1, e2, e3); \
128    }
129
130#define SWIZZLE4(e1, e2, e3, e4) \
131    inline Vec4<T> e1##e2##e3##e4() const \
132    { \
133        return Vec4<T>(e1, e2, e3, e4); \
134    }
135
136#define SWIZZLE22(e1) \
137    SWIZZLE2(e1, x); SWIZZLE2(e1, y);
138#define SWIZZLE23(e1) \
139    SWIZZLE2(e1, x); SWIZZLE2(e1, y); SWIZZLE2(e1, z);
140#define SWIZZLE24(e1) \
141    SWIZZLE2(e1, x); SWIZZLE2(e1, y); SWIZZLE2(e1, z); SWIZZLE2(e1, w);
142
143#define SWIZZLE32(e1, e2) \
144    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y);
145#define SWIZZLE322(e1) \
146    SWIZZLE32(e1, x); SWIZZLE32(e1, y);
147#define SWIZZLE33(e1, e2) \
148    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y); SWIZZLE3(e1, e2, z);
149#define SWIZZLE333(e1) \
150    SWIZZLE33(e1, x); SWIZZLE33(e1, y); SWIZZLE33(e1, z);
151#define SWIZZLE34(e1, e2) \
152    SWIZZLE3(e1, e2, x); SWIZZLE3(e1, e2, y); \
153    SWIZZLE3(e1, e2, z); SWIZZLE3(e1, e2, w);
154#define SWIZZLE344(e1) \
155    SWIZZLE34(e1, x); SWIZZLE34(e1, y); \
156    SWIZZLE34(e1, z); SWIZZLE34(e1, w);
157
158#define SWIZZLE42(e1, e2, e3) \
159    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y);
160#define SWIZZLE422(e1, e2) \
161    SWIZZLE42(e1, e2, x); SWIZZLE42(e1, e2, y);
162#define SWIZZLE4222(e1) \
163    SWIZZLE422(e1, x); SWIZZLE422(e1, y);
164#define SWIZZLE43(e1, e2, e3) \
165    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y); SWIZZLE4(e1, e2, e3, z);
166#define SWIZZLE433(e1, e2) \
167    SWIZZLE43(e1, e2, x); SWIZZLE43(e1, e2, y); SWIZZLE43(e1, e2, z);
168#define SWIZZLE4333(e1) \
169    SWIZZLE433(e1, x); SWIZZLE433(e1, y); SWIZZLE433(e1, z);
170#define SWIZZLE44(e1, e2, e3) \
171    SWIZZLE4(e1, e2, e3, x); SWIZZLE4(e1, e2, e3, y); \
172    SWIZZLE4(e1, e2, e3, z); SWIZZLE4(e1, e2, e3, w);
173#define SWIZZLE444(e1, e2) \
174    SWIZZLE44(e1, e2, x); SWIZZLE44(e1, e2, y); \
175    SWIZZLE44(e1, e2, z); SWIZZLE44(e1, e2, w);
176#define SWIZZLE4444(e1) \
177    SWIZZLE444(e1, x); SWIZZLE444(e1, y); SWIZZLE444(e1, z); SWIZZLE444(e1, w);
178
179template <typename T> struct Vec2;
180template <typename T> struct Vec3;
181template <typename T> struct Vec4;
182
183/*
184 * 2-element vectors
185 */
186
187template <typename T> struct Vec2
188{
189    inline Vec2() { }
190    inline Vec2(T val) { x = y = val; }
191    inline Vec2(T _x, T _y) { x = _x; y = _y; }
192
193    OPERATORS(2)
194
195    SWIZZLE22(x); SWIZZLE22(y);
196    SWIZZLE322(x); SWIZZLE322(y);
197    SWIZZLE4222(x); SWIZZLE4222(y);
198
199#if !defined __ANDROID__
200    template<typename U>
201    friend std::ostream &operator<<(std::ostream &stream, Vec2<U> const &v);
202#endif
203
204    union { T x; T a; T i; };
205    union { T y; T b; T j; };
206};
207
208typedef Vec2<float> vec2;
209typedef Vec2<int> ivec2;
210
211/*
212 * 3-element vectors
213 */
214
215template <typename T> struct Vec3
216{
217    inline Vec3() { }
218    inline Vec3(T val) { x = y = z = val; }
219    inline Vec3(T _x, T _y, T _z) { x = _x; y = _y; z = _z; }
220    inline Vec3(Vec2<T> _xy, T _z) { x = _xy.x; y = _xy.y; z = _z; }
221    inline Vec3(T _x, Vec2<T> _yz) { x = _x; y = _yz.x; z = _yz.y; }
222
223    OPERATORS(3)
224
225    SWIZZLE23(x); SWIZZLE23(y); SWIZZLE23(z);
226    SWIZZLE333(x); SWIZZLE333(y); SWIZZLE333(z);
227    SWIZZLE4333(x); SWIZZLE4333(y); SWIZZLE4333(z);
228
229#if !defined __ANDROID__
230    template<typename U>
231    friend std::ostream &operator<<(std::ostream &stream, Vec3<U> const &v);
232#endif
233
234    union { T x; T a; T i; };
235    union { T y; T b; T j; };
236    union { T z; T c; T k; };
237};
238
239typedef Vec3<float> vec3;
240typedef Vec3<int> ivec3;
241
242/*
243 * 4-element vectors
244 */
245
246template <typename T> struct Vec4
247{
248    inline Vec4() { }
249    inline Vec4(T val) { x = y = z = w = val; }
250    inline Vec4(T _x, T _y, T _z, T _w) { x = _x; y = _y; z = _z; w = _w; }
251    inline Vec4(Vec2<T> _xy, T _z, T _w) { x = _xy.x; y = _xy.y; z = _z; w = _w; }
252    inline Vec4(T _x, Vec2<T> _yz, T _w) { x = _x; y = _yz.x; z = _yz.y; w = _w; }
253    inline Vec4(T _x, T _y, Vec2<T> _zw) { x = _x; y = _y; z = _zw.x; w = _zw.y; }
254    inline Vec4(Vec2<T> _xy, Vec2<T> _zw) { x = _xy.x; y = _xy.y; z = _zw.x; w = _zw.y; }
255    inline Vec4(Vec3<T> _xyz, T _w) { x = _xyz.x; y = _xyz.y; z = _xyz.z; w = _w; }
256    inline Vec4(T _x, Vec3<T> _yzw) { x = _x; y = _yzw.x; z = _yzw.y; w = _yzw.z; }
257
258    OPERATORS(4)
259
260    SWIZZLE24(x); SWIZZLE24(y); SWIZZLE24(z); SWIZZLE24(w);
261    SWIZZLE344(x); SWIZZLE344(y); SWIZZLE344(z); SWIZZLE344(w);
262    SWIZZLE4444(x); SWIZZLE4444(y); SWIZZLE4444(z); SWIZZLE4444(w);
263
264#if !defined __ANDROID__
265    template<typename U>
266    friend std::ostream &operator<<(std::ostream &stream, Vec4<U> const &v);
267#endif
268
269    union { T x; T a; T i; };
270    union { T y; T b; T j; };
271    union { T z; T c; T k; };
272    union { T w; T d; T l; };
273};
274
275typedef Vec4<float> vec4;
276typedef Vec4<int> ivec4;
277
278#define SCALAR_GLOBAL(elems, op, U) \
279    template<typename T> \
280    static inline Vec##elems<U> operator op(U const &val, \
281                                            Vec##elems<T> const &that) \
282    { \
283        Vec##elems<U> ret; \
284        for (int n = 0; n < elems; n++) \
285            ret[n] = val op that[n]; \
286        return ret; \
287    }
288
289#define SCALAR_GLOBAL2(elems, op) \
290    SCALAR_GLOBAL(elems, op, int) \
291    SCALAR_GLOBAL(elems, op, float)
292
293#define GLOBALS(elems) \
294    SCALAR_GLOBAL2(elems, -) \
295    SCALAR_GLOBAL2(elems, +) \
296    SCALAR_GLOBAL2(elems, *) \
297    SCALAR_GLOBAL2(elems, /)
298
299GLOBALS(2)
300GLOBALS(3)
301GLOBALS(4)
302
303/*
304 * 4×4-element matrices
305 */
306
307template <typename T> struct Mat4
308{
309    inline Mat4() { }
310    inline Mat4(T val)
311    {
312        for (int j = 0; j < 4; j++)
313            for (int i = 0; i < 4; i++)
314                v[i][j] = (i == j) ? val : 0;
315    }
316    inline Mat4(Vec4<T> v0, Vec4<T> v1, Vec4<T> v2, Vec4<T> v3)
317    {
318        v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3;
319    }
320
321    inline Vec4<T>& operator[](int n) { return v[n]; }
322    inline Vec4<T> const& operator[](int n) const { return v[n]; }
323
324    T det() const;
325    Mat4<T> invert() const;
326
327    static Mat4<T> ortho(T left, T right, T bottom, T top, T near, T far);
328    static Mat4<T> frustum(T left, T right, T bottom, T top, T near, T far);
329    static Mat4<T> perspective(T theta, T width, T height, T near, T far);
330    static Mat4<T> translate(T x, T y, T z);
331    static Mat4<T> rotate(T theta, T x, T y, T z);
332
333    void printf() const;
334
335#if !defined __ANDROID__
336    template<class U>
337    friend std::ostream &operator<<(std::ostream &stream, Mat4<U> const &m);
338#endif
339
340    inline Mat4<T> operator +(Mat4<T> const val) const
341    {
342        Mat4<T> ret;
343        for (int j = 0; j < 4; j++)
344            for (int i = 0; i < 4; i++)
345                ret[i][j] = v[i][j] + val[i][j];
346        return ret;
347    }
348
349    inline Mat4<T> operator +=(Mat4<T> const val)
350    {
351        return *this = *this + val;
352    }
353
354    inline Mat4<T> operator -(Mat4<T> const val) const
355    {
356        Mat4<T> ret;
357        for (int j = 0; j < 4; j++)
358            for (int i = 0; i < 4; i++)
359                ret[i][j] = v[i][j] - val[i][j];
360        return ret;
361    }
362
363    inline Mat4<T> operator -=(Mat4<T> const val)
364    {
365        return *this = *this - val;
366    }
367
368    inline Mat4<T> operator *(Mat4<T> const val) const
369    {
370        Mat4<T> ret;
371        for (int j = 0; j < 4; j++)
372            for (int i = 0; i < 4; i++)
373            {
374                T tmp = 0;
375                for (int k = 0; k < 4; k++)
376                    tmp += v[k][j] * val[i][k];
377                ret[i][j] = tmp;
378            }
379        return ret;
380    }
381
382    inline Mat4<T> operator *=(Mat4<T> const val)
383    {
384        return *this = *this * val;
385    }
386
387    inline Vec4<T> operator *(Vec4<T> const val) const
388    {
389        Vec4<T> ret;
390        for (int j = 0; j < 4; j++)
391        {
392            T tmp = 0;
393            for (int i = 0; i < 4; i++)
394                tmp += v[i][j] * val[i];
395            ret[j] = tmp;
396        }
397        return ret;
398    }
399
400    Vec4<T> v[4];
401};
402
403typedef Mat4<float> mat4;
404typedef Mat4<int> imat4;
405
406} /* namespace lol */
407
408#endif // __LOL_MATRIX_H__
409
Note: See TracBrowser for help on using the repository browser.