diff --git a/src/Makefile.am b/src/Makefile.am index 6a567616..585ba228 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ noinst_LIBRARIES = liblol.a liblol_a_SOURCES = \ - core.h matrix.cpp real.cpp tiler.cpp tiler.h dict.cpp dict.h \ + core.h vector.cpp real.cpp tiler.cpp tiler.h dict.cpp dict.h \ audio.cpp audio.h scene.cpp scene.h font.cpp font.h layer.cpp layer.h \ map.cpp map.h entity.cpp entity.h ticker.cpp ticker.h lolgl.h \ tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h log.cpp log.h \ @@ -13,7 +13,7 @@ liblol_a_SOURCES = \ platform.cpp platform.h sprite.cpp sprite.h trig.cpp trig.h \ \ lol/unit.h \ - lol/math/matrix.h lol/math/real.h lol/math/remez.h \ + lol/math/vector.h lol/math/real.h lol/math/remez.h \ \ application/application.cpp application/application.h \ eglapp.cpp eglapp.h \ diff --git a/src/core.h b/src/core.h index 0ce798b4..19781e9f 100644 --- a/src/core.h +++ b/src/core.h @@ -65,7 +65,7 @@ static inline int isnan(float f) #include "trig.h" #include "half.h" #include "lol/math/real.h" -#include "lol/math/matrix.h" +#include "lol/math/vector.h" #include "numeric.h" #include "timer.h" #include "thread/thread.h" diff --git a/src/eglapp.h b/src/eglapp.h index 25c739fd..6612b1be 100644 --- a/src/eglapp.h +++ b/src/eglapp.h @@ -16,7 +16,7 @@ #if !defined __LOL_EGLAPP_H__ #define __LOL_EGLAPP_H__ -#include "lol/math/matrix.h" +#include "lol/math/vector.h" namespace lol { diff --git a/src/image/image.h b/src/image/image.h index d4e85d50..2045a8e2 100644 --- a/src/image/image.h +++ b/src/image/image.h @@ -16,7 +16,7 @@ #if !defined __LOL_IMAGE_H__ #define __LOL_IMAGE_H__ -#include "lol/math/matrix.h" +#include "lol/math/vector.h" namespace lol { diff --git a/src/input.h b/src/input.h index 5768e2fe..99dc24eb 100644 --- a/src/input.h +++ b/src/input.h @@ -16,7 +16,7 @@ #if !defined __LOL_INPUT_H__ #define __LOL_INPUT_H__ -#include "lol/math/matrix.h" +#include "lol/math/vector.h" namespace lol { diff --git a/src/lol/math/matrix.h b/src/lol/math/matrix.h deleted file mode 100644 index 78eaa44f..00000000 --- a/src/lol/math/matrix.h +++ /dev/null @@ -1,1227 +0,0 @@ -// -// Lol Engine -// -// Copyright: (c) 2010-2011 Sam Hocevar -// This program is free software; you can redistribute it and/or -// modify it under the terms of the Do What The Fuck You Want To -// Public License, Version 2, as published by Sam Hocevar. See -// http://sam.zoy.org/projects/COPYING.WTFPL for more details. -// - -// -// The Matrix classes -// ------------------ -// - -#if !defined __LOL_MATH_MATRIX_H__ -#define __LOL_MATH_MATRIX_H__ - -#include -#include -#if !defined __ANDROID__ -# include -#endif - -namespace lol -{ - -class half; -class real; - -#define VECTOR_TYPES(tname, suffix) \ - template struct tname; \ - typedef tname f16##suffix; \ - typedef tname suffix; \ - typedef tname f64##suffix; \ - typedef tname i8##suffix; \ - typedef tname u8##suffix; \ - typedef tname i16##suffix; \ - typedef tname u16##suffix; \ - typedef tname i##suffix; \ - typedef tname u##suffix; \ - typedef tname i64##suffix; \ - typedef tname u64##suffix; - -VECTOR_TYPES(Vec2, vec2) -VECTOR_TYPES(Cmplx, cmplx) -VECTOR_TYPES(Vec3, vec3) -VECTOR_TYPES(Vec4, vec4) -VECTOR_TYPES(Quat, quat) -VECTOR_TYPES(Mat4, mat4) - -/* - * Magic vector swizzling (part 1/2) - */ - -template struct XVec2 -{ - inline Vec2 operator =(Vec2 that); - - static int const I = (N >> 2) & 3; - static int const J = (N >> 0) & 3; - T ptr[1 + (I > J ? I : J)]; -}; - -template struct XVec3 -{ - inline Vec3 operator =(Vec3 that); - - static int const I = (N >> 4) & 3; - static int const J = (N >> 2) & 3; - static int const K = (N >> 0) & 3; - T ptr[1 + (I > J ? I > K ? I : K - : J > K ? J : K)]; -}; - -template struct XVec4 -{ - inline Vec4 operator =(Vec4 that); - - static int const I = (N >> 6) & 3; - static int const J = (N >> 4) & 3; - static int const K = (N >> 2) & 3; - static int const L = (N >> 0) & 3; - T ptr[1 + (I > J ? I > K ? I > L ? I : L : K > L ? K : L - : J > K ? J > L ? J : L : K > L ? K : L)]; -}; - -/* - * Helper macros for vector type member functions - */ - -#define MEMBER_OPS() \ - inline T& operator[](int n) { return *(&x + n); } \ - inline T const& operator[](int n) const { return *(&x + n); } \ - \ - void printf() const; - -#define OTHER_MEMBER_OPS(tname) \ - template \ - inline operator tname() const \ - { \ - tname ret; \ - for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \ - ret[n] = static_cast((*this)[n]); \ - return ret; \ - } - -/* - * 2-element vectors - */ - -template struct Vec2 -{ - inline Vec2() {} - inline Vec2(T X, T Y) : x(X), y(Y) {} - - explicit inline Vec2(T X) : x(X), y(X) {} - - template - inline Vec2(XVec2 const &v) - : x(v.ptr[v.I]), y(v.ptr[v.J]) {} - - template - explicit inline Vec2(XVec2 const &v) - : x(v.ptr[v.I]), y(v.ptr[v.J]) {} - - MEMBER_OPS() - OTHER_MEMBER_OPS(Vec2) - -#if !defined __ANDROID__ - template - friend std::ostream &operator<<(std::ostream &stream, Vec2 const &v); -#endif - - union - { - struct { T x, y; }; - struct { T r, g; }; - struct { T s, t; }; - - XVec2 xx, rr, ss; - XVec2 xy, rg, st; - XVec2 yx, gr, ts; - XVec2 yy, gg, tt; - XVec3 xxx, rrr, sss; - XVec3 xxy, rrg, sst; - XVec3 xyx, rgr, sts; - XVec3 xyy, rgg, stt; - XVec3 yxx, grr, tss; - XVec3 yxy, grg, tst; - XVec3 yyx, ggr, tts; - XVec3 yyy, ggg, ttt; - XVec4 xxxx, rrrr, ssss; - XVec4 xxxy, rrrg, ssst; - XVec4 xxyx, rrgr, ssts; - XVec4 xxyy, rrgg, sstt; - XVec4 xyxx, rgrr, stss; - XVec4 xyxy, rgrg, stst; - XVec4 xyyx, rggr, stts; - XVec4 xyyy, rggg, sttt; - XVec4 yxxx, grrr, tsss; - XVec4 yxxy, grrg, tsst; - XVec4 yxyx, grgr, tsts; - XVec4 yxyy, grgg, tstt; - XVec4 yyxx, ggrr, ttss; - XVec4 yyxy, ggrg, ttst; - XVec4 yyyx, gggr, ttts; - XVec4 yyyy, gggg, tttt; - }; -}; - -/* - * 2-element complexes - */ - -template struct Cmplx -{ - inline Cmplx() {} - inline Cmplx(T X) : x(X), y(0) {} - inline Cmplx(T X, T Y) : x(X), y(Y) {} - - MEMBER_OPS() - - inline Cmplx operator *(Cmplx const &val) const - { - return Cmplx(x * val.x - y * val.y, x * val.y + y * val.x); - } - - inline Cmplx operator *=(Cmplx const &val) - { - return *this = (*this) * val; - } - - inline Cmplx operator ~() const - { - return Cmplx(x, -y); - } - - inline T norm() const { return len(*this); } -#if !defined __ANDROID__ - template - friend std::ostream &operator<<(std::ostream &stream, Cmplx const &v); -#endif - - T x, y; -}; - -template -static inline Cmplx re(Cmplx const &val) -{ - return ~val / sqlen(val); -} - -template -static inline Cmplx operator /(T a, Cmplx const &b) -{ - return a * re(b); -} - -template -static inline Cmplx operator /(Cmplx a, Cmplx const &b) -{ - return a * re(b); -} - -template -static inline bool operator ==(Cmplx const &a, T b) -{ - return (a.x == b) && !a.y; -} - -template -static inline bool operator !=(Cmplx const &a, T b) -{ - return (a.x != b) || a.y; -} - -template -static inline bool operator ==(T a, Cmplx const &b) { return b == a; } - -template -static inline bool operator !=(T a, Cmplx const &b) { return b != a; } - -/* - * 3-element vectors - */ - -template struct Vec3 -{ - inline Vec3() {} - inline Vec3(T X, T Y, T Z) : x(X), y(Y), z(Z) {} - inline Vec3(Vec2 XY, T Z) : x(XY.x), y(XY.y), z(Z) {} - inline Vec3(T X, Vec2 YZ) : x(X), y(YZ.x), z(YZ.y) {} - - explicit inline Vec3(T X) : x(X), y(X), z(X) {} - - template - inline Vec3(XVec3 const &v) - : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]) {} - - template - explicit inline Vec3(XVec3 const &v) - : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]) {} - - MEMBER_OPS() - OTHER_MEMBER_OPS(Vec3) - - template - friend Vec3 cross(Vec3, Vec3); - -#if !defined __ANDROID__ - template - friend std::ostream &operator<<(std::ostream &stream, Vec3 const &v); -#endif - - union - { - struct { T x, y, z; }; - struct { T r, g, b; }; - struct { T s, t, p; }; - - XVec2 xx, rr, ss; - XVec2 xy, rg, st; - XVec2 xz, rb, sp; - XVec2 yx, gr, ts; - XVec2 yy, gg, tt; - XVec2 yz, gb, tp; - XVec2 zx, br, ps; - XVec2 zy, bg, pt; - XVec2 zz, bb, pp; - XVec3 xxx, rrr, sss; - XVec3 xxy, rrg, sst; - XVec3 xxz, rrb, ssp; - XVec3 xyx, rgr, sts; - XVec3 xyy, rgg, stt; - XVec3 xyz, rgb, stp; - XVec3 xzx, rbr, sps; - XVec3 xzy, rbg, spt; - XVec3 xzz, rbb, spp; - XVec3 yxx, grr, tss; - XVec3 yxy, grg, tst; - XVec3 yxz, grb, tsp; - XVec3 yyx, ggr, tts; - XVec3 yyy, ggg, ttt; - XVec3 yyz, ggb, ttp; - XVec3 yzx, gbr, tps; - XVec3 yzy, gbg, tpt; - XVec3 yzz, gbb, tpp; - XVec3 zxx, brr, pss; - XVec3 zxy, brg, pst; - XVec3 zxz, brb, psp; - XVec3 zyx, bgr, pts; - XVec3 zyy, bgg, ptt; - XVec3 zyz, bgb, ptp; - XVec3 zzx, bbr, pps; - XVec3 zzy, bbg, ppt; - XVec3 zzz, bbb, ppp; - XVec4 xxxx, rrrr, ssss; - XVec4 xxxy, rrrg, ssst; - XVec4 xxxz, rrrb, sssp; - XVec4 xxyx, rrgr, ssts; - XVec4 xxyy, rrgg, sstt; - XVec4 xxyz, rrgb, sstp; - XVec4 xxzx, rrbr, ssps; - XVec4 xxzy, rrbg, sspt; - XVec4 xxzz, rrbb, sspp; - XVec4 xyxx, rgrr, stss; - XVec4 xyxy, rgrg, stst; - XVec4 xyxz, rgrb, stsp; - XVec4 xyyx, rggr, stts; - XVec4 xyyy, rggg, sttt; - XVec4 xyyz, rggb, sttp; - XVec4 xyzx, rgbr, stps; - XVec4 xyzy, rgbg, stpt; - XVec4 xyzz, rgbb, stpp; - XVec4 xzxx, rbrr, spss; - XVec4 xzxy, rbrg, spst; - XVec4 xzxz, rbrb, spsp; - XVec4 xzyx, rbgr, spts; - XVec4 xzyy, rbgg, sptt; - XVec4 xzyz, rbgb, sptp; - XVec4 xzzx, rbbr, spps; - XVec4 xzzy, rbbg, sppt; - XVec4 xzzz, rbbb, sppp; - XVec4 yxxx, grrr, tsss; - XVec4 yxxy, grrg, tsst; - XVec4 yxxz, grrb, tssp; - XVec4 yxyx, grgr, tsts; - XVec4 yxyy, grgg, tstt; - XVec4 yxyz, grgb, tstp; - XVec4 yxzx, grbr, tsps; - XVec4 yxzy, grbg, tspt; - XVec4 yxzz, grbb, tspp; - XVec4 yyxx, ggrr, ttss; - XVec4 yyxy, ggrg, ttst; - XVec4 yyxz, ggrb, ttsp; - XVec4 yyyx, gggr, ttts; - XVec4 yyyy, gggg, tttt; - XVec4 yyyz, gggb, tttp; - XVec4 yyzx, ggbr, ttps; - XVec4 yyzy, ggbg, ttpt; - XVec4 yyzz, ggbb, ttpp; - XVec4 yzxx, gbrr, tpss; - XVec4 yzxy, gbrg, tpst; - XVec4 yzxz, gbrb, tpsp; - XVec4 yzyx, gbgr, tpts; - XVec4 yzyy, gbgg, tptt; - XVec4 yzyz, gbgb, tptp; - XVec4 yzzx, gbbr, tpps; - XVec4 yzzy, gbbg, tppt; - XVec4 yzzz, gbbb, tppp; - XVec4 zxxx, brrr, psss; - XVec4 zxxy, brrg, psst; - XVec4 zxxz, brrb, pssp; - XVec4 zxyx, brgr, psts; - XVec4 zxyy, brgg, pstt; - XVec4 zxyz, brgb, pstp; - XVec4 zxzx, brbr, psps; - XVec4 zxzy, brbg, pspt; - XVec4 zxzz, brbb, pspp; - XVec4 zyxx, bgrr, ptss; - XVec4 zyxy, bgrg, ptst; - XVec4 zyxz, bgrb, ptsp; - XVec4 zyyx, bggr, ptts; - XVec4 zyyy, bggg, pttt; - XVec4 zyyz, bggb, pttp; - XVec4 zyzx, bgbr, ptps; - XVec4 zyzy, bgbg, ptpt; - XVec4 zyzz, bgbb, ptpp; - XVec4 zzxx, bbrr, ppss; - XVec4 zzxy, bbrg, ppst; - XVec4 zzxz, bbrb, ppsp; - XVec4 zzyx, bbgr, ppts; - XVec4 zzyy, bbgg, pptt; - XVec4 zzyz, bbgb, pptp; - XVec4 zzzx, bbbr, ppps; - XVec4 zzzy, bbbg, pppt; - XVec4 zzzz, bbbb, pppp; - }; -}; - -/* - * 4-element vectors - */ - -template struct Vec4 -{ - inline Vec4() {} - inline Vec4(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {} - inline Vec4(Vec2 XY, T Z, T W) : x(XY.x), y(XY.y), z(Z), w(W) {} - inline Vec4(T X, Vec2 YZ, T W) : x(X), y(YZ.x), z(YZ.y), w(W) {} - inline Vec4(T X, T Y, Vec2 ZW) : x(X), y(Y), z(ZW.x), w(ZW.y) {} - inline Vec4(Vec2 XY, Vec2 ZW) : x(XY.x), y(XY.y), z(ZW.x), w(ZW.y) {} - inline Vec4(Vec3 XYZ, T W) : x(XYZ.x), y(XYZ.y), z(XYZ.z), w(W) {} - inline Vec4(T X, Vec3 YZW) : x(X), y(YZW.x), z(YZW.y), w(YZW.z) {} - - explicit inline Vec4(T X) : x(X), y(X), z(X), w(X) {} - - template - inline Vec4(XVec4 const &v) - : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]), w(v.ptr[v.L]) {} - - template - explicit inline Vec4(XVec4 const &v) - : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]), w(v.ptr[v.L]) {} - - MEMBER_OPS() - OTHER_MEMBER_OPS(Vec4) - -#if !defined __ANDROID__ - template - friend std::ostream &operator<<(std::ostream &stream, Vec4 const &v); -#endif - - union - { - struct { T x, y, z, w; }; - struct { T r, g, b, a; }; - struct { T s, t, p, q; }; - - XVec2 xx, rr, ss; - XVec2 xy, rg, st; - XVec2 xz, rb, sp; - XVec2 xw, ra, sq; - XVec2 yx, gr, ts; - XVec2 yy, gg, tt; - XVec2 yz, gb, tp; - XVec2 yw, ga, tq; - XVec2 zx, br, ps; - XVec2 zy, bg, pt; - XVec2 zz, bb, pp; - XVec2 zw, ba, pq; - XVec2 wx, ar, qs; - XVec2 wy, ag, qt; - XVec2 wz, ab, qp; - XVec2 ww, aa, qq; - XVec3 xxx, rrr, sss; - XVec3 xxy, rrg, sst; - XVec3 xxz, rrb, ssp; - XVec3 xxw, rra, ssq; - XVec3 xyx, rgr, sts; - XVec3 xyy, rgg, stt; - XVec3 xyz, rgb, stp; - XVec3 xyw, rga, stq; - XVec3 xzx, rbr, sps; - XVec3 xzy, rbg, spt; - XVec3 xzz, rbb, spp; - XVec3 xzw, rba, spq; - XVec3 xwx, rar, sqs; - XVec3 xwy, rag, sqt; - XVec3 xwz, rab, sqp; - XVec3 xww, raa, sqq; - XVec3 yxx, grr, tss; - XVec3 yxy, grg, tst; - XVec3 yxz, grb, tsp; - XVec3 yxw, gra, tsq; - XVec3 yyx, ggr, tts; - XVec3 yyy, ggg, ttt; - XVec3 yyz, ggb, ttp; - XVec3 yyw, gga, ttq; - XVec3 yzx, gbr, tps; - XVec3 yzy, gbg, tpt; - XVec3 yzz, gbb, tpp; - XVec3 yzw, gba, tpq; - XVec3 ywx, gar, tqs; - XVec3 ywy, gag, tqt; - XVec3 ywz, gab, tqp; - XVec3 yww, gaa, tqq; - XVec3 zxx, brr, pss; - XVec3 zxy, brg, pst; - XVec3 zxz, brb, psp; - XVec3 zxw, bra, psq; - XVec3 zyx, bgr, pts; - XVec3 zyy, bgg, ptt; - XVec3 zyz, bgb, ptp; - XVec3 zyw, bga, ptq; - XVec3 zzx, bbr, pps; - XVec3 zzy, bbg, ppt; - XVec3 zzz, bbb, ppp; - XVec3 zzw, bba, ppq; - XVec3 zwx, bar, pqs; - XVec3 zwy, bag, pqt; - XVec3 zwz, bab, pqp; - XVec3 zww, baa, pqq; - XVec3 wxx, arr, qss; - XVec3 wxy, arg, qst; - XVec3 wxz, arb, qsp; - XVec3 wxw, ara, qsq; - XVec3 wyx, agr, qts; - XVec3 wyy, agg, qtt; - XVec3 wyz, agb, qtp; - XVec3 wyw, aga, qtq; - XVec3 wzx, abr, qps; - XVec3 wzy, abg, qpt; - XVec3 wzz, abb, qpp; - XVec3 wzw, aba, qpq; - XVec3 wwx, aar, qqs; - XVec3 wwy, aag, qqt; - XVec3 wwz, aab, qqp; - XVec3 www, aaa, qqq; - XVec4 xxxx, rrrr, ssss; - XVec4 xxxy, rrrg, ssst; - XVec4 xxxz, rrrb, sssp; - XVec4 xxxw, rrra, sssq; - XVec4 xxyx, rrgr, ssts; - XVec4 xxyy, rrgg, sstt; - XVec4 xxyz, rrgb, sstp; - XVec4 xxyw, rrga, sstq; - XVec4 xxzx, rrbr, ssps; - XVec4 xxzy, rrbg, sspt; - XVec4 xxzz, rrbb, sspp; - XVec4 xxzw, rrba, sspq; - XVec4 xxwx, rrar, ssqs; - XVec4 xxwy, rrag, ssqt; - XVec4 xxwz, rrab, ssqp; - XVec4 xxww, rraa, ssqq; - XVec4 xyxx, rgrr, stss; - XVec4 xyxy, rgrg, stst; - XVec4 xyxz, rgrb, stsp; - XVec4 xyxw, rgra, stsq; - XVec4 xyyx, rggr, stts; - XVec4 xyyy, rggg, sttt; - XVec4 xyyz, rggb, sttp; - XVec4 xyyw, rgga, sttq; - XVec4 xyzx, rgbr, stps; - XVec4 xyzy, rgbg, stpt; - XVec4 xyzz, rgbb, stpp; - XVec4 xyzw, rgba, stpq; - XVec4 xywx, rgar, stqs; - XVec4 xywy, rgag, stqt; - XVec4 xywz, rgab, stqp; - XVec4 xyww, rgaa, stqq; - XVec4 xzxx, rbrr, spss; - XVec4 xzxy, rbrg, spst; - XVec4 xzxz, rbrb, spsp; - XVec4 xzxw, rbra, spsq; - XVec4 xzyx, rbgr, spts; - XVec4 xzyy, rbgg, sptt; - XVec4 xzyz, rbgb, sptp; - XVec4 xzyw, rbga, sptq; - XVec4 xzzx, rbbr, spps; - XVec4 xzzy, rbbg, sppt; - XVec4 xzzz, rbbb, sppp; - XVec4 xzzw, rbba, sppq; - XVec4 xzwx, rbar, spqs; - XVec4 xzwy, rbag, spqt; - XVec4 xzwz, rbab, spqp; - XVec4 xzww, rbaa, spqq; - XVec4 xwxx, rarr, sqss; - XVec4 xwxy, rarg, sqst; - XVec4 xwxz, rarb, sqsp; - XVec4 xwxw, rara, sqsq; - XVec4 xwyx, ragr, sqts; - XVec4 xwyy, ragg, sqtt; - XVec4 xwyz, ragb, sqtp; - XVec4 xwyw, raga, sqtq; - XVec4 xwzx, rabr, sqps; - XVec4 xwzy, rabg, sqpt; - XVec4 xwzz, rabb, sqpp; - XVec4 xwzw, raba, sqpq; - XVec4 xwwx, raar, sqqs; - XVec4 xwwy, raag, sqqt; - XVec4 xwwz, raab, sqqp; - XVec4 xwww, raaa, sqqq; - XVec4 yxxx, grrr, tsss; - XVec4 yxxy, grrg, tsst; - XVec4 yxxz, grrb, tssp; - XVec4 yxxw, grra, tssq; - XVec4 yxyx, grgr, tsts; - XVec4 yxyy, grgg, tstt; - XVec4 yxyz, grgb, tstp; - XVec4 yxyw, grga, tstq; - XVec4 yxzx, grbr, tsps; - XVec4 yxzy, grbg, tspt; - XVec4 yxzz, grbb, tspp; - XVec4 yxzw, grba, tspq; - XVec4 yxwx, grar, tsqs; - XVec4 yxwy, grag, tsqt; - XVec4 yxwz, grab, tsqp; - XVec4 yxww, graa, tsqq; - XVec4 yyxx, ggrr, ttss; - XVec4 yyxy, ggrg, ttst; - XVec4 yyxz, ggrb, ttsp; - XVec4 yyxw, ggra, ttsq; - XVec4 yyyx, gggr, ttts; - XVec4 yyyy, gggg, tttt; - XVec4 yyyz, gggb, tttp; - XVec4 yyyw, ggga, tttq; - XVec4 yyzx, ggbr, ttps; - XVec4 yyzy, ggbg, ttpt; - XVec4 yyzz, ggbb, ttpp; - XVec4 yyzw, ggba, ttpq; - XVec4 yywx, ggar, ttqs; - XVec4 yywy, ggag, ttqt; - XVec4 yywz, ggab, ttqp; - XVec4 yyww, ggaa, ttqq; - XVec4 yzxx, gbrr, tpss; - XVec4 yzxy, gbrg, tpst; - XVec4 yzxz, gbrb, tpsp; - XVec4 yzxw, gbra, tpsq; - XVec4 yzyx, gbgr, tpts; - XVec4 yzyy, gbgg, tptt; - XVec4 yzyz, gbgb, tptp; - XVec4 yzyw, gbga, tptq; - XVec4 yzzx, gbbr, tpps; - XVec4 yzzy, gbbg, tppt; - XVec4 yzzz, gbbb, tppp; - XVec4 yzzw, gbba, tppq; - XVec4 yzwx, gbar, tpqs; - XVec4 yzwy, gbag, tpqt; - XVec4 yzwz, gbab, tpqp; - XVec4 yzww, gbaa, tpqq; - XVec4 ywxx, garr, tqss; - XVec4 ywxy, garg, tqst; - XVec4 ywxz, garb, tqsp; - XVec4 ywxw, gara, tqsq; - XVec4 ywyx, gagr, tqts; - XVec4 ywyy, gagg, tqtt; - XVec4 ywyz, gagb, tqtp; - XVec4 ywyw, gaga, tqtq; - XVec4 ywzx, gabr, tqps; - XVec4 ywzy, gabg, tqpt; - XVec4 ywzz, gabb, tqpp; - XVec4 ywzw, gaba, tqpq; - XVec4 ywwx, gaar, tqqs; - XVec4 ywwy, gaag, tqqt; - XVec4 ywwz, gaab, tqqp; - XVec4 ywww, gaaa, tqqq; - XVec4 zxxx, brrr, psss; - XVec4 zxxy, brrg, psst; - XVec4 zxxz, brrb, pssp; - XVec4 zxxw, brra, pssq; - XVec4 zxyx, brgr, psts; - XVec4 zxyy, brgg, pstt; - XVec4 zxyz, brgb, pstp; - XVec4 zxyw, brga, pstq; - XVec4 zxzx, brbr, psps; - XVec4 zxzy, brbg, pspt; - XVec4 zxzz, brbb, pspp; - XVec4 zxzw, brba, pspq; - XVec4 zxwx, brar, psqs; - XVec4 zxwy, brag, psqt; - XVec4 zxwz, brab, psqp; - XVec4 zxww, braa, psqq; - XVec4 zyxx, bgrr, ptss; - XVec4 zyxy, bgrg, ptst; - XVec4 zyxz, bgrb, ptsp; - XVec4 zyxw, bgra, ptsq; - XVec4 zyyx, bggr, ptts; - XVec4 zyyy, bggg, pttt; - XVec4 zyyz, bggb, pttp; - XVec4 zyyw, bgga, pttq; - XVec4 zyzx, bgbr, ptps; - XVec4 zyzy, bgbg, ptpt; - XVec4 zyzz, bgbb, ptpp; - XVec4 zyzw, bgba, ptpq; - XVec4 zywx, bgar, ptqs; - XVec4 zywy, bgag, ptqt; - XVec4 zywz, bgab, ptqp; - XVec4 zyww, bgaa, ptqq; - XVec4 zzxx, bbrr, ppss; - XVec4 zzxy, bbrg, ppst; - XVec4 zzxz, bbrb, ppsp; - XVec4 zzxw, bbra, ppsq; - XVec4 zzyx, bbgr, ppts; - XVec4 zzyy, bbgg, pptt; - XVec4 zzyz, bbgb, pptp; - XVec4 zzyw, bbga, pptq; - XVec4 zzzx, bbbr, ppps; - XVec4 zzzy, bbbg, pppt; - XVec4 zzzz, bbbb, pppp; - XVec4 zzzw, bbba, pppq; - XVec4 zzwx, bbar, ppqs; - XVec4 zzwy, bbag, ppqt; - XVec4 zzwz, bbab, ppqp; - XVec4 zzww, bbaa, ppqq; - XVec4 zwxx, barr, pqss; - XVec4 zwxy, barg, pqst; - XVec4 zwxz, barb, pqsp; - XVec4 zwxw, bara, pqsq; - XVec4 zwyx, bagr, pqts; - XVec4 zwyy, bagg, pqtt; - XVec4 zwyz, bagb, pqtp; - XVec4 zwyw, baga, pqtq; - XVec4 zwzx, babr, pqps; - XVec4 zwzy, babg, pqpt; - XVec4 zwzz, babb, pqpp; - XVec4 zwzw, baba, pqpq; - XVec4 zwwx, baar, pqqs; - XVec4 zwwy, baag, pqqt; - XVec4 zwwz, baab, pqqp; - XVec4 zwww, baaa, pqqq; - XVec4 wxxx, arrr, qsss; - XVec4 wxxy, arrg, qsst; - XVec4 wxxz, arrb, qssp; - XVec4 wxxw, arra, qssq; - XVec4 wxyx, argr, qsts; - XVec4 wxyy, argg, qstt; - XVec4 wxyz, argb, qstp; - XVec4 wxyw, arga, qstq; - XVec4 wxzx, arbr, qsps; - XVec4 wxzy, arbg, qspt; - XVec4 wxzz, arbb, qspp; - XVec4 wxzw, arba, qspq; - XVec4 wxwx, arar, qsqs; - XVec4 wxwy, arag, qsqt; - XVec4 wxwz, arab, qsqp; - XVec4 wxww, araa, qsqq; - XVec4 wyxx, agrr, qtss; - XVec4 wyxy, agrg, qtst; - XVec4 wyxz, agrb, qtsp; - XVec4 wyxw, agra, qtsq; - XVec4 wyyx, aggr, qtts; - XVec4 wyyy, aggg, qttt; - XVec4 wyyz, aggb, qttp; - XVec4 wyyw, agga, qttq; - XVec4 wyzx, agbr, qtps; - XVec4 wyzy, agbg, qtpt; - XVec4 wyzz, agbb, qtpp; - XVec4 wyzw, agba, qtpq; - XVec4 wywx, agar, qtqs; - XVec4 wywy, agag, qtqt; - XVec4 wywz, agab, qtqp; - XVec4 wyww, agaa, qtqq; - XVec4 wzxx, abrr, qpss; - XVec4 wzxy, abrg, qpst; - XVec4 wzxz, abrb, qpsp; - XVec4 wzxw, abra, qpsq; - XVec4 wzyx, abgr, qpts; - XVec4 wzyy, abgg, qptt; - XVec4 wzyz, abgb, qptp; - XVec4 wzyw, abga, qptq; - XVec4 wzzx, abbr, qpps; - XVec4 wzzy, abbg, qppt; - XVec4 wzzz, abbb, qppp; - XVec4 wzzw, abba, qppq; - XVec4 wzwx, abar, qpqs; - XVec4 wzwy, abag, qpqt; - XVec4 wzwz, abab, qpqp; - XVec4 wzww, abaa, qpqq; - XVec4 wwxx, aarr, qqss; - XVec4 wwxy, aarg, qqst; - XVec4 wwxz, aarb, qqsp; - XVec4 wwxw, aara, qqsq; - XVec4 wwyx, aagr, qqts; - XVec4 wwyy, aagg, qqtt; - XVec4 wwyz, aagb, qqtp; - XVec4 wwyw, aaga, qqtq; - XVec4 wwzx, aabr, qqps; - XVec4 wwzy, aabg, qqpt; - XVec4 wwzz, aabb, qqpp; - XVec4 wwzw, aaba, qqpq; - XVec4 wwwx, aaar, qqqs; - XVec4 wwwy, aaag, qqqt; - XVec4 wwwz, aaab, qqqp; - XVec4 wwww, aaaa, qqqq; - }; -}; - -/* - * 4-element quaternions - */ - -template struct Quat -{ - inline Quat() {} - inline Quat(T X) : x(0), y(0), z(0), w(X) {} - inline Quat(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {} - - Quat(Mat4 const &m); - - MEMBER_OPS() - - inline Quat operator *(Quat const &val) const - { - Quat ret; - Vec3 v1(x, y, z); - Vec3 v2(val.x, val.y, val.z); - Vec3 v3 = cross(v1, v2) + w * v2 + val.w * v1; - ret.x = v3.x; - ret.y = v3.y; - ret.z = v3.z; - ret.w = w * val.w - dot(v1, v2); - return ret; - } - - inline Quat operator *=(Quat const &val) - { - return *this = (*this) * val; - } - - inline Quat operator ~() const - { - Quat ret; - for (int n = 0; n < 3; n++) - ret[n] = -(*this)[n]; - ret[3] = (*this)[3]; - return ret; - } - -#if !defined __ANDROID__ - template - friend std::ostream &operator<<(std::ostream &stream, Quat const &v); -#endif - - T x, y, z, w; -}; - -template -inline T norm(Quat const &val) -{ - return sqlen(val); -} - -template -static inline Quat re(Quat const &val) -{ - return ~val / norm(val); -} - -template -static inline Quat operator /(T x, Quat const &y) -{ - return x * re(y); -} - -template -static inline Quat operator /(Quat x, Quat const &y) -{ - return x * re(y); -} - -/* - * Common operators for all vector types, including quaternions - */ - -#define VECTOR_OP(tname, op, tprefix, T) \ - tprefix \ - static inline tname operator op(tname const &a, tname const &b) \ - { \ - tname ret; \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - ret[n] = a[n] op b[n]; \ - return ret; \ - } \ - \ - tprefix \ - static inline tname operator op##=(tname &a, tname const &b) \ - { \ - return a = a op b; \ - } - -#define BOOL_OP(tname, op, op2, ret, tprefix, T) \ - tprefix \ - static inline bool operator op(tname const &a, tname const &b) \ - { \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - if (!(a[n] op2 b[n])) \ - return !ret; \ - return ret; \ - } - -#define SCALAR_OP(tname, op, tprefix, T) \ - tprefix \ - static inline tname operator op(tname const &a, T const &val) \ - { \ - tname ret; \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - ret[n] = a[n] op val; \ - return ret; \ - } \ - \ - tprefix \ - static inline tname operator op(T const &val, tname const &a) \ - { \ - tname ret; \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - ret[n] = a[n] op val; \ - return ret; \ - } \ - \ - tprefix \ - static inline tname operator op##=(tname &a, T const &val) \ - { \ - return a = a op val; \ - } - -#define SCALAR_PROMOTE_OP(tname, op, U) \ - template \ - static inline tname operator op(U const &val, tname const &a) \ - { \ - tname ret; \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - ret[n] = val op a[n]; \ - return ret; \ - } - -#define GLOBAL_OPS(tname, tprefix, T) \ - SCALAR_OP(tname, *, tprefix, T) \ - SCALAR_OP(tname, /, tprefix, T) \ - \ - VECTOR_OP(tname, -, tprefix, T) \ - VECTOR_OP(tname, +, tprefix, T) \ - \ - BOOL_OP(tname, ==, ==, true, tprefix, T) \ - BOOL_OP(tname, !=, ==, false, tprefix, T) \ - \ - tprefix \ - static inline tname operator -(tname const &a) \ - { \ - tname ret; \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - ret[n] = -a[n]; \ - return ret; \ - } \ - \ - tprefix \ - static inline T sqlen(tname const &a) \ - { \ - T acc = 0; \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - acc += a[n] * a[n]; \ - return acc; \ - } \ - \ - tprefix \ - static inline double len(tname const &a) \ - { \ - using namespace std; \ - return sqrt((double)sqlen(a)); \ - } \ - \ - tprefix \ - static inline T dot(tname const &a, tname const &b) \ - { \ - T ret = 0; \ - for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ - ret += a[n] * b[n]; \ - return ret; \ - } \ - \ - tprefix \ - static inline tname normalize(tname const &val) \ - { \ - T norm = len(val); \ - return norm ? val / norm : val * (T)0; \ - } - -#define GLOBAL_TEMPLATE_OPS(tname) \ - GLOBAL_OPS(tname, template, T) - -#define ALL_GLOBAL_OPS(tname, tprefix, T) \ - VECTOR_OP(tname, *, tprefix, T) \ - VECTOR_OP(tname, /, tprefix, T) \ - \ - GLOBAL_OPS(tname, tprefix, T) \ - \ - BOOL_OP(tname, <=, <=, true, tprefix, T) \ - BOOL_OP(tname, >=, >=, true, tprefix, T) \ - BOOL_OP(tname, <, <, true, tprefix, T) \ - BOOL_OP(tname, >, >, true, tprefix, T) - -/* FIXME: a few problems need to be fixed before we can use "half" here. It - * will probably never work until we switch to C++11 because it's not really - * a POD class. */ -#define GLOBAL_TYPED_OPS(tname) \ - ALL_GLOBAL_OPS(tname, , float) \ - ALL_GLOBAL_OPS(tname, , double) \ - ALL_GLOBAL_OPS(tname, , int8_t) \ - ALL_GLOBAL_OPS(tname, , uint8_t) \ - ALL_GLOBAL_OPS(tname, , int16_t) \ - ALL_GLOBAL_OPS(tname, , uint16_t) \ - ALL_GLOBAL_OPS(tname, , int32_t) \ - ALL_GLOBAL_OPS(tname, , uint32_t) \ - ALL_GLOBAL_OPS(tname, , int64_t) \ - ALL_GLOBAL_OPS(tname, , uint64_t) - -GLOBAL_TEMPLATE_OPS(Cmplx) -GLOBAL_TEMPLATE_OPS(Quat) - -GLOBAL_TYPED_OPS(Vec2) -GLOBAL_TYPED_OPS(Vec3) -GLOBAL_TYPED_OPS(Vec4) - -/* - * Magic vector swizzling (part 2/2) - */ - -template -inline Vec2 XVec2::operator =(Vec2 that) -{ - ptr[I] = that.x; ptr[J] = that.y; - return *this; -} - -template -inline Vec3 XVec3::operator =(Vec3 that) -{ - ptr[I] = that.x; ptr[J] = that.y; ptr[K] = that.z; - return *this; -} - -template -inline Vec4 XVec4::operator =(Vec4 that) -{ - ptr[I] = that.x; ptr[J] = that.y; ptr[K] = that.z; ptr[L] = that.w; - return *this; -} - -/* - * 4×4-element matrices - */ - -template struct Mat4 -{ - inline Mat4() {} - explicit inline Mat4(T val) - { - for (int j = 0; j < 4; j++) - for (int i = 0; i < 4; i++) - v[i][j] = (i == j) ? val : 0; - } - inline Mat4(Vec4 v0, Vec4 v1, Vec4 v2, Vec4 v3) - { - v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; - } - - inline Vec4& operator[](int n) { return v[n]; } - inline Vec4 const& operator[](int n) const { return v[n]; } - - T det() const; - Mat4 invert() const; - - /* Helpers for transformation matrices */ - static Mat4 translate(T x, T y, T z); - static Mat4 translate(Vec3 v); - static Mat4 rotate(T angle, T x, T y, T z); - static Mat4 rotate(T angle, Vec3 v); - static Mat4 rotate(Quat q); - - static inline Mat4 translate(Mat4 mat, Vec3 v) - { - return translate(v) * mat; - } - - static inline Mat4 rotate(Mat4 mat, T angle, Vec3 v) - { - return rotate(angle, v) * mat; - } - - /* Helpers for view matrices */ - static Mat4 lookat(Vec3 eye, Vec3 center, Vec3 up); - - /* Helpers for projection matrices */ - static Mat4 ortho(T left, T right, T bottom, T top, T near, T far); - static Mat4 frustum(T left, T right, T bottom, T top, T near, T far); - static Mat4 perspective(T fov_y, T width, T height, T near, T far); - - void printf() const; - -#if !defined __ANDROID__ - template - friend std::ostream &operator<<(std::ostream &stream, Mat4 const &m); -#endif - - inline Mat4 operator +(Mat4 const val) const - { - Mat4 ret; - for (int j = 0; j < 4; j++) - for (int i = 0; i < 4; i++) - ret[i][j] = v[i][j] + val[i][j]; - return ret; - } - - inline Mat4 operator +=(Mat4 const val) - { - return *this = *this + val; - } - - inline Mat4 operator -(Mat4 const val) const - { - Mat4 ret; - for (int j = 0; j < 4; j++) - for (int i = 0; i < 4; i++) - ret[i][j] = v[i][j] - val[i][j]; - return ret; - } - - inline Mat4 operator -=(Mat4 const val) - { - return *this = *this - val; - } - - inline Mat4 operator *(Mat4 const val) const - { - Mat4 ret; - for (int j = 0; j < 4; j++) - for (int i = 0; i < 4; i++) - { - T tmp = 0; - for (int k = 0; k < 4; k++) - tmp += v[k][j] * val[i][k]; - ret[i][j] = tmp; - } - return ret; - } - - inline Mat4 operator *=(Mat4 const val) - { - return *this = *this * val; - } - - inline Vec4 operator *(Vec4 const val) const - { - Vec4 ret; - for (int j = 0; j < 4; j++) - { - T tmp = 0; - for (int i = 0; i < 4; i++) - tmp += v[i][j] * val[i]; - ret[j] = tmp; - } - return ret; - } - - Vec4 v[4]; -}; - -/* - * Arbitrarily-sized square matrices; for now this only supports - * naive inversion and is used for the Remez inversion method. - */ - -template struct Mat -{ - inline Mat() {} - - Mat(T x) - { - for (int j = 0; j < N; j++) - for (int i = 0; i < N; i++) - if (i == j) - m[i][j] = x; - else - m[i][j] = 0; - } - - /* Naive matrix inversion */ - Mat inv() const - { - Mat a = *this, b((T)1); - - /* Inversion method: iterate through all columns and make sure - * all the terms are 1 on the diagonal and 0 everywhere else */ - for (int i = 0; i < N; i++) - { - /* If the expected coefficient is zero, add one of - * the other lines. The first we meet will do. */ - if (!a.m[i][i]) - { - for (int j = i + 1; j < N; j++) - { - if (!a.m[i][j]) - continue; - /* Add row j to row i */ - for (int n = 0; n < N; n++) - { - a.m[n][i] += a.m[n][j]; - b.m[n][i] += b.m[n][j]; - } - break; - } - } - - /* Now we know the diagonal term is non-zero. Get its inverse - * and use that to nullify all other terms in the column */ - T x = (T)1 / a.m[i][i]; - for (int j = 0; j < N; j++) - { - if (j == i) - continue; - T mul = x * a.m[i][j]; - for (int n = 0; n < N; n++) - { - a.m[n][j] -= mul * a.m[n][i]; - b.m[n][j] -= mul * b.m[n][i]; - } - } - - /* Finally, ensure the diagonal term is 1 */ - for (int n = 0; n < N; n++) - { - a.m[n][i] *= x; - b.m[n][i] *= x; - } - } - - return b; - } - - T m[N][N]; -}; - -} /* namespace lol */ - -#endif // __LOL_MATH_MATRIX_H__ - diff --git a/src/lol/math/remez.h b/src/lol/math/remez.h index b1f39c1e..634233f0 100644 --- a/src/lol/math/remez.h +++ b/src/lol/math/remez.h @@ -18,7 +18,7 @@ #include -#include "lol/math/matrix.h" +#include "lol/math/vector.h" namespace lol { diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h new file mode 100644 index 00000000..3561997c --- /dev/null +++ b/src/lol/math/vector.h @@ -0,0 +1,1213 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2012 Sam Hocevar +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://sam.zoy.org/projects/COPYING.WTFPL for more details. +// + +// +// The vector, complex, quaternion and matrix classes +// -------------------------------------------------- +// + +#if !defined __LOL_MATH_VECTOR_H__ +#define __LOL_MATH_VECTOR_H__ + +#include +#include +#if !defined __ANDROID__ +# include +#endif + +namespace lol +{ + +class half; +class real; + +#define DECLARE_VECTOR_TYPEDEFS(tname, suffix) \ + template struct tname; \ + typedef tname f16##suffix; \ + typedef tname suffix; \ + typedef tname f64##suffix; \ + typedef tname i8##suffix; \ + typedef tname u8##suffix; \ + typedef tname i16##suffix; \ + typedef tname u16##suffix; \ + typedef tname i##suffix; \ + typedef tname u##suffix; \ + typedef tname i64##suffix; \ + typedef tname u64##suffix; + +DECLARE_VECTOR_TYPEDEFS(Vec2, vec2) +DECLARE_VECTOR_TYPEDEFS(Cmplx, cmplx) +DECLARE_VECTOR_TYPEDEFS(Vec3, vec3) +DECLARE_VECTOR_TYPEDEFS(Vec4, vec4) +DECLARE_VECTOR_TYPEDEFS(Quat, quat) +DECLARE_VECTOR_TYPEDEFS(Mat4, mat4) + +/* + * Magic vector swizzling (part 1/2) + */ + +template struct XVec2 +{ + inline Vec2 operator =(Vec2 that); + + static int const I = (N >> 4) & 3; + static int const J = (N >> 0) & 3; + T ptr[1 + (I > J ? I : J)]; +}; + +template struct XVec3 +{ + inline Vec3 operator =(Vec3 that); + + static int const I = (N >> 8) & 3; + static int const J = (N >> 4) & 3; + static int const K = (N >> 0) & 3; + T ptr[1 + (I > J ? I > K ? I : K + : J > K ? J : K)]; +}; + +template struct XVec4 +{ + inline Vec4 operator =(Vec4 that); + + static int const I = (N >> 12) & 3; + static int const J = (N >> 8) & 3; + static int const K = (N >> 4) & 3; + static int const L = (N >> 0) & 3; + T ptr[1 + (I > J ? I > K ? I > L ? I : L : K > L ? K : L + : J > K ? J > L ? J : L : K > L ? K : L)]; +}; + +/* + * Helper macro for vector type member functions + */ + +#define DECLARE_MEMBER_OPS(tname) \ + inline T& operator[](int n) { return *(&x + n); } \ + inline T const& operator[](int n) const { return *(&x + n); } \ + \ + void printf() const; \ + \ + template \ + inline operator tname() const \ + { \ + tname ret; \ + for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \ + ret[n] = static_cast((*this)[n]); \ + return ret; \ + } + +/* + * 2-element vectors + */ + +template struct Vec2 +{ + inline Vec2() {} + inline Vec2(T X, T Y) : x(X), y(Y) {} + + explicit inline Vec2(T X) : x(X), y(X) {} + + template + inline Vec2(XVec2 const &v) + : x(v.ptr[v.I]), y(v.ptr[v.J]) {} + + template + explicit inline Vec2(XVec2 const &v) + : x(v.ptr[v.I]), y(v.ptr[v.J]) {} + + DECLARE_MEMBER_OPS(Vec2) + +#if !defined __ANDROID__ + template + friend std::ostream &operator<<(std::ostream &stream, Vec2 const &v); +#endif + + union + { + struct { T x, y; }; + struct { T r, g; }; + struct { T s, t; }; + + XVec2 xx, rr, ss; + XVec2 xy, rg, st; + XVec2 yx, gr, ts; + XVec2 yy, gg, tt; + + XVec3 xxx, rrr, sss; + XVec3 xxy, rrg, sst; + XVec3 xyx, rgr, sts; + XVec3 xyy, rgg, stt; + XVec3 yxx, grr, tss; + XVec3 yxy, grg, tst; + XVec3 yyx, ggr, tts; + XVec3 yyy, ggg, ttt; + + XVec4 xxxx, rrrr, ssss; + XVec4 xxxy, rrrg, ssst; + XVec4 xxyx, rrgr, ssts; + XVec4 xxyy, rrgg, sstt; + XVec4 xyxx, rgrr, stss; + XVec4 xyxy, rgrg, stst; + XVec4 xyyx, rggr, stts; + XVec4 xyyy, rggg, sttt; + XVec4 yxxx, grrr, tsss; + XVec4 yxxy, grrg, tsst; + XVec4 yxyx, grgr, tsts; + XVec4 yxyy, grgg, tstt; + XVec4 yyxx, ggrr, ttss; + XVec4 yyxy, ggrg, ttst; + XVec4 yyyx, gggr, ttts; + XVec4 yyyy, gggg, tttt; + }; +}; + +/* + * 2-element complexes + */ + +template struct Cmplx +{ + inline Cmplx() {} + inline Cmplx(T X) : x(X), y(0) {} + inline Cmplx(T X, T Y) : x(X), y(Y) {} + + DECLARE_MEMBER_OPS(Cmplx) + + inline Cmplx operator *(Cmplx const &val) const + { + return Cmplx(x * val.x - y * val.y, x * val.y + y * val.x); + } + + inline Cmplx operator *=(Cmplx const &val) + { + return *this = (*this) * val; + } + + inline Cmplx operator ~() const + { + return Cmplx(x, -y); + } + + inline T norm() const { return len(*this); } +#if !defined __ANDROID__ + template + friend std::ostream &operator<<(std::ostream &stream, Cmplx const &v); +#endif + + T x, y; +}; + +template +static inline Cmplx re(Cmplx const &val) +{ + return ~val / sqlen(val); +} + +template +static inline Cmplx operator /(T a, Cmplx const &b) +{ + return a * re(b); +} + +template +static inline Cmplx operator /(Cmplx a, Cmplx const &b) +{ + return a * re(b); +} + +template +static inline bool operator ==(Cmplx const &a, T b) +{ + return (a.x == b) && !a.y; +} + +template +static inline bool operator !=(Cmplx const &a, T b) +{ + return (a.x != b) || a.y; +} + +template +static inline bool operator ==(T a, Cmplx const &b) { return b == a; } + +template +static inline bool operator !=(T a, Cmplx const &b) { return b != a; } + +/* + * 3-element vectors + */ + +template struct Vec3 +{ + inline Vec3() {} + inline Vec3(T X, T Y, T Z) : x(X), y(Y), z(Z) {} + inline Vec3(Vec2 XY, T Z) : x(XY.x), y(XY.y), z(Z) {} + inline Vec3(T X, Vec2 YZ) : x(X), y(YZ.x), z(YZ.y) {} + + explicit inline Vec3(T X) : x(X), y(X), z(X) {} + + template + inline Vec3(XVec3 const &v) + : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]) {} + + template + explicit inline Vec3(XVec3 const &v) + : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]) {} + + DECLARE_MEMBER_OPS(Vec3) + + template + friend Vec3 cross(Vec3, Vec3); + +#if !defined __ANDROID__ + template + friend std::ostream &operator<<(std::ostream &stream, Vec3 const &v); +#endif + + union + { + struct { T x, y, z; }; + struct { T r, g, b; }; + struct { T s, t, p; }; + + XVec2 xx, rr, ss; + XVec2 xy, rg, st; + XVec2 xz, rb, sp; + XVec2 yx, gr, ts; + XVec2 yy, gg, tt; + XVec2 yz, gb, tp; + XVec2 zx, br, ps; + XVec2 zy, bg, pt; + XVec2 zz, bb, pp; + + XVec3 xxx, rrr, sss; + XVec3 xxy, rrg, sst; + XVec3 xxz, rrb, ssp; + XVec3 xyx, rgr, sts; + XVec3 xyy, rgg, stt; + XVec3 xyz, rgb, stp; + XVec3 xzx, rbr, sps; + XVec3 xzy, rbg, spt; + XVec3 xzz, rbb, spp; + XVec3 yxx, grr, tss; + XVec3 yxy, grg, tst; + XVec3 yxz, grb, tsp; + XVec3 yyx, ggr, tts; + XVec3 yyy, ggg, ttt; + XVec3 yyz, ggb, ttp; + XVec3 yzx, gbr, tps; + XVec3 yzy, gbg, tpt; + XVec3 yzz, gbb, tpp; + XVec3 zxx, brr, pss; + XVec3 zxy, brg, pst; + XVec3 zxz, brb, psp; + XVec3 zyx, bgr, pts; + XVec3 zyy, bgg, ptt; + XVec3 zyz, bgb, ptp; + XVec3 zzx, bbr, pps; + XVec3 zzy, bbg, ppt; + XVec3 zzz, bbb, ppp; + + XVec4 xxxx, rrrr, ssss; + XVec4 xxxy, rrrg, ssst; + XVec4 xxxz, rrrb, sssp; + XVec4 xxyx, rrgr, ssts; + XVec4 xxyy, rrgg, sstt; + XVec4 xxyz, rrgb, sstp; + XVec4 xxzx, rrbr, ssps; + XVec4 xxzy, rrbg, sspt; + XVec4 xxzz, rrbb, sspp; + XVec4 xyxx, rgrr, stss; + XVec4 xyxy, rgrg, stst; + XVec4 xyxz, rgrb, stsp; + XVec4 xyyx, rggr, stts; + XVec4 xyyy, rggg, sttt; + XVec4 xyyz, rggb, sttp; + XVec4 xyzx, rgbr, stps; + XVec4 xyzy, rgbg, stpt; + XVec4 xyzz, rgbb, stpp; + XVec4 xzxx, rbrr, spss; + XVec4 xzxy, rbrg, spst; + XVec4 xzxz, rbrb, spsp; + XVec4 xzyx, rbgr, spts; + XVec4 xzyy, rbgg, sptt; + XVec4 xzyz, rbgb, sptp; + XVec4 xzzx, rbbr, spps; + XVec4 xzzy, rbbg, sppt; + XVec4 xzzz, rbbb, sppp; + XVec4 yxxx, grrr, tsss; + XVec4 yxxy, grrg, tsst; + XVec4 yxxz, grrb, tssp; + XVec4 yxyx, grgr, tsts; + XVec4 yxyy, grgg, tstt; + XVec4 yxyz, grgb, tstp; + XVec4 yxzx, grbr, tsps; + XVec4 yxzy, grbg, tspt; + XVec4 yxzz, grbb, tspp; + XVec4 yyxx, ggrr, ttss; + XVec4 yyxy, ggrg, ttst; + XVec4 yyxz, ggrb, ttsp; + XVec4 yyyx, gggr, ttts; + XVec4 yyyy, gggg, tttt; + XVec4 yyyz, gggb, tttp; + XVec4 yyzx, ggbr, ttps; + XVec4 yyzy, ggbg, ttpt; + XVec4 yyzz, ggbb, ttpp; + XVec4 yzxx, gbrr, tpss; + XVec4 yzxy, gbrg, tpst; + XVec4 yzxz, gbrb, tpsp; + XVec4 yzyx, gbgr, tpts; + XVec4 yzyy, gbgg, tptt; + XVec4 yzyz, gbgb, tptp; + XVec4 yzzx, gbbr, tpps; + XVec4 yzzy, gbbg, tppt; + XVec4 yzzz, gbbb, tppp; + XVec4 zxxx, brrr, psss; + XVec4 zxxy, brrg, psst; + XVec4 zxxz, brrb, pssp; + XVec4 zxyx, brgr, psts; + XVec4 zxyy, brgg, pstt; + XVec4 zxyz, brgb, pstp; + XVec4 zxzx, brbr, psps; + XVec4 zxzy, brbg, pspt; + XVec4 zxzz, brbb, pspp; + XVec4 zyxx, bgrr, ptss; + XVec4 zyxy, bgrg, ptst; + XVec4 zyxz, bgrb, ptsp; + XVec4 zyyx, bggr, ptts; + XVec4 zyyy, bggg, pttt; + XVec4 zyyz, bggb, pttp; + XVec4 zyzx, bgbr, ptps; + XVec4 zyzy, bgbg, ptpt; + XVec4 zyzz, bgbb, ptpp; + XVec4 zzxx, bbrr, ppss; + XVec4 zzxy, bbrg, ppst; + XVec4 zzxz, bbrb, ppsp; + XVec4 zzyx, bbgr, ppts; + XVec4 zzyy, bbgg, pptt; + XVec4 zzyz, bbgb, pptp; + XVec4 zzzx, bbbr, ppps; + XVec4 zzzy, bbbg, pppt; + XVec4 zzzz, bbbb, pppp; + }; +}; + +/* + * 4-element vectors + */ + +template struct Vec4 +{ + inline Vec4() {} + inline Vec4(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {} + inline Vec4(Vec2 XY, T Z, T W) : x(XY.x), y(XY.y), z(Z), w(W) {} + inline Vec4(T X, Vec2 YZ, T W) : x(X), y(YZ.x), z(YZ.y), w(W) {} + inline Vec4(T X, T Y, Vec2 ZW) : x(X), y(Y), z(ZW.x), w(ZW.y) {} + inline Vec4(Vec2 XY, Vec2 ZW) : x(XY.x), y(XY.y), z(ZW.x), w(ZW.y) {} + inline Vec4(Vec3 XYZ, T W) : x(XYZ.x), y(XYZ.y), z(XYZ.z), w(W) {} + inline Vec4(T X, Vec3 YZW) : x(X), y(YZW.x), z(YZW.y), w(YZW.z) {} + + explicit inline Vec4(T X) : x(X), y(X), z(X), w(X) {} + + template + inline Vec4(XVec4 const &v) + : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]), w(v.ptr[v.L]) {} + + template + explicit inline Vec4(XVec4 const &v) + : x(v.ptr[v.I]), y(v.ptr[v.J]), z(v.ptr[v.K]), w(v.ptr[v.L]) {} + + DECLARE_MEMBER_OPS(Vec4) + +#if !defined __ANDROID__ + template + friend std::ostream &operator<<(std::ostream &stream, Vec4 const &v); +#endif + + union + { + struct { T x, y, z, w; }; + struct { T r, g, b, a; }; + struct { T s, t, p, q; }; + + XVec2 xx, rr, ss; + XVec2 xy, rg, st; + XVec2 xz, rb, sp; + XVec2 xw, ra, sq; + XVec2 yx, gr, ts; + XVec2 yy, gg, tt; + XVec2 yz, gb, tp; + XVec2 yw, ga, tq; + XVec2 zx, br, ps; + XVec2 zy, bg, pt; + XVec2 zz, bb, pp; + XVec2 zw, ba, pq; + XVec2 wx, ar, qs; + XVec2 wy, ag, qt; + XVec2 wz, ab, qp; + XVec2 ww, aa, qq; + + XVec3 xxx, rrr, sss; + XVec3 xxy, rrg, sst; + XVec3 xxz, rrb, ssp; + XVec3 xxw, rra, ssq; + XVec3 xyx, rgr, sts; + XVec3 xyy, rgg, stt; + XVec3 xyz, rgb, stp; + XVec3 xyw, rga, stq; + XVec3 xzx, rbr, sps; + XVec3 xzy, rbg, spt; + XVec3 xzz, rbb, spp; + XVec3 xzw, rba, spq; + XVec3 xwx, rar, sqs; + XVec3 xwy, rag, sqt; + XVec3 xwz, rab, sqp; + XVec3 xww, raa, sqq; + XVec3 yxx, grr, tss; + XVec3 yxy, grg, tst; + XVec3 yxz, grb, tsp; + XVec3 yxw, gra, tsq; + XVec3 yyx, ggr, tts; + XVec3 yyy, ggg, ttt; + XVec3 yyz, ggb, ttp; + XVec3 yyw, gga, ttq; + XVec3 yzx, gbr, tps; + XVec3 yzy, gbg, tpt; + XVec3 yzz, gbb, tpp; + XVec3 yzw, gba, tpq; + XVec3 ywx, gar, tqs; + XVec3 ywy, gag, tqt; + XVec3 ywz, gab, tqp; + XVec3 yww, gaa, tqq; + XVec3 zxx, brr, pss; + XVec3 zxy, brg, pst; + XVec3 zxz, brb, psp; + XVec3 zxw, bra, psq; + XVec3 zyx, bgr, pts; + XVec3 zyy, bgg, ptt; + XVec3 zyz, bgb, ptp; + XVec3 zyw, bga, ptq; + XVec3 zzx, bbr, pps; + XVec3 zzy, bbg, ppt; + XVec3 zzz, bbb, ppp; + XVec3 zzw, bba, ppq; + XVec3 zwx, bar, pqs; + XVec3 zwy, bag, pqt; + XVec3 zwz, bab, pqp; + XVec3 zww, baa, pqq; + XVec3 wxx, arr, qss; + XVec3 wxy, arg, qst; + XVec3 wxz, arb, qsp; + XVec3 wxw, ara, qsq; + XVec3 wyx, agr, qts; + XVec3 wyy, agg, qtt; + XVec3 wyz, agb, qtp; + XVec3 wyw, aga, qtq; + XVec3 wzx, abr, qps; + XVec3 wzy, abg, qpt; + XVec3 wzz, abb, qpp; + XVec3 wzw, aba, qpq; + XVec3 wwx, aar, qqs; + XVec3 wwy, aag, qqt; + XVec3 wwz, aab, qqp; + XVec3 www, aaa, qqq; + + XVec4 xxxx, rrrr, ssss; + XVec4 xxxy, rrrg, ssst; + XVec4 xxxz, rrrb, sssp; + XVec4 xxxw, rrra, sssq; + XVec4 xxyx, rrgr, ssts; + XVec4 xxyy, rrgg, sstt; + XVec4 xxyz, rrgb, sstp; + XVec4 xxyw, rrga, sstq; + XVec4 xxzx, rrbr, ssps; + XVec4 xxzy, rrbg, sspt; + XVec4 xxzz, rrbb, sspp; + XVec4 xxzw, rrba, sspq; + XVec4 xxwx, rrar, ssqs; + XVec4 xxwy, rrag, ssqt; + XVec4 xxwz, rrab, ssqp; + XVec4 xxww, rraa, ssqq; + XVec4 xyxx, rgrr, stss; + XVec4 xyxy, rgrg, stst; + XVec4 xyxz, rgrb, stsp; + XVec4 xyxw, rgra, stsq; + XVec4 xyyx, rggr, stts; + XVec4 xyyy, rggg, sttt; + XVec4 xyyz, rggb, sttp; + XVec4 xyyw, rgga, sttq; + XVec4 xyzx, rgbr, stps; + XVec4 xyzy, rgbg, stpt; + XVec4 xyzz, rgbb, stpp; + XVec4 xyzw, rgba, stpq; + XVec4 xywx, rgar, stqs; + XVec4 xywy, rgag, stqt; + XVec4 xywz, rgab, stqp; + XVec4 xyww, rgaa, stqq; + XVec4 xzxx, rbrr, spss; + XVec4 xzxy, rbrg, spst; + XVec4 xzxz, rbrb, spsp; + XVec4 xzxw, rbra, spsq; + XVec4 xzyx, rbgr, spts; + XVec4 xzyy, rbgg, sptt; + XVec4 xzyz, rbgb, sptp; + XVec4 xzyw, rbga, sptq; + XVec4 xzzx, rbbr, spps; + XVec4 xzzy, rbbg, sppt; + XVec4 xzzz, rbbb, sppp; + XVec4 xzzw, rbba, sppq; + XVec4 xzwx, rbar, spqs; + XVec4 xzwy, rbag, spqt; + XVec4 xzwz, rbab, spqp; + XVec4 xzww, rbaa, spqq; + XVec4 xwxx, rarr, sqss; + XVec4 xwxy, rarg, sqst; + XVec4 xwxz, rarb, sqsp; + XVec4 xwxw, rara, sqsq; + XVec4 xwyx, ragr, sqts; + XVec4 xwyy, ragg, sqtt; + XVec4 xwyz, ragb, sqtp; + XVec4 xwyw, raga, sqtq; + XVec4 xwzx, rabr, sqps; + XVec4 xwzy, rabg, sqpt; + XVec4 xwzz, rabb, sqpp; + XVec4 xwzw, raba, sqpq; + XVec4 xwwx, raar, sqqs; + XVec4 xwwy, raag, sqqt; + XVec4 xwwz, raab, sqqp; + XVec4 xwww, raaa, sqqq; + XVec4 yxxx, grrr, tsss; + XVec4 yxxy, grrg, tsst; + XVec4 yxxz, grrb, tssp; + XVec4 yxxw, grra, tssq; + XVec4 yxyx, grgr, tsts; + XVec4 yxyy, grgg, tstt; + XVec4 yxyz, grgb, tstp; + XVec4 yxyw, grga, tstq; + XVec4 yxzx, grbr, tsps; + XVec4 yxzy, grbg, tspt; + XVec4 yxzz, grbb, tspp; + XVec4 yxzw, grba, tspq; + XVec4 yxwx, grar, tsqs; + XVec4 yxwy, grag, tsqt; + XVec4 yxwz, grab, tsqp; + XVec4 yxww, graa, tsqq; + XVec4 yyxx, ggrr, ttss; + XVec4 yyxy, ggrg, ttst; + XVec4 yyxz, ggrb, ttsp; + XVec4 yyxw, ggra, ttsq; + XVec4 yyyx, gggr, ttts; + XVec4 yyyy, gggg, tttt; + XVec4 yyyz, gggb, tttp; + XVec4 yyyw, ggga, tttq; + XVec4 yyzx, ggbr, ttps; + XVec4 yyzy, ggbg, ttpt; + XVec4 yyzz, ggbb, ttpp; + XVec4 yyzw, ggba, ttpq; + XVec4 yywx, ggar, ttqs; + XVec4 yywy, ggag, ttqt; + XVec4 yywz, ggab, ttqp; + XVec4 yyww, ggaa, ttqq; + XVec4 yzxx, gbrr, tpss; + XVec4 yzxy, gbrg, tpst; + XVec4 yzxz, gbrb, tpsp; + XVec4 yzxw, gbra, tpsq; + XVec4 yzyx, gbgr, tpts; + XVec4 yzyy, gbgg, tptt; + XVec4 yzyz, gbgb, tptp; + XVec4 yzyw, gbga, tptq; + XVec4 yzzx, gbbr, tpps; + XVec4 yzzy, gbbg, tppt; + XVec4 yzzz, gbbb, tppp; + XVec4 yzzw, gbba, tppq; + XVec4 yzwx, gbar, tpqs; + XVec4 yzwy, gbag, tpqt; + XVec4 yzwz, gbab, tpqp; + XVec4 yzww, gbaa, tpqq; + XVec4 ywxx, garr, tqss; + XVec4 ywxy, garg, tqst; + XVec4 ywxz, garb, tqsp; + XVec4 ywxw, gara, tqsq; + XVec4 ywyx, gagr, tqts; + XVec4 ywyy, gagg, tqtt; + XVec4 ywyz, gagb, tqtp; + XVec4 ywyw, gaga, tqtq; + XVec4 ywzx, gabr, tqps; + XVec4 ywzy, gabg, tqpt; + XVec4 ywzz, gabb, tqpp; + XVec4 ywzw, gaba, tqpq; + XVec4 ywwx, gaar, tqqs; + XVec4 ywwy, gaag, tqqt; + XVec4 ywwz, gaab, tqqp; + XVec4 ywww, gaaa, tqqq; + XVec4 zxxx, brrr, psss; + XVec4 zxxy, brrg, psst; + XVec4 zxxz, brrb, pssp; + XVec4 zxxw, brra, pssq; + XVec4 zxyx, brgr, psts; + XVec4 zxyy, brgg, pstt; + XVec4 zxyz, brgb, pstp; + XVec4 zxyw, brga, pstq; + XVec4 zxzx, brbr, psps; + XVec4 zxzy, brbg, pspt; + XVec4 zxzz, brbb, pspp; + XVec4 zxzw, brba, pspq; + XVec4 zxwx, brar, psqs; + XVec4 zxwy, brag, psqt; + XVec4 zxwz, brab, psqp; + XVec4 zxww, braa, psqq; + XVec4 zyxx, bgrr, ptss; + XVec4 zyxy, bgrg, ptst; + XVec4 zyxz, bgrb, ptsp; + XVec4 zyxw, bgra, ptsq; + XVec4 zyyx, bggr, ptts; + XVec4 zyyy, bggg, pttt; + XVec4 zyyz, bggb, pttp; + XVec4 zyyw, bgga, pttq; + XVec4 zyzx, bgbr, ptps; + XVec4 zyzy, bgbg, ptpt; + XVec4 zyzz, bgbb, ptpp; + XVec4 zyzw, bgba, ptpq; + XVec4 zywx, bgar, ptqs; + XVec4 zywy, bgag, ptqt; + XVec4 zywz, bgab, ptqp; + XVec4 zyww, bgaa, ptqq; + XVec4 zzxx, bbrr, ppss; + XVec4 zzxy, bbrg, ppst; + XVec4 zzxz, bbrb, ppsp; + XVec4 zzxw, bbra, ppsq; + XVec4 zzyx, bbgr, ppts; + XVec4 zzyy, bbgg, pptt; + XVec4 zzyz, bbgb, pptp; + XVec4 zzyw, bbga, pptq; + XVec4 zzzx, bbbr, ppps; + XVec4 zzzy, bbbg, pppt; + XVec4 zzzz, bbbb, pppp; + XVec4 zzzw, bbba, pppq; + XVec4 zzwx, bbar, ppqs; + XVec4 zzwy, bbag, ppqt; + XVec4 zzwz, bbab, ppqp; + XVec4 zzww, bbaa, ppqq; + XVec4 zwxx, barr, pqss; + XVec4 zwxy, barg, pqst; + XVec4 zwxz, barb, pqsp; + XVec4 zwxw, bara, pqsq; + XVec4 zwyx, bagr, pqts; + XVec4 zwyy, bagg, pqtt; + XVec4 zwyz, bagb, pqtp; + XVec4 zwyw, baga, pqtq; + XVec4 zwzx, babr, pqps; + XVec4 zwzy, babg, pqpt; + XVec4 zwzz, babb, pqpp; + XVec4 zwzw, baba, pqpq; + XVec4 zwwx, baar, pqqs; + XVec4 zwwy, baag, pqqt; + XVec4 zwwz, baab, pqqp; + XVec4 zwww, baaa, pqqq; + XVec4 wxxx, arrr, qsss; + XVec4 wxxy, arrg, qsst; + XVec4 wxxz, arrb, qssp; + XVec4 wxxw, arra, qssq; + XVec4 wxyx, argr, qsts; + XVec4 wxyy, argg, qstt; + XVec4 wxyz, argb, qstp; + XVec4 wxyw, arga, qstq; + XVec4 wxzx, arbr, qsps; + XVec4 wxzy, arbg, qspt; + XVec4 wxzz, arbb, qspp; + XVec4 wxzw, arba, qspq; + XVec4 wxwx, arar, qsqs; + XVec4 wxwy, arag, qsqt; + XVec4 wxwz, arab, qsqp; + XVec4 wxww, araa, qsqq; + XVec4 wyxx, agrr, qtss; + XVec4 wyxy, agrg, qtst; + XVec4 wyxz, agrb, qtsp; + XVec4 wyxw, agra, qtsq; + XVec4 wyyx, aggr, qtts; + XVec4 wyyy, aggg, qttt; + XVec4 wyyz, aggb, qttp; + XVec4 wyyw, agga, qttq; + XVec4 wyzx, agbr, qtps; + XVec4 wyzy, agbg, qtpt; + XVec4 wyzz, agbb, qtpp; + XVec4 wyzw, agba, qtpq; + XVec4 wywx, agar, qtqs; + XVec4 wywy, agag, qtqt; + XVec4 wywz, agab, qtqp; + XVec4 wyww, agaa, qtqq; + XVec4 wzxx, abrr, qpss; + XVec4 wzxy, abrg, qpst; + XVec4 wzxz, abrb, qpsp; + XVec4 wzxw, abra, qpsq; + XVec4 wzyx, abgr, qpts; + XVec4 wzyy, abgg, qptt; + XVec4 wzyz, abgb, qptp; + XVec4 wzyw, abga, qptq; + XVec4 wzzx, abbr, qpps; + XVec4 wzzy, abbg, qppt; + XVec4 wzzz, abbb, qppp; + XVec4 wzzw, abba, qppq; + XVec4 wzwx, abar, qpqs; + XVec4 wzwy, abag, qpqt; + XVec4 wzwz, abab, qpqp; + XVec4 wzww, abaa, qpqq; + XVec4 wwxx, aarr, qqss; + XVec4 wwxy, aarg, qqst; + XVec4 wwxz, aarb, qqsp; + XVec4 wwxw, aara, qqsq; + XVec4 wwyx, aagr, qqts; + XVec4 wwyy, aagg, qqtt; + XVec4 wwyz, aagb, qqtp; + XVec4 wwyw, aaga, qqtq; + XVec4 wwzx, aabr, qqps; + XVec4 wwzy, aabg, qqpt; + XVec4 wwzz, aabb, qqpp; + XVec4 wwzw, aaba, qqpq; + XVec4 wwwx, aaar, qqqs; + XVec4 wwwy, aaag, qqqt; + XVec4 wwwz, aaab, qqqp; + XVec4 wwww, aaaa, qqqq; + }; +}; + +/* + * 4-element quaternions + */ + +template struct Quat +{ + inline Quat() {} + inline Quat(T X) : x(0), y(0), z(0), w(X) {} + inline Quat(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {} + + Quat(Mat4 const &m); + + DECLARE_MEMBER_OPS(Quat) + + inline Quat operator *(Quat const &val) const + { + Quat ret; + Vec3 v1(x, y, z); + Vec3 v2(val.x, val.y, val.z); + Vec3 v3 = cross(v1, v2) + w * v2 + val.w * v1; + return Quat(v3.x, v3.y, v3.z, w * val.w - dot(v1, v2)); + } + + inline Quat operator *=(Quat const &val) + { + return *this = (*this) * val; + } + + inline Quat operator ~() const + { + return Quat(-x, -y, -z, w); + } + +#if !defined __ANDROID__ + template + friend std::ostream &operator<<(std::ostream &stream, Quat const &v); +#endif + + T x, y, z, w; +}; + +template +inline T norm(Quat const &val) +{ + return sqlen(val); +} + +template +static inline Quat re(Quat const &val) +{ + return ~val / norm(val); +} + +template +static inline Quat operator /(T x, Quat const &y) +{ + return x * re(y); +} + +template +static inline Quat operator /(Quat x, Quat const &y) +{ + return x * re(y); +} + +/* + * Common operators for all vector types, including quaternions + */ + +#define DECLARE_VECTOR_OP(tname, op, tprefix, T) \ + tprefix \ + static inline tname operator op(tname const &a, tname const &b) \ + { \ + tname ret; \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + ret[n] = a[n] op b[n]; \ + return ret; \ + } \ + \ + tprefix \ + static inline tname operator op##=(tname &a, tname const &b) \ + { \ + return a = a op b; \ + } + +#define DECLARE_BOOL_OP(tname, op, op2, ret, tprefix, T) \ + tprefix \ + static inline bool operator op(tname const &a, tname const &b) \ + { \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + if (!(a[n] op2 b[n])) \ + return !ret; \ + return ret; \ + } + +#define DECLARE_SCALAR_OP(tname, op, tprefix, T) \ + tprefix \ + static inline tname operator op(tname const &a, T const &val) \ + { \ + tname ret; \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + ret[n] = a[n] op val; \ + return ret; \ + } \ + \ + tprefix \ + static inline tname operator op(T const &val, tname const &a) \ + { \ + tname ret; \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + ret[n] = a[n] op val; \ + return ret; \ + } \ + \ + tprefix \ + static inline tname operator op##=(tname &a, T const &val) \ + { \ + return a = a op val; \ + } + +/* FIXME: this is not used yet */ +#define SCALAR_PROMOTE_OP(tname, op, U) \ + template \ + static inline tname operator op(U const &val, tname const &a) \ + { \ + tname ret; \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + ret[n] = val op a[n]; \ + return ret; \ + } + +#define DECLARE_ALL_GLOBAL_OPS(tname, tprefix, T) \ + DECLARE_SCALAR_OP(tname, *, tprefix, T) \ + DECLARE_SCALAR_OP(tname, /, tprefix, T) \ + \ + DECLARE_VECTOR_OP(tname, -, tprefix, T) \ + DECLARE_VECTOR_OP(tname, +, tprefix, T) \ + \ + DECLARE_BOOL_OP(tname, ==, ==, true, tprefix, T) \ + DECLARE_BOOL_OP(tname, !=, ==, false, tprefix, T) \ + \ + tprefix \ + static inline tname operator -(tname const &a) \ + { \ + tname ret; \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + ret[n] = -a[n]; \ + return ret; \ + } \ + \ + tprefix \ + static inline T sqlen(tname const &a) \ + { \ + T acc = 0; \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + acc += a[n] * a[n]; \ + return acc; \ + } \ + \ + tprefix \ + static inline double len(tname const &a) \ + { \ + using namespace std; \ + return sqrt((double)sqlen(a)); \ + } \ + \ + tprefix \ + static inline T dot(tname const &a, tname const &b) \ + { \ + T ret = 0; \ + for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \ + ret += a[n] * b[n]; \ + return ret; \ + } \ + \ + tprefix \ + static inline tname normalize(tname const &val) \ + { \ + T norm = len(val); \ + return norm ? val / norm : val * (T)0; \ + } + +#define DECLARE_GLOBAL_TEMPLATE_OPS(tname) \ + DECLARE_ALL_GLOBAL_OPS(tname, template, T) + +#define DECLARE_ALL_GLOBAL_OPS(tname, tprefix, T) \ + DECLARE_VECTOR_OP(tname, *, tprefix, T) \ + DECLARE_VECTOR_OP(tname, /, tprefix, T) \ + \ + DECLARE_ALL_GLOBAL_OPS(tname, tprefix, T) \ + \ + DECLARE_BOOL_OP(tname, <=, <=, true, tprefix, T) \ + DECLARE_BOOL_OP(tname, >=, >=, true, tprefix, T) \ + DECLARE_BOOL_OP(tname, <, <, true, tprefix, T) \ + DECLARE_BOOL_OP(tname, >, >, true, tprefix, T) + +/* FIXME: a few problems need to be fixed before we can use "half" here. It + * will probably never work until we switch to C++11 because it's not really + * a POD class. */ +#define DECLARE_GLOBAL_TYPED_OPS(tname) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, float) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, double) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, int8_t) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, uint8_t) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, int16_t) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, uint16_t) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, int32_t) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, uint32_t) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, int64_t) \ + DECLARE_ALL_GLOBAL_OPS(tname, /* empty */, uint64_t) + +DECLARE_GLOBAL_TEMPLATE_OPS(Cmplx) +DECLARE_GLOBAL_TEMPLATE_OPS(Quat) + +DECLARE_GLOBAL_TYPED_OPS(Vec2) +DECLARE_GLOBAL_TYPED_OPS(Vec3) +DECLARE_GLOBAL_TYPED_OPS(Vec4) + +#undef DECLARE_VECTOR_TYPEDEFS +#undef DECLARE_MEMBER_OPS +#undef DECLARE_VECTOR_OP +#undef DECLARE_BOOL_OP +#undef DECLARE_SCALAR_OP +#undef DECLARE_ALL_GLOBAL_OPS +#undef DECLARE_GLOBAL_TEMPLATE_OPS +#undef DECLARE_ALL_GLOBAL_OPS +#undef DECLARE_GLOBAL_TYPED_OPS + +/* + * Magic vector swizzling (part 2/2) + */ + +template +inline Vec2 XVec2::operator =(Vec2 that) +{ + ptr[I] = that[0]; ptr[J] = that[1]; + return *this; +} + +template +inline Vec3 XVec3::operator =(Vec3 that) +{ + ptr[I] = that[0]; ptr[J] = that[1]; ptr[K] = that[2]; + return *this; +} + +template +inline Vec4 XVec4::operator =(Vec4 that) +{ + ptr[I] = that[0]; ptr[J] = that[1]; ptr[K] = that[2]; ptr[L] = that[3]; + return *this; +} + +/* + * 4×4-element matrices + */ + +template struct Mat4 +{ + inline Mat4() {} + inline Mat4(Vec4 V0, Vec4 V1, Vec4 V2, Vec4 V3) + : v0(V0), v1(V1), v2(V2), v3(V3) {} + + explicit inline Mat4(T val) + : v0(val, (T)0, (T)0, (T)0), + v1((T)0, val, (T)0, (T)0), + v2((T)0, (T)0, val, (T)0), + v3((T)0, (T)0, (T)0, val) {} + + inline Vec4& operator[](int n) { return (&v0)[n]; } + inline Vec4 const& operator[](int n) const { return (&v0)[n]; } + + T det() const; + Mat4 invert() const; + + /* Helpers for transformation matrices */ + static Mat4 translate(T x, T y, T z); + static Mat4 translate(Vec3 v); + static Mat4 rotate(T angle, T x, T y, T z); + static Mat4 rotate(T angle, Vec3 v); + static Mat4 rotate(Quat q); + + static inline Mat4 translate(Mat4 mat, Vec3 v) + { + return translate(v) * mat; + } + + static inline Mat4 rotate(Mat4 mat, T angle, Vec3 v) + { + return rotate(angle, v) * mat; + } + + /* Helpers for view matrices */ + static Mat4 lookat(Vec3 eye, Vec3 center, Vec3 up); + + /* Helpers for projection matrices */ + static Mat4 ortho(T left, T right, T bottom, T top, T near, T far); + static Mat4 frustum(T left, T right, T bottom, T top, T near, T far); + static Mat4 perspective(T fov_y, T width, T height, T near, T far); + + void printf() const; + +#if !defined __ANDROID__ + template + friend std::ostream &operator<<(std::ostream &stream, Mat4 const &m); +#endif + + inline Mat4 operator +(Mat4 const m) const + { + return Mat4(v0 + m[0], v1 + m[1], v2 + m[2], v3 + m[3]); + } + + inline Mat4 operator +=(Mat4 const m) + { + return *this = *this + m; + } + + inline Mat4 operator -(Mat4 const m) const + { + return Mat4(v0 - m[0], v1 - m[1], v2 - m[2], v3 - m[3]); + } + + inline Mat4 operator -=(Mat4 const m) + { + return *this = *this - m; + } + + inline Mat4 operator *(Mat4 const m) const + { + return Mat4(*this * m[0], *this * m[1], *this * m[2], *this * m[3]); + } + + inline Mat4 operator *=(Mat4 const m) + { + return *this = *this * m; + } + + inline Vec4 operator *(Vec4 const m) const + { + Vec4 ret; + for (int j = 0; j < 4; j++) + { + T tmp = 0; + for (int k = 0; k < 4; k++) + tmp += (*this)[k][j] * m[k]; + ret[j] = tmp; + } + return ret; + } + + Vec4 v0, v1, v2, v3; +}; + +/* + * Arbitrarily-sized square matrices; for now this only supports + * naive inversion and is used for the Remez inversion method. + */ + +template struct Mat +{ + inline Mat() {} + + Mat(T x) + { + for (int j = 0; j < N; j++) + for (int i = 0; i < N; i++) + if (i == j) + m[i][j] = x; + else + m[i][j] = 0; + } + + /* Naive matrix inversion */ + Mat inv() const + { + Mat a = *this, b((T)1); + + /* Inversion method: iterate through all columns and make sure + * all the terms are 1 on the diagonal and 0 everywhere else */ + for (int i = 0; i < N; i++) + { + /* If the expected coefficient is zero, add one of + * the other lines. The first we meet will do. */ + if (!a.m[i][i]) + { + for (int j = i + 1; j < N; j++) + { + if (!a.m[i][j]) + continue; + /* Add row j to row i */ + for (int n = 0; n < N; n++) + { + a.m[n][i] += a.m[n][j]; + b.m[n][i] += b.m[n][j]; + } + break; + } + } + + /* Now we know the diagonal term is non-zero. Get its inverse + * and use that to nullify all other terms in the column */ + T x = (T)1 / a.m[i][i]; + for (int j = 0; j < N; j++) + { + if (j == i) + continue; + T mul = x * a.m[i][j]; + for (int n = 0; n < N; n++) + { + a.m[n][j] -= mul * a.m[n][i]; + b.m[n][j] -= mul * b.m[n][i]; + } + } + + /* Finally, ensure the diagonal term is 1 */ + for (int n = 0; n < N; n++) + { + a.m[n][i] *= x; + b.m[n][i] *= x; + } + } + + return b; + } + + T m[N][N]; +}; + +} /* namespace lol */ + +#endif // __LOL_MATH_VECTOR_H__ + diff --git a/src/platform/nacl/naclapp.h b/src/platform/nacl/naclapp.h index ddf260a0..477eb204 100644 --- a/src/platform/nacl/naclapp.h +++ b/src/platform/nacl/naclapp.h @@ -16,7 +16,7 @@ #if !defined __LOL_NACLAPP_H__ #define __LOL_NACLAPP_H__ -#include "lol/math/matrix.h" +#include "lol/math/vector.h" namespace lol { diff --git a/src/platform/ps3/ps3app.h b/src/platform/ps3/ps3app.h index 227d3b7e..86b84a04 100644 --- a/src/platform/ps3/ps3app.h +++ b/src/platform/ps3/ps3app.h @@ -16,7 +16,7 @@ #if !defined __LOL_PS3APP_H__ #define __LOL_PS3APP_H__ -#include "lol/math/matrix.h" +#include "lol/math/vector.h" namespace lol { diff --git a/src/platform/sdl/sdlapp.h b/src/platform/sdl/sdlapp.h index 06232042..a7201723 100644 --- a/src/platform/sdl/sdlapp.h +++ b/src/platform/sdl/sdlapp.h @@ -16,7 +16,7 @@ #if !defined __LOL_SDLAPP_H__ #define __LOL_SDLAPP_H__ -#include "lol/math/matrix.h" +#include "lol/math/vector.h" namespace lol { diff --git a/src/matrix.cpp b/src/vector.cpp similarity index 100% rename from src/matrix.cpp rename to src/vector.cpp diff --git a/test/Makefile.am b/test/Makefile.am index 0d275bdb..9805bf53 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -22,14 +22,14 @@ noinst_PROGRAMS = quad benchsuite testsuite TESTS = testsuite testsuite_SOURCES = testsuite.cpp \ - unit/matrix.cpp unit/half.cpp unit/trig.cpp unit/build.cpp \ + unit/vector.cpp unit/half.cpp unit/trig.cpp unit/build.cpp \ unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp testsuite_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ testsuite_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ testsuite_DEPENDENCIES = $(top_builddir)/src/liblol.a benchsuite_SOURCES = benchsuite.cpp \ - benchmark/matrix.cpp benchmark/half.cpp benchmark/trig.cpp \ + benchmark/vector.cpp benchmark/half.cpp benchmark/trig.cpp \ benchmark/real.cpp benchsuite_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ benchsuite_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ diff --git a/test/benchmark/matrix.cpp b/test/benchmark/vector.cpp similarity index 100% rename from test/benchmark/matrix.cpp rename to test/benchmark/vector.cpp diff --git a/test/unit/matrix.cpp b/test/unit/vector.cpp similarity index 98% rename from test/unit/matrix.cpp rename to test/unit/vector.cpp index 1d59a6ab..b068bce2 100644 --- a/test/unit/matrix.cpp +++ b/test/unit/vector.cpp @@ -1,7 +1,7 @@ // // Lol Engine // -// Copyright: (c) 2010-2011 Sam Hocevar +// Copyright: (c) 2010-2012 Sam Hocevar // This program is free software; you can redistribute it and/or // modify it under the terms of the Do What The Fuck You Want To // Public License, Version 2, as published by Sam Hocevar. See @@ -18,7 +18,7 @@ namespace lol { -LOLUNIT_FIXTURE(MatrixTest) +LOLUNIT_FIXTURE(VectorTest) { void SetUp() {