1 struct vec;
2 struct vec4;
3 
4 struct vec2
5 {
6     union
7     {
8         struct { float x, y; };
9         float v[2];
10     };
11 
vec2vec212     vec2() {}
vec2vec213     vec2(float x, float y) : x(x), y(y) {}
14     explicit vec2(const vec &v);
15     explicit vec2(const vec4 &v);
16 
17     float &operator[](int i)       { return v[i]; }
18     float  operator[](int i) const { return v[i]; }
19 
20     bool operator==(const vec2 &o) const { return x == o.x && y == o.y; }
21     bool operator!=(const vec2 &o) const { return x != o.x || y != o.y; }
22 
iszerovec223     bool iszero() const { return x==0 && y==0; }
dotvec224     float dot(const vec2 &o) const  { return x*o.x + y*o.y; }
squaredlenvec225     float squaredlen() const { return dot(*this); }
magnitudevec226     float magnitude() const  { return sqrtf(squaredlen()); }
normalizevec227     vec2 &normalize() { mul(1/magnitude()); return *this; }
crossvec228     float cross(const vec2 &o) const { return x*o.y - y*o.x; }
squaredistvec229     float squaredist(const vec2 &e) const { return vec2(*this).sub(e).squaredlen(); }
distvec230     float dist(const vec2 &e) const { return sqrtf(squaredist(e)); }
31 
mulvec232     vec2 &mul(float f)       { x *= f; y *= f; return *this; }
mulvec233     vec2 &mul(const vec2 &o) { x *= o.x; y *= o.y; return *this; }
squarevec234     vec2 &square()           { mul(*this); return *this; }
divvec235     vec2 &div(float f)       { x /= f; y /= f; return *this; }
divvec236     vec2 &div(const vec2 &o) { x /= o.x; y /= o.y; return *this; }
recipvec237     vec2 &recip()            { x = 1/x; y = 1/y; return *this; }
addvec238     vec2 &add(float f)       { x += f; y += f; return *this; }
addvec239     vec2 &add(const vec2 &o) { x += o.x; y += o.y; return *this; }
subvec240     vec2 &sub(float f)       { x -= f; y -= f; return *this; }
subvec241     vec2 &sub(const vec2 &o) { x -= o.x; y -= o.y; return *this; }
negvec242     vec2 &neg()              { x = -x; y = -y; return *this; }
minvec243     vec2 &min(const vec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; }
maxvec244     vec2 &max(const vec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; }
minvec245     vec2 &min(float f)       { x = ::min(x, f); y = ::min(y, f); return *this; }
maxvec246     vec2 &max(float f)       { x = ::max(x, f); y = ::max(y, f); return *this; }
absvec247     vec2 &abs() { x = fabs(x); y = fabs(y); return *this; }
clampvec248     vec2 &clamp(float l, float h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); return *this; }
reflectvec249     vec2 &reflect(const vec2 &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; return *this; }
lerpvec250     vec2 &lerp(const vec2 &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; return *this; }
lerpvec251     vec2 &lerp(const vec2 &a, const vec2 &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; return *this; }
avgvec252     vec2 &avg(const vec2 &b) { add(b); mul(0.5f); return *this; }
maddvec253     template<class B> vec2 &madd(const vec2 &a, const B &b) { return add(vec2(a).mul(b)); }
msubvec254     template<class B> vec2 &msub(const vec2 &a, const B &b) { return sub(vec2(a).mul(b)); }
55 
rotate_around_zvec256     vec2 &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
rotate_around_zvec257     vec2 &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
rotate_around_zvec258     vec2 &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
59 };
60 
htcmp(const vec2 & x,const vec2 & y)61 static inline bool htcmp(const vec2 &x, const vec2 &y)
62 {
63     return x == y;
64 }
65 
hthash(const vec2 & k)66 static inline uint hthash(const vec2 &k)
67 {
68     union { uint i; float f; } x, y;
69     x.f = k.x; y.f = k.y;
70     uint v = x.i^y.i;
71     return v + (v>>12);
72 }
73 
74 struct ivec;
75 struct usvec;
76 struct svec;
77 
78 struct vec
79 {
80     union
81     {
82         struct { float x, y, z; };
83         struct { float r, g, b; };
84         float v[3];
85     };
86 
vecvec87     vec() {}
vecvec88     explicit vec(int a) : x(a), y(a), z(a) {}
vecvec89     explicit vec(float a) : x(a), y(a), z(a) {}
vecvec90     vec(float a, float b, float c) : x(a), y(b), z(c) {}
vecvec91     explicit vec(int v[3]) : x(v[0]), y(v[1]), z(v[2]) {}
vecvec92     explicit vec(const float *v) : x(v[0]), y(v[1]), z(v[2]) {}
93     explicit vec(const vec2 &v, float z = 0) : x(v.x), y(v.y), z(z) {}
94     explicit vec(const vec4 &v);
95     explicit vec(const ivec &v);
96     explicit vec(const usvec &v);
97     explicit vec(const svec &v);
98 
vecvec99     vec(float yaw, float pitch) : x(-sinf(yaw)*cosf(pitch)), y(cosf(yaw)*cosf(pitch)), z(sinf(pitch)) {}
100 
101     float &operator[](int i)       { return v[i]; }
102     float  operator[](int i) const { return v[i]; }
103 
setvec104     vec &set(int i, float f) { v[i] = f; return *this; }
105 
106     bool operator==(const vec &o) const { return x == o.x && y == o.y && z == o.z; }
107     bool operator!=(const vec &o) const { return x != o.x || y != o.y || z != o.z; }
108 
iszerovec109     bool iszero() const { return x==0 && y==0 && z==0; }
squaredlenvec110     float squaredlen() const { return x*x + y*y + z*z; }
dot2vec111     float dot2(const vec2 &o) const { return x*o.x + y*o.y; }
dot2vec112     float dot2(const vec &o) const { return x*o.x + y*o.y; }
dotvec113     float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
squaredotvec114     float squaredot(const vec &o) const { float k = dot(o); return k*k; }
absdotvec115     float absdot(const vec &o) const { return fabs(x*o.x) + fabs(y*o.y) + fabs(z*o.z); }
zdotvec116     float zdot(const vec &o) const { return z*o.z; }
mulvec117     vec &mul(const vec &o)   { x *= o.x; y *= o.y; z *= o.z; return *this; }
mulvec118     vec &mul(float f)        { x *= f; y *= f; z *= f; return *this; }
squarevec119     vec &square()            { mul(*this); return *this; }
divvec120     vec &div(const vec &o)   { x /= o.x; y /= o.y; z /= o.z; return *this; }
divvec121     vec &div(float f)        { x /= f; y /= f; z /= f; return *this; }
recipvec122     vec &recip()             { x = 1/x; y = 1/y; z = 1/z; return *this; }
addvec123     vec &add(const vec &o)   { x += o.x; y += o.y; z += o.z; return *this; }
addvec124     vec &add(float f)        { x += f; y += f; z += f; return *this; }
addzvec125     vec &addz(float f)       { z += f; return *this; }
subvec126     vec &sub(const vec &o)   { x -= o.x; y -= o.y; z -= o.z; return *this; }
subvec127     vec &sub(float f)        { x -= f; y -= f; z -= f; return *this; }
subzvec128     vec &subz(float f)       { z -= f; return *this; }
neg2vec129     vec &neg2()              { x = -x; y = -y; return *this; }
negvec130     vec &neg()               { x = -x; y = -y; z = -z; return *this; }
minvec131     vec &min(const vec &o)   { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
maxvec132     vec &max(const vec &o)   { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
minvec133     vec &min(float f)        { x = ::min(x, f); y = ::min(y, f); z = ::min(z, f); return *this; }
maxvec134     vec &max(float f)        { x = ::max(x, f); y = ::max(y, f); z = ::max(z, f); return *this; }
absvec135     vec &abs() { x = fabs(x); y = fabs(y); z = fabs(z); return *this; }
clampvec136     vec &clamp(float l, float h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); z = ::clamp(z, l, h); return *this; }
magnitude2vec137     float magnitude2() const { return sqrtf(dot2(*this)); }
magnitudevec138     float magnitude() const  { return sqrtf(squaredlen()); }
normalizevec139     vec &normalize()         { div(magnitude()); return *this; }
isnormalizedvec140     bool isnormalized() const { float m = squaredlen(); return (m>0.99f && m<1.01f); }
squaredistvec141     float squaredist(const vec &e) const { return vec(*this).sub(e).squaredlen(); }
distvec142     float dist(const vec &e) const { return sqrtf(squaredist(e)); }
distvec143     float dist(const vec &e, vec &t) const { t = *this; t.sub(e); return t.magnitude(); }
dist2vec144     float dist2(const vec &o) const { float dx = x-o.x, dy = y-o.y; return sqrtf(dx*dx + dy*dy); }
145     template<class T>
rejectvec146     bool reject(const T &o, float r) { return x>o.x+r || x<o.x-r || y>o.y+r || y<o.y-r; }
147     template<class A, class B>
crossvec148     vec &cross(const A &a, const B &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
crossvec149     vec &cross(const vec &o, const vec &a, const vec &b) { return cross(vec(a).sub(o), vec(b).sub(o)); }
scalartriplevec150     float scalartriple(const vec &a, const vec &b) const { return x*(a.y*b.z-a.z*b.y) + y*(a.z*b.x-a.x*b.z) + z*(a.x*b.y-a.y*b.x); }
zscalartriplevec151     float zscalartriple(const vec &a, const vec &b) const { return z*(a.x*b.y-a.y*b.x); }
reflectzvec152     vec &reflectz(float rz) { z = 2*rz - z; return *this; }
reflectvec153     vec &reflect(const vec &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
projectvec154     vec &project(const vec &n) { float k = dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
projectxydirvec155     vec &projectxydir(const vec &n) { if(n.z) z = -(x*n.x/n.z + y*n.y/n.z); return *this; }
projectxyvec156     vec &projectxy(const vec &n)
157     {
158         float m = squaredlen(), k = dot(n);
159         projectxydir(n);
160         rescale(sqrtf(::max(m - k*k, 0.0f)));
161         return *this;
162     }
projectxyvec163     vec &projectxy(const vec &n, float threshold)
164     {
165         float m = squaredlen(), k = ::min(dot(n), threshold);
166         projectxydir(n);
167         rescale(sqrtf(::max(m - k*k, 0.0f)));
168         return *this;
169     }
lerpvec170     vec &lerp(const vec &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; z += (b.z-z)*t; return *this; }
lerpvec171     vec &lerp(const vec &a, const vec &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; z = a.z + (b.z-a.z)*t; return *this; }
avgvec172     vec &avg(const vec &b) { add(b); mul(0.5f); return *this; }
maddvec173     template<class B> vec &madd(const vec &a, const B &b) { return add(vec(a).mul(b)); }
msubvec174     template<class B> vec &msub(const vec &a, const B &b) { return sub(vec(a).mul(b)); }
175 
rescalevec176     vec &rescale(float k)
177     {
178         float mag = magnitude();
179         if(mag > 1e-6f) mul(k / mag);
180         return *this;
181     }
182 
rotate_around_zvec183     vec &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
rotate_around_xvec184     vec &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; }
rotate_around_yvec185     vec &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx+s*rz; z = c*rz-s*rx; return *this; }
186 
rotate_around_zvec187     vec &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
rotate_around_xvec188     vec &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
rotate_around_yvec189     vec &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
190 
rotate_around_zvec191     vec &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
rotate_around_xvec192     vec &rotate_around_x(const vec2 &sc) { return rotate_around_x(sc.x, sc.y); }
rotate_around_yvec193     vec &rotate_around_y(const vec2 &sc) { return rotate_around_y(sc.x, sc.y); }
194 
rotatevec195     vec &rotate(float c, float s, const vec &d)
196     {
197         *this = vec(x*(d.x*d.x*(1-c)+c) + y*(d.x*d.y*(1-c)-d.z*s) + z*(d.x*d.z*(1-c)+d.y*s),
198                     x*(d.y*d.x*(1-c)+d.z*s) + y*(d.y*d.y*(1-c)+c) + z*(d.y*d.z*(1-c)-d.x*s),
199                     x*(d.x*d.z*(1-c)-d.y*s) + y*(d.y*d.z*(1-c)+d.x*s) + z*(d.z*d.z*(1-c)+c));
200         return *this;
201     }
rotatevec202     vec &rotate(float angle, const vec &d) { return rotate(cosf(angle), sinf(angle), d); }
rotatevec203     vec &rotate(const vec2 &sc, const vec &d) { return rotate(sc.x, sc.y, d); }
204 
orthogonalvec205     void orthogonal(const vec &d)
206     {
207         int i = fabs(d.x) > fabs(d.y) ? (fabs(d.x) > fabs(d.z) ? 0 : 2) : (fabs(d.y) > fabs(d.z) ? 1 : 2);
208         v[i] = d[(i+1)%3];
209         v[(i+1)%3] = -d[i];
210         v[(i+2)%3] = 0;
211     }
212 
orthonormalizevec213     void orthonormalize(vec &s, vec &t) const
214     {
215         s.project(*this);
216         t.project(*this).project(s);
217     }
218 
219     template<class T>
insidebbvec220     bool insidebb(const T &bbmin, const T &bbmax) const
221     {
222         return x >= bbmin.x && x <= bbmax.x && y >= bbmin.y && y <= bbmax.y && z >= bbmin.z && z <= bbmax.z;
223     }
224 
225     template<class T, class U>
insidebbvec226     bool insidebb(const T &o, U size) const
227     {
228         return x >= o.x && x <= o.x + size && y >= o.y && y <= o.y + size && z >= o.z && z <= o.z + size;
229     }
230 
dist_to_bbvec231     template<class T> float dist_to_bb(const T &min, const T &max) const
232     {
233         float sqrdist = 0;
234         loopi(3)
235         {
236             if     (v[i] < min[i]) { float delta = v[i]-min[i]; sqrdist += delta*delta; }
237             else if(v[i] > max[i]) { float delta = max[i]-v[i]; sqrdist += delta*delta; }
238         }
239         return sqrtf(sqrdist);
240     }
241 
dist_to_bbvec242     template<class T, class S> float dist_to_bb(const T &o, S size) const
243     {
244         return dist_to_bb(o, T(o).add(size));
245     }
246 
project_bbvec247     template<class T> float project_bb(const T &min, const T &max) const
248     {
249         return x*(x < 0 ? max.x : min.x) + y*(y < 0 ? max.y : min.y) + z*(z < 0 ? max.z : min.z);
250     }
251 
hexcolorvec252     static vec hexcolor(int color)
253     {
254         return vec(((color>>16)&0xFF)*(1.0f/255.0f), ((color>>8)&0xFF)*(1.0f/255.0f), (color&0xFF)*(1.0f/255.0f));
255     }
256 
tohexcolorvec257     int tohexcolor() const { return (int(::clamp(r, 0.0f, 1.0f)*255)<<16)|(int(::clamp(g, 0.0f, 1.0f)*255)<<8)|int(::clamp(b, 0.0f, 1.0f)*255); }
258 };
259 
vec2(const vec & v)260 inline vec2::vec2(const vec &v) : x(v.x), y(v.y) {}
261 
htcmp(const vec & x,const vec & y)262 static inline bool htcmp(const vec &x, const vec &y)
263 {
264     return x == y;
265 }
266 
hthash(const vec & k)267 static inline uint hthash(const vec &k)
268 {
269     union { uint i; float f; } x, y, z;
270     x.f = k.x; y.f = k.y; z.f = k.z;
271     uint v = x.i^y.i^z.i;
272     return v + (v>>12);
273 }
274 
275 struct vec4
276 {
277     union
278     {
279         struct { float x, y, z, w; };
280         struct { float r, g, b, a; };
281         float v[4];
282     };
283 
vec4vec4284     vec4() {}
285     explicit vec4(const vec &p, float w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
vec4vec4286     vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
vec4vec4287     explicit vec4(const float *v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
288 
289     float &operator[](int i)       { return v[i]; }
290     float  operator[](int i) const { return v[i]; }
291 
292     bool operator==(const vec4 &o) const { return x == o.x && y == o.y && z == o.z && w == o.w; }
293     bool operator!=(const vec4 &o) const { return x != o.x || y != o.y || z != o.z || w != o.w; }
294 
dot3vec4295     float dot3(const vec4 &o) const { return x*o.x + y*o.y + z*o.z; }
dot3vec4296     float dot3(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
dotvec4297     float dot(const vec4 &o) const { return dot3(o) + w*o.w; }
dotvec4298     float dot(const vec &o) const  { return x*o.x + y*o.y + z*o.z + w; }
squaredlenvec4299     float squaredlen() const { return dot(*this); }
magnitudevec4300     float magnitude() const  { return sqrtf(squaredlen()); }
magnitude3vec4301     float magnitude3() const { return sqrtf(dot3(*this)); }
normalizevec4302     vec4 &normalize() { mul(1/magnitude()); return *this; }
303 
lerpvec4304     vec4 &lerp(const vec4 &b, float t)
305     {
306         x += (b.x-x)*t;
307         y += (b.y-y)*t;
308         z += (b.z-z)*t;
309         w += (b.w-w)*t;
310         return *this;
311     }
lerpvec4312     vec4 &lerp(const vec4 &a, const vec4 &b, float t)
313     {
314         x = a.x+(b.x-a.x)*t;
315         y = a.y+(b.y-a.y)*t;
316         z = a.z+(b.z-a.z)*t;
317         w = a.w+(b.w-a.w)*t;
318         return *this;
319     }
avgvec4320     vec4 &avg(const vec4 &b) { add(b); mul(0.5f); return *this; }
maddvec4321     template<class B> vec4 &madd(const vec4 &a, const B &b) { return add(vec4(a).mul(b)); }
msubvec4322     template<class B> vec4 &msub(const vec4 &a, const B &b) { return sub(vec4(a).mul(b)); }
323 
mul3vec4324     vec4 &mul3(float f)      { x *= f; y *= f; z *= f; return *this; }
mulvec4325     vec4 &mul(float f)       { mul3(f); w *= f; return *this; }
mulvec4326     vec4 &mul(const vec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
mulvec4327     vec4 &mul(const vec &o)  { x *= o.x; y *= o.y; z *= o.z; return *this; }
squarevec4328     vec4 &square()           { mul(*this); return *this; }
div3vec4329     vec4 &div3(float f)      { x /= f; y /= f; z /= f; return *this; }
divvec4330     vec4 &div(float f)       { div3(f); w /= f; return *this; }
divvec4331     vec4 &div(const vec4 &o) { x /= o.x; y /= o.y; z /= o.z; w /= o.w; return *this; }
divvec4332     vec4 &div(const vec &o)  { x /= o.x; y /= o.y; z /= o.z; return *this; }
recipvec4333     vec4 &recip()            { x = 1/x; y = 1/y; z = 1/z; w = 1/w; return *this; }
addvec4334     vec4 &add(const vec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
addvec4335     vec4 &add(const vec &o)  { x += o.x; y += o.y; z += o.z; return *this; }
add3vec4336     vec4 &add3(float f)      { x += f; y += f; z += f; return *this; }
addvec4337     vec4 &add(float f)       { add3(f); w += f; return *this; }
addwvec4338     vec4 &addw(float f)      { w += f; return *this; }
subvec4339     vec4 &sub(const vec4 &o) { x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this; }
subvec4340     vec4 &sub(const vec &o)  { x -= o.x; y -= o.y; z -= o.z; return *this; }
sub3vec4341     vec4 &sub3(float f)      { x -= f; y -= f; z -= f; return *this; }
subvec4342     vec4 &sub(float f)       { sub3(f); w -= f; return *this; }
subwvec4343     vec4 &subw(float f)      { w -= f; return *this; }
neg3vec4344     vec4 &neg3()             { x = -x; y = -y; z = -z; return *this; }
negvec4345     vec4 &neg()              { neg3(); w = -w; return *this; }
clampvec4346     vec4 &clamp(float l, float h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); z = ::clamp(z, l, h); w = ::clamp(w, l, h); return *this; }
347 
348     template<class A, class B>
crossvec4349     vec4 &cross(const A &a, const B &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
crossvec4350     vec4 &cross(const vec &o, const vec &a, const vec &b) { return cross(vec(a).sub(o), vec(b).sub(o)); }
351 
setxyzvec4352     void setxyz(const vec &v) { x = v.x; y = v.y; z = v.z; }
353 
rotate_around_zvec4354     vec4 &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
rotate_around_xvec4355     vec4 &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; }
rotate_around_yvec4356     vec4 &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx-s*rz; z = c*rz+s*rx; return *this; }
357 
rotate_around_zvec4358     vec4 &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
rotate_around_xvec4359     vec4 &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
rotate_around_yvec4360     vec4 &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
361 
rotate_around_zvec4362     vec4 &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
rotate_around_xvec4363     vec4 &rotate_around_x(const vec2 &sc) { return rotate_around_x(sc.x, sc.y); }
rotate_around_yvec4364     vec4 &rotate_around_y(const vec2 &sc) { return rotate_around_y(sc.x, sc.y); }
365 };
366 
vec2(const vec4 & v)367 inline vec2::vec2(const vec4 &v) : x(v.x), y(v.y) {}
vec(const vec4 & v)368 inline vec::vec(const vec4 &v) : x(v.x), y(v.y), z(v.z) {}
369 
370 struct matrix3;
371 struct matrix4x3;
372 struct matrix4;
373 
374 struct quat : vec4
375 {
quatquat376     quat() {}
quatquat377     quat(float x, float y, float z, float w) : vec4(x, y, z, w) {}
quatquat378     quat(const vec &axis, float angle)
379     {
380         w = cosf(angle/2);
381         float s = sinf(angle/2);
382         x = s*axis.x;
383         y = s*axis.y;
384         z = s*axis.z;
385     }
quatquat386     quat(const vec &u, const vec &v)
387     {
388         w = sqrtf(u.squaredlen() * v.squaredlen()) + u.dot(v);
389         cross(u, v);
390         normalize();
391     }
quatquat392     explicit quat(const vec &v)
393     {
394         x = v.x;
395         y = v.y;
396         z = v.z;
397         restorew();
398     }
quatquat399     explicit quat(const matrix3 &m) { convertmatrix(m); }
quatquat400     explicit quat(const matrix4x3 &m) { convertmatrix(m); }
quatquat401     explicit quat(const matrix4 &m) { convertmatrix(m); }
402 
restorewquat403     void restorew() { w = 1.0f-x*x-y*y-z*z; w = w<0 ? 0 : -sqrtf(w); }
404 
addquat405     quat &add(const vec4 &o) { vec4::add(o); return *this; }
subquat406     quat &sub(const vec4 &o) { vec4::sub(o); return *this; }
mulquat407     quat &mul(float k) { vec4::mul(k); return *this; }
maddquat408     template<class B> quat &madd(const vec4 &a, const B &b) { return add(vec4(a).mul(b)); }
msubquat409     template<class B> quat &msub(const vec4 &a, const B &b) { return sub(vec4(a).mul(b)); }
410 
mulquat411     quat &mul(const quat &p, const quat &o)
412     {
413         x = p.w*o.x + p.x*o.w + p.y*o.z - p.z*o.y;
414         y = p.w*o.y - p.x*o.z + p.y*o.w + p.z*o.x;
415         z = p.w*o.z + p.x*o.y - p.y*o.x + p.z*o.w;
416         w = p.w*o.w - p.x*o.x - p.y*o.y - p.z*o.z;
417         return *this;
418     }
mulquat419     quat &mul(const quat &o) { return mul(quat(*this), o); }
420 
invertquat421     quat &invert() { neg3(); return *this; }
422 
normalizequat423     quat &normalize() { vec4::normalize(); return *this; }
424 
calcangleaxisquat425     void calcangleaxis(float &angle, vec &axis) const
426     {
427         float rr = dot3(*this);
428         if(rr>0)
429         {
430             angle = 2*acosf(w);
431             axis = vec(x, y, z).mul(1/rr);
432         }
433         else { angle = 0; axis = vec(0, 0, 1); }
434     }
435 
calcanglesquat436     vec calcangles() const
437     {
438         vec4 qq = vec4(*this).square();
439         float rr = qq.x + qq.y + qq.z + qq.w,
440               t = x*y + z*w;
441         if(fabs(t) > 0.49999f*rr) return t < 0 ? vec(-2*atan2f(x, w), -M_PI/2, 0) : vec(2*atan2f(x, w), M_PI/2, 0);
442         return vec(atan2f(2*(y*w - x*z), qq.x - qq.y - qq.z + qq.w),
443                    asinf(2*t/rr),
444                    atan2f(2*(x*w - y*z), -qq.x + qq.y - qq.z + qq.w));
445     }
446 
rotatequat447     vec rotate(const vec &v) const
448     {
449         return vec().cross(*this, vec().cross(*this, v).madd(v, w)).mul(2).add(v);
450     }
451 
invertedrotatequat452     vec invertedrotate(const vec &v) const
453     {
454         return vec().cross(*this, vec().cross(*this, v).msub(v, w)).mul(2).add(v);
455     }
456 
457     template<class M>
convertmatrixquat458     void convertmatrix(const M &m)
459     {
460         float trace = m.a.x + m.b.y + m.c.z;
461         if(trace>0)
462         {
463             float r = sqrtf(1 + trace), inv = 0.5f/r;
464             w = 0.5f*r;
465             x = (m.b.z - m.c.y)*inv;
466             y = (m.c.x - m.a.z)*inv;
467             z = (m.a.y - m.b.x)*inv;
468         }
469         else if(m.a.x > m.b.y && m.a.x > m.c.z)
470         {
471             float r = sqrtf(1 + m.a.x - m.b.y - m.c.z), inv = 0.5f/r;
472             x = 0.5f*r;
473             y = (m.a.y + m.b.x)*inv;
474             z = (m.c.x + m.a.z)*inv;
475             w = (m.b.z - m.c.y)*inv;
476         }
477         else if(m.b.y > m.c.z)
478         {
479             float r = sqrtf(1 + m.b.y - m.a.x - m.c.z), inv = 0.5f/r;
480             x = (m.a.y + m.b.x)*inv;
481             y = 0.5f*r;
482             z = (m.b.z + m.c.y)*inv;
483             w = (m.c.x - m.a.z)*inv;
484         }
485         else
486         {
487             float r = sqrtf(1 + m.c.z - m.a.x - m.b.y), inv = 0.5f/r;
488             x = (m.c.x + m.a.z)*inv;
489             y = (m.b.z + m.c.y)*inv;
490             z = 0.5f*r;
491             w = (m.a.y - m.b.x)*inv;
492         }
493     }
494 };
495 
496 struct dualquat
497 {
498     quat real, dual;
499 
dualquatdualquat500     dualquat() {}
dualquatdualquat501     dualquat(const quat &q, const vec &p)
502         : real(q),
503           dual(0.5f*( p.x*q.w + p.y*q.z - p.z*q.y),
504                0.5f*(-p.x*q.z + p.y*q.w + p.z*q.x),
505                0.5f*( p.x*q.y - p.y*q.x + p.z*q.w),
506               -0.5f*( p.x*q.x + p.y*q.y + p.z*q.z))
507     {
508     }
dualquatdualquat509     explicit dualquat(const quat &q) : real(q), dual(0, 0, 0, 0) {}
510     explicit dualquat(const matrix4x3 &m);
511 
muldualquat512     dualquat &mul(float k) { real.mul(k); dual.mul(k); return *this; }
adddualquat513     dualquat &add(const dualquat &d) { real.add(d.real); dual.add(d.dual); return *this; }
514 
lerpdualquat515     dualquat &lerp(const dualquat &to, float t)
516     {
517         float k = real.dot(to.real) < 0 ? -t : t;
518         real.mul(1-t).madd(to.real, k);
519         dual.mul(1-t).madd(to.dual, k);
520         return *this;
521     }
lerpdualquat522     dualquat &lerp(const dualquat &from, const dualquat &to, float t)
523     {
524         float k = from.real.dot(to.real) < 0 ? -t : t;
525         (real = from.real).mul(1-t).madd(to.real, k);
526         (dual = from.dual).mul(1-t).madd(to.dual, k);
527         return *this;
528     }
529 
invertdualquat530     dualquat &invert()
531     {
532         real.invert();
533         dual.invert();
534         dual.msub(real, 2*real.dot(dual));
535         return *this;
536     }
537 
muldualquat538     void mul(const dualquat &p, const dualquat &o)
539     {
540         real.mul(p.real, o.real);
541         dual.mul(p.real, o.dual).add(quat().mul(p.dual, o.real));
542     }
muldualquat543     void mul(const dualquat &o) { mul(dualquat(*this), o); }
544 
mulorientdualquat545     void mulorient(const quat &q)
546     {
547         real.mul(q, quat(real));
548         dual.mul(quat(q).invert(), quat(dual));
549     }
550 
mulorientdualquat551     void mulorient(const quat &q, const dualquat &base)
552     {
553         quat trans;
554         trans.mul(base.dual, quat(base.real).invert());
555         dual.mul(quat(q).invert(), quat().mul(real, trans).add(dual));
556 
557         real.mul(q, quat(real));
558         dual.add(quat().mul(real, trans.invert())).msub(real, 2*base.real.dot(base.dual));
559     }
560 
normalizedualquat561     void normalize()
562     {
563         float invlen = 1/real.magnitude();
564         real.mul(invlen);
565         dual.mul(invlen);
566     }
567 
translatedualquat568     void translate(const vec &p)
569     {
570         dual.x +=  0.5f*( p.x*real.w + p.y*real.z - p.z*real.y);
571         dual.y +=  0.5f*(-p.x*real.z + p.y*real.w + p.z*real.x);
572         dual.z +=  0.5f*( p.x*real.y - p.y*real.x + p.z*real.w);
573         dual.w += -0.5f*( p.x*real.x + p.y*real.y + p.z*real.z);
574     }
575 
scaledualquat576     void scale(float k)
577     {
578         dual.mul(k);
579     }
580 
fixantipodaldualquat581     void fixantipodal(const dualquat &d)
582     {
583         if(real.dot(d.real) < 0)
584         {
585             real.neg();
586             dual.neg();
587         }
588     }
589 
accumulatedualquat590     void accumulate(const dualquat &d, float k)
591     {
592         if(real.dot(d.real) < 0) k = -k;
593         real.madd(d.real, k);
594         dual.madd(d.dual, k);
595     }
596 
transformdualquat597     vec transform(const vec &v) const
598     {
599         return vec().cross(real, vec().cross(real, v).madd(v, real.w).add(vec(dual))).madd(vec(dual), real.w).msub(vec(real), dual.w).mul(2).add(v);
600     }
601 
transformdualquat602     quat transform(const quat &q) const
603     {
604         return quat().mul(real, q);
605     }
606 
transposedtransformdualquat607     vec transposedtransform(const vec &v) const
608     {
609         return dualquat(*this).invert().transform(v);
610     }
611 
transformnormaldualquat612     vec transformnormal(const vec &v) const
613     {
614         return real.rotate(v);
615     }
616 
transposedtransformnormaldualquat617     vec transposedtransformnormal(const vec &v) const
618     {
619         return real.invertedrotate(v);
620     }
621 
gettranslationdualquat622     vec gettranslation() const
623     {
624         return vec().cross(real, dual).madd(vec(dual), real.w).msub(vec(real), dual.w).mul(2);
625     }
626 };
627 
628 struct matrix3
629 {
630     vec a, b, c;
631 
matrix3matrix3632     matrix3() {}
matrix3matrix3633     matrix3(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {}
matrix3matrix3634     explicit matrix3(float angle, const vec &axis) { rotate(angle, axis); }
matrix3matrix3635     explicit matrix3(const quat &q)
636     {
637         float x = q.x, y = q.y, z = q.z, w = q.w,
638               tx = 2*x, ty = 2*y, tz = 2*z,
639               txx = tx*x, tyy = ty*y, tzz = tz*z,
640               txy = tx*y, txz = tx*z, tyz = ty*z,
641               twx = w*tx, twy = w*ty, twz = w*tz;
642         a = vec(1 - (tyy + tzz), txy + twz, txz - twy);
643         b = vec(txy - twz, 1 - (txx + tzz), tyz + twx);
644         c = vec(txz + twy, tyz - twx, 1 - (txx + tyy));
645     }
646     explicit matrix3(const matrix4x3 &m);
647     explicit matrix3(const matrix4 &m);
648 
mulmatrix3649     void mul(const matrix3 &m, const matrix3 &n)
650     {
651         a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
652         b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
653         c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
654     }
mulmatrix3655     void mul(const matrix3 &n) { mul(matrix3(*this), n); }
656 
multransposematrix3657     void multranspose(const matrix3 &m, const matrix3 &n)
658     {
659         a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
660         b = vec(m.a).mul(n.a.y).madd(m.b, m.b.y).madd(m.c, n.c.y);
661         c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
662     }
multransposematrix3663     void multranspose(const matrix3 &n) { multranspose(matrix3(*this), n); }
664 
transposemulmatrix3665     void transposemul(const matrix3 &m, const matrix3 &n)
666     {
667         a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
668         b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
669         c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
670     }
transposemulmatrix3671     void transposemul(const matrix3 &n) { transposemul(matrix3(*this), n); }
672 
transposematrix3673     void transpose()
674     {
675         swap(a.y, b.x); swap(a.z, c.x);
676         swap(b.z, c.y);
677     }
678 
679     template<class M>
transposematrix3680     void transpose(const M &m)
681     {
682         a = vec(m.a.x, m.b.x, m.c.x);
683         b = vec(m.a.y, m.b.y, m.c.y);
684         c = vec(m.a.z, m.b.z, m.c.z);
685     }
686 
invertmatrix3687     void invert(const matrix3 &o)
688     {
689         vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
690         transpose(o);
691         a.mul(unscale);
692         b.mul(unscale);
693         c.mul(unscale);
694     }
invertmatrix3695     void invert() { invert(matrix3(*this)); }
696 
normalizematrix3697     void normalize()
698     {
699         a.normalize();
700         b.normalize();
701         c.normalize();
702     }
703 
scalematrix3704     void scale(float k)
705     {
706         a.mul(k);
707         b.mul(k);
708         c.mul(k);
709     }
710 
rotatematrix3711     void rotate(float angle, const vec &axis)
712     {
713         rotate(cosf(angle), sinf(angle), axis);
714     }
715 
rotatematrix3716     void rotate(float ck, float sk, const vec &axis)
717     {
718         a = vec(axis.x*axis.x*(1-ck)+ck, axis.x*axis.y*(1-ck)+axis.z*sk, axis.x*axis.z*(1-ck)-axis.y*sk);
719         b = vec(axis.x*axis.y*(1-ck)-axis.z*sk, axis.y*axis.y*(1-ck)+ck, axis.y*axis.z*(1-ck)+axis.x*sk);
720         c = vec(axis.x*axis.z*(1-ck)+axis.y*sk, axis.y*axis.z*(1-ck)-axis.x*sk, axis.z*axis.z*(1-ck)+ck);
721     }
722 
setyawmatrix3723     void setyaw(float ck, float sk)
724     {
725         a = vec(ck, sk, 0);
726         b = vec(-sk, ck, 0);
727         c = vec(0, 0, 1);
728     }
729 
setyawmatrix3730     void setyaw(float angle)
731     {
732         setyaw(cosf(angle), sinf(angle));
733     }
734 
tracematrix3735     float trace() const { return a.x + b.y + c.z; }
736 
737     bool calcangleaxis(float tr, float &angle, vec &axis, float threshold = 1e-16f) const
738     {
739         if(tr <= -1)
740         {
741             if(a.x >= b.y && a.x >= c.z)
742             {
743                 float r = 1 + a.x - b.y - c.z;
744                 if(r <= threshold) return false;
745                 r = sqrtf(r);
746                 axis.x = 0.5f*r;
747                 axis.y = b.x/r;
748                 axis.z = c.x/r;
749             }
750             else if(b.y >= c.z)
751             {
752                 float r = 1 + b.y - a.x - c.z;
753                 if(r <= threshold) return false;
754                 r = sqrtf(r);
755                 axis.y = 0.5f*r;
756                 axis.x = b.x/r;
757                 axis.z = c.y/r;
758             }
759             else
760             {
761                 float r = 1 + b.y - a.x - c.z;
762                 if(r <= threshold) return false;
763                 r = sqrtf(r);
764                 axis.z = 0.5f*r;
765                 axis.x = c.x/r;
766                 axis.y = c.y/r;
767             }
768             angle = M_PI;
769         }
770         else if(tr >= 3)
771         {
772             axis = vec(0, 0, 1);
773             angle = 0;
774         }
775         else
776         {
777             axis = vec(b.z - c.y, c.x - a.z, a.y - b.x);
778             float r = axis.squaredlen();
779             if(r <= threshold) return false;
780             axis.mul(1/sqrtf(r));
781             angle = acosf(0.5f*(tr - 1));
782         }
783         return true;
784     }
785 
786     bool calcangleaxis(float &angle, vec &axis, float threshold = 1e-16f) const { return calcangleaxis(trace(), angle, axis, threshold); }
787 
transformmatrix3788     vec transform(const vec &o) const
789     {
790         return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z);
791     }
transposedtransformmatrix3792     vec transposedtransform(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
abstransformmatrix3793     vec abstransform(const vec &o) const
794     {
795         return vec(a).mul(o.x).abs().add(vec(b).mul(o.y).abs()).add(vec(c).mul(o.z).abs());
796     }
abstransposedtransformmatrix3797     vec abstransposedtransform(const vec &o) const
798     {
799         return vec(a.absdot(o), b.absdot(o), c.absdot(o));
800     }
801 
identitymatrix3802     void identity()
803     {
804         a = vec(1, 0, 0);
805         b = vec(0, 1, 0);
806         c = vec(0, 0, 1);
807     }
808 
rotate_around_xmatrix3809     void rotate_around_x(float ck, float sk)
810     {
811         vec rb = vec(b).mul(ck).madd(c, sk),
812             rc = vec(c).mul(ck).msub(b, sk);
813         b = rb;
814         c = rc;
815     }
rotate_around_xmatrix3816     void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
rotate_around_xmatrix3817     void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
818 
rotate_around_ymatrix3819     void rotate_around_y(float ck, float sk)
820     {
821         vec rc = vec(c).mul(ck).madd(a, sk),
822             ra = vec(a).mul(ck).msub(c, sk);
823         c = rc;
824         a = ra;
825     }
rotate_around_ymatrix3826     void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
rotate_around_ymatrix3827     void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
828 
rotate_around_zmatrix3829     void rotate_around_z(float ck, float sk)
830     {
831         vec ra = vec(a).mul(ck).madd(b, sk),
832             rb = vec(b).mul(ck).msub(a, sk);
833         a = ra;
834         b = rb;
835     }
rotate_around_zmatrix3836     void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
rotate_around_zmatrix3837     void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
838 
transformmatrix3839     vec transform(const vec2 &o) { return vec(a).mul(o.x).madd(b, o.y); }
transposedtransformmatrix3840     vec transposedtransform(const vec2 &o) const { return vec(a.dot2(o), b.dot2(o), c.dot2(o)); }
841 
rowxmatrix3842     vec rowx() const { return vec(a.x, b.x, c.x); }
rowymatrix3843     vec rowy() const { return vec(a.y, b.y, c.y); }
rowzmatrix3844     vec rowz() const { return vec(a.z, b.z, c.z); }
845 };
846 
847 struct matrix4x3
848 {
849     vec a, b, c, d;
850 
matrix4x3matrix4x3851     matrix4x3() {}
matrix4x3matrix4x3852     matrix4x3(const vec &a, const vec &b, const vec &c, const vec &d) : a(a), b(b), c(c), d(d) {}
matrix4x3matrix4x3853     matrix4x3(const matrix3 &rot, const vec &trans) : a(rot.a), b(rot.b), c(rot.c), d(trans) {}
matrix4x3matrix4x3854     matrix4x3(const dualquat &dq)
855     {
856         vec4 r = vec4(dq.real).mul(1/dq.real.squaredlen()), rr = vec4(r).mul(dq.real);
857         r.mul(2);
858         float xy = r.x*dq.real.y, xz = r.x*dq.real.z, yz = r.y*dq.real.z,
859               wx = r.w*dq.real.x, wy = r.w*dq.real.y, wz = r.w*dq.real.z;
860         a = vec(rr.w + rr.x - rr.y - rr.z, xy + wz, xz - wy);
861         b = vec(xy - wz, rr.w + rr.y - rr.x - rr.z, yz + wx);
862         c = vec(xz + wy, yz - wx, rr.w + rr.z - rr.x - rr.y);
863         d = vec(-(dq.dual.w*r.x - dq.dual.x*r.w + dq.dual.y*r.z - dq.dual.z*r.y),
864                 -(dq.dual.w*r.y - dq.dual.x*r.z - dq.dual.y*r.w + dq.dual.z*r.x),
865                 -(dq.dual.w*r.z + dq.dual.x*r.y - dq.dual.y*r.x - dq.dual.z*r.w));
866 
867     }
868     explicit matrix4x3(const matrix4 &m);
869 
mulmatrix4x3870     void mul(float k)
871     {
872         a.mul(k);
873         b.mul(k);
874         c.mul(k);
875         d.mul(k);
876     }
877 
setscalematrix4x3878     void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; }
setscalematrix4x3879     void setscale(const vec &v) { setscale(v.x, v.y, v.z); }
setscalematrix4x3880     void setscale(float n) { setscale(n, n, n); }
881 
scalematrix4x3882     void scale(float x, float y, float z)
883     {
884         a.mul(x);
885         b.mul(y);
886         c.mul(z);
887     }
scalematrix4x3888     void scale(const vec &v) { scale(v.x, v.y, v.z); }
scalematrix4x3889     void scale(float n) { scale(n, n, n); }
890 
settranslationmatrix4x3891     void settranslation(const vec &p) { d = p; }
settranslationmatrix4x3892     void settranslation(float x, float y, float z) { d = vec(x, y, z); }
893 
translatematrix4x3894     void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); }
translatematrix4x3895     void translate(float x, float y, float z) { translate(vec(x, y, z)); }
translatematrix4x3896     void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); }
897 
accumulatematrix4x3898     void accumulate(const matrix4x3 &m, float k)
899     {
900         a.madd(m.a, k);
901         b.madd(m.b, k);
902         c.madd(m.c, k);
903         d.madd(m.d, k);
904     }
905 
normalizematrix4x3906     void normalize()
907     {
908         a.normalize();
909         b.normalize();
910         c.normalize();
911     }
912 
lerpmatrix4x3913     void lerp(const matrix4x3 &to, float t)
914     {
915         a.lerp(to.a, t);
916         b.lerp(to.b, t);
917         c.lerp(to.c, t);
918         d.lerp(to.d, t);
919     }
lerpmatrix4x3920     void lerp(const matrix4x3 &from, const matrix4x3 &to, float t)
921     {
922         a.lerp(from.a, to.a, t);
923         b.lerp(from.b, to.b, t);
924         c.lerp(from.c, to.c, t);
925         d.lerp(from.d, to.d, t);
926     }
927 
identitymatrix4x3928     void identity()
929     {
930         a = vec(1, 0, 0);
931         b = vec(0, 1, 0);
932         c = vec(0, 0, 1);
933         d = vec(0, 0, 0);
934     }
935 
mulmatrix4x3936     void mul(const matrix4x3 &m, const matrix4x3 &n)
937     {
938         a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
939         b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
940         c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
941         d = vec(m.d).madd(m.a, n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
942     }
mulmatrix4x3943     void mul(const matrix4x3 &n) { mul(matrix4x3(*this), n); }
944 
mulmatrix4x3945     void mul(const matrix3 &m, const matrix4x3 &n)
946     {
947         a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
948         b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
949         c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
950         d = vec(m.a).mul(n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
951     }
952 
mulmatrix4x3953     void mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n)
954     {
955         mul(rot, n);
956         d.add(trans);
957     }
958 
transposematrix4x3959     void transpose()
960     {
961         d = vec(a.dot(d), b.dot(d), c.dot(d)).neg();
962         swap(a.y, b.x); swap(a.z, c.x);
963         swap(b.z, c.y);
964     }
965 
transposematrix4x3966     void transpose(const matrix4x3 &o)
967     {
968         a = vec(o.a.x, o.b.x, o.c.x);
969         b = vec(o.a.y, o.b.y, o.c.y);
970         c = vec(o.a.z, o.b.z, o.c.z);
971         d = vec(o.a.dot(o.d), o.b.dot(o.d), o.c.dot(o.d)).neg();
972     }
973 
transposemulmatrix4x3974     void transposemul(const matrix4x3 &m, const matrix4x3 &n)
975     {
976         vec t(m.a.dot(m.d), m.b.dot(m.d), m.c.dot(m.d));
977         a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
978         b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
979         c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
980         d = vec(m.a.dot(n.d), m.b.dot(n.d), m.c.dot(n.d)).sub(t);
981     }
982 
multransposematrix4x3983     void multranspose(const matrix4x3 &m, const matrix4x3 &n)
984     {
985         vec t(n.a.dot(n.d), n.b.dot(n.d), n.c.dot(n.d));
986         a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
987         b = vec(m.a).mul(n.a.y).madd(m.b, m.b.y).madd(m.c, n.c.y);
988         c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
989         d = vec(m.d).msub(m.a, t.x).msub(m.b, t.y).msub(m.c, t.z);
990     }
991 
invertmatrix4x3992     void invert(const matrix4x3 &o)
993     {
994         vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
995         transpose(o);
996         a.mul(unscale);
997         b.mul(unscale);
998         c.mul(unscale);
999         d.mul(unscale);
1000     }
invertmatrix4x31001     void invert() { invert(matrix4x3(*this)); }
1002 
rotatematrix4x31003     void rotate(float angle, const vec &d)
1004     {
1005         rotate(cosf(angle), sinf(angle), d);
1006     }
1007 
rotatematrix4x31008     void rotate(float ck, float sk, const vec &axis)
1009     {
1010         matrix3 m;
1011         m.rotate(ck, sk, axis);
1012         *this = matrix4x3(m, vec(0, 0, 0));
1013     }
1014 
rotate_around_xmatrix4x31015     void rotate_around_x(float ck, float sk)
1016     {
1017         vec rb = vec(b).mul(ck).madd(c, sk),
1018             rc = vec(c).mul(ck).msub(b, sk);
1019         b = rb;
1020         c = rc;
1021     }
rotate_around_xmatrix4x31022     void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
rotate_around_xmatrix4x31023     void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
1024 
rotate_around_ymatrix4x31025     void rotate_around_y(float ck, float sk)
1026     {
1027         vec rc = vec(c).mul(ck).madd(a, sk),
1028             ra = vec(a).mul(ck).msub(c, sk);
1029         c = rc;
1030         a = ra;
1031     }
rotate_around_ymatrix4x31032     void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
rotate_around_ymatrix4x31033     void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
1034 
rotate_around_zmatrix4x31035     void rotate_around_z(float ck, float sk)
1036     {
1037         vec ra = vec(a).mul(ck).madd(b, sk),
1038             rb = vec(b).mul(ck).msub(a, sk);
1039         a = ra;
1040         b = rb;
1041     }
rotate_around_zmatrix4x31042     void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
rotate_around_zmatrix4x31043     void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
1044 
transformmatrix4x31045     vec transform(const vec &o) const { return vec(d).madd(a, o.x).madd(b, o.y).madd(c, o.z); }
transposedtransformmatrix4x31046     vec transposedtransform(const vec &o) const { vec p = vec(o).sub(d); return vec(a.dot(p), b.dot(p), c.dot(p)); }
transformnormalmatrix4x31047     vec transformnormal(const vec &o) const { return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z); }
transposedtransformnormalmatrix4x31048     vec transposedtransformnormal(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
transformmatrix4x31049     vec transform(const vec2 &o) const { return vec(d).madd(a, o.x).madd(b, o.y); }
1050 
rowxmatrix4x31051     vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); }
rowymatrix4x31052     vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); }
rowzmatrix4x31053     vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); }
1054 };
1055 
dualquat(const matrix4x3 & m)1056 inline dualquat::dualquat(const matrix4x3 &m) : real(m)
1057 {
1058     dual.x =  0.5f*( m.d.x*real.w + m.d.y*real.z - m.d.z*real.y);
1059     dual.y =  0.5f*(-m.d.x*real.z + m.d.y*real.w + m.d.z*real.x);
1060     dual.z =  0.5f*( m.d.x*real.y - m.d.y*real.x + m.d.z*real.w);
1061     dual.w = -0.5f*( m.d.x*real.x + m.d.y*real.y + m.d.z*real.z);
1062 }
1063 
matrix3(const matrix4x3 & m)1064 inline matrix3::matrix3(const matrix4x3 &m) : a(m.a), b(m.b), c(m.c) {}
1065 
1066 struct plane : vec
1067 {
1068     float offset;
1069 
distplane1070     float dist(const vec &p) const { return dot(p)+offset; }
distplane1071     float dist(const vec4 &p) const { return p.dot3(*this) + p.w*offset; }
1072     bool operator==(const plane &p) const { return x==p.x && y==p.y && z==p.z && offset==p.offset; }
1073     bool operator!=(const plane &p) const { return x!=p.x || y!=p.y || z!=p.z || offset!=p.offset; }
1074 
planeplane1075     plane() {}
planeplane1076     plane(const vec &c, float off) : vec(c), offset(off) {}
planeplane1077     plane(const vec4 &p) : vec(p), offset(p.w) {}
planeplane1078     plane(int d, float off)
1079     {
1080         x = y = z = 0.0f;
1081         v[d] = 1.0f;
1082         offset = -off;
1083     }
planeplane1084     plane(float a, float b, float c, float d) : vec(a, b, c), offset(d) {}
1085 
toplaneplane1086     void toplane(const vec &n, const vec &p)
1087     {
1088         x = n.x; y = n.y; z = n.z;
1089         offset = -dot(p);
1090     }
1091 
toplaneplane1092     bool toplane(const vec &a, const vec &b, const vec &c)
1093     {
1094         cross(vec(b).sub(a), vec(c).sub(a));
1095         float mag = magnitude();
1096         if(!mag) return false;
1097         div(mag);
1098         offset = -dot(a);
1099         return true;
1100     }
1101 
rayintersectplane1102     bool rayintersect(const vec &o, const vec &ray, float &dist)
1103     {
1104         float cosalpha = dot(ray);
1105         if(cosalpha==0) return false;
1106         float deltac = offset+dot(o);
1107         dist -= deltac/cosalpha;
1108         return true;
1109     }
1110 
reflectzplane1111     plane &reflectz(float rz)
1112     {
1113         offset += 2*rz*z;
1114         z = -z;
1115         return *this;
1116     }
1117 
invertplane1118     plane &invert()
1119     {
1120         neg();
1121         offset = -offset;
1122         return *this;
1123     }
1124 
scaleplane1125     plane &scale(float k)
1126     {
1127         mul(k);
1128         return *this;
1129     }
1130 
translateplane1131     plane &translate(const vec &p)
1132     {
1133         offset += dot(p);
1134         return *this;
1135     }
1136 
normalizeplane1137     plane &normalize()
1138     {
1139         float mag = magnitude();
1140         div(mag);
1141         offset /= mag;
1142         return *this;
1143     }
1144 
zintersectplane1145     float zintersect(const vec &p) const { return -(x*p.x+y*p.y+offset)/z; }
zdeltaplane1146     float zdelta(const vec &p) const { return -(x*p.x+y*p.y)/z; }
zdistplane1147     float zdist(const vec &p) const { return p.z-zintersect(p); }
1148 };
1149 
1150 struct triangle
1151 {
1152     vec a, b, c;
1153 
triangletriangle1154     triangle(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {}
triangletriangle1155     triangle() {}
1156 
addtriangle1157     triangle &add(const vec &o) { a.add(o); b.add(o); c.add(o); return *this; }
subtriangle1158     triangle &sub(const vec &o) { a.sub(o); b.sub(o); c.sub(o); return *this; }
1159 
1160     bool operator==(const triangle &t) const { return a == t.a && b == t.b && c == t.c; }
1161 };
1162 
1163 /**
1164 
1165 The engine uses 3 different linear coordinate systems
1166 which are oriented around each of the axis dimensions.
1167 
1168 So any point within the game can be defined by four coordinates: (d, x, y, z)
1169 
1170 d is the reference axis dimension
1171 x is the coordinate of the ROW dimension
1172 y is the coordinate of the COL dimension
1173 z is the coordinate of the reference dimension (DEPTH)
1174 
1175 typically, if d is not used, then it is implicitly the Z dimension.
1176 ie: d=z => x=x, y=y, z=z
1177 
1178 **/
1179 
1180 // DIM: X=0 Y=1 Z=2.
1181 const int R[3]  = {1, 2, 0}; // row
1182 const int C[3]  = {2, 0, 1}; // col
1183 const int D[3]  = {0, 1, 2}; // depth
1184 
1185 struct ivec4;
1186 struct ivec2;
1187 
1188 struct ivec
1189 {
1190     union
1191     {
1192         struct { int x, y, z; };
1193         struct { int r, g, b; };
1194         int v[3];
1195     };
1196 
ivecivec1197     ivec() {}
ivecivec1198     ivec(const vec &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)) {}
ivecivec1199     ivec(int a, int b, int c) : x(a), y(b), z(c) {}
ivecivec1200     ivec(int d, int row, int col, int depth)
1201     {
1202         v[R[d]] = row;
1203         v[C[d]] = col;
1204         v[D[d]] = depth;
1205     }
ivecivec1206     ivec(int i, const ivec &co, int size) : x(co.x+((i&1)>>0)*size), y(co.y+((i&2)>>1)*size), z(co.z +((i&4)>>2)*size) {}
1207     explicit ivec(const ivec4 &v);
1208     explicit ivec(const ivec2 &v, int z = 0);
1209     explicit ivec(const usvec &v);
1210     explicit ivec(const svec &v);
1211 
1212     int &operator[](int i)       { return v[i]; }
1213     int  operator[](int i) const { return v[i]; }
1214 
1215     //int idx(int i) { return v[i]; }
1216     bool operator==(const ivec &v) const { return x==v.x && y==v.y && z==v.z; }
1217     bool operator!=(const ivec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
iszeroivec1218     bool iszero() const { return x==0 && y==0 && z==0; }
shlivec1219     ivec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
shrivec1220     ivec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
mulivec1221     ivec &mul(int n) { x *= n; y *= n; z *= n; return *this; }
divivec1222     ivec &div(int n) { x /= n; y /= n; z /= n; return *this; }
addivec1223     ivec &add(int n) { x += n; y += n; z += n; return *this; }
subivec1224     ivec &sub(int n) { x -= n; y -= n; z -= n; return *this; }
mulivec1225     ivec &mul(const ivec &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
divivec1226     ivec &div(const ivec &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
addivec1227     ivec &add(const ivec &v) { x += v.x; y += v.y; z += v.z; return *this; }
subivec1228     ivec &sub(const ivec &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
maskivec1229     ivec &mask(int n) { x &= n; y &= n; z &= n; return *this; }
negivec1230     ivec &neg() { x = -x; y = -y; z = -z; return *this; }
minivec1231     ivec &min(const ivec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
maxivec1232     ivec &max(const ivec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
minivec1233     ivec &min(int n) { x = ::min(x, n); y = ::min(y, n); z = ::min(z, n); return *this; }
maxivec1234     ivec &max(int n) { x = ::max(x, n); y = ::max(y, n); z = ::max(z, n); return *this; }
absivec1235     ivec &abs() { x = ::abs(x); y = ::abs(y); z = ::abs(z); return *this; }
clampivec1236     ivec &clamp(int l, int h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); z = ::clamp(z, l, h); return *this; }
crossivec1237     ivec &cross(const ivec &a, const ivec &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
dotivec1238     int dot(const ivec &o) const { return x*o.x + y*o.y + z*o.z; }
distivec1239     float dist(const plane &p) const { return x*p.x + y*p.y + z*p.z + p.offset; }
1240 
floorivec1241     static inline ivec floor(const vec &o) { return ivec(int(::floor(o.x)), int(::floor(o.y)), int(::floor(o.z))); }
ceilivec1242     static inline ivec ceil(const vec &o) { return ivec(int(::ceil(o.x)), int(::ceil(o.y)), int(::ceil(o.z))); }
1243 };
1244 
vec(const ivec & v)1245 inline vec::vec(const ivec &v) : x(v.x), y(v.y), z(v.z) {}
1246 
htcmp(const ivec & x,const ivec & y)1247 static inline bool htcmp(const ivec &x, const ivec &y)
1248 {
1249     return x == y;
1250 }
1251 
hthash(const ivec & k)1252 static inline uint hthash(const ivec &k)
1253 {
1254     return k.x^k.y^k.z;
1255 }
1256 
1257 struct ivec2
1258 {
1259     union
1260     {
1261         struct { int x, y; };
1262         int v[2];
1263     };
1264 
ivec2ivec21265     ivec2() {}
ivec2ivec21266     ivec2(int x, int y) : x(x), y(y) {}
ivec2ivec21267     explicit ivec2(const vec2 &v) : x(int(v.x)), y(int(v.y)) {}
ivec2ivec21268     explicit ivec2(const ivec &v) : x(v.x), y(v.y) {}
1269 
1270     int &operator[](int i)       { return v[i]; }
1271     int  operator[](int i) const { return v[i]; }
1272 
1273     bool operator==(const ivec2 &o) const { return x == o.x && y == o.y; }
1274     bool operator!=(const ivec2 &o) const { return x != o.x || y != o.y; }
1275 
iszeroivec21276     bool iszero() const { return x==0 && y==0; }
shlivec21277     ivec2 &shl(int n) { x<<= n; y<<= n; return *this; }
shrivec21278     ivec2 &shr(int n) { x>>= n; y>>= n; return *this; }
mulivec21279     ivec2 &mul(int n) { x *= n; y *= n; return *this; }
divivec21280     ivec2 &div(int n) { x /= n; y /= n; return *this; }
addivec21281     ivec2 &add(int n) { x += n; y += n; return *this; }
subivec21282     ivec2 &sub(int n) { x -= n; y -= n; return *this; }
mulivec21283     ivec2 &mul(const ivec2 &v) { x *= v.x; y *= v.y; return *this; }
divivec21284     ivec2 &div(const ivec2 &v) { x /= v.x; y /= v.y; return *this; }
addivec21285     ivec2 &add(const ivec2 &v) { x += v.x; y += v.y; return *this; }
subivec21286     ivec2 &sub(const ivec2 &v) { x -= v.x; y -= v.y; return *this; }
maskivec21287     ivec2 &mask(int n) { x &= n; y &= n; return *this; }
negivec21288     ivec2 &neg() { x = -x; y = -y; return *this; }
minivec21289     ivec2 &min(const ivec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; }
maxivec21290     ivec2 &max(const ivec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; }
minivec21291     ivec2 &min(int n) { x = ::min(x, n); y = ::min(y, n); return *this; }
maxivec21292     ivec2 &max(int n) { x = ::max(x, n); y = ::max(y, n); return *this; }
absivec21293     ivec2 &abs() { x = ::abs(x); y = ::abs(y); return *this; }
dotivec21294     int dot(const ivec2 &o) const { return x*o.x + y*o.y; }
crossivec21295     int cross(const ivec2 &o) const { return x*o.y - y*o.x; }
1296 };
1297 
ivec(const ivec2 & v,int z)1298 inline ivec::ivec(const ivec2 &v, int z) : x(v.x), y(v.y), z(z) {}
1299 
htcmp(const ivec2 & x,const ivec2 & y)1300 static inline bool htcmp(const ivec2 &x, const ivec2 &y)
1301 {
1302     return x == y;
1303 }
1304 
hthash(const ivec2 & k)1305 static inline uint hthash(const ivec2 &k)
1306 {
1307     return k.x^k.y;
1308 }
1309 
1310 struct ivec4
1311 {
1312     union
1313     {
1314         struct { int x, y, z, w; };
1315         struct { int r, g, b, a; };
1316         int v[4];
1317     };
1318 
ivec4ivec41319     ivec4() {}
1320     explicit ivec4(const ivec &p, int w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
ivec4ivec41321     ivec4(int x, int y, int z, int w) : x(x), y(y), z(z), w(w) {}
ivec4ivec41322     explicit ivec4(const vec4 &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)), w(int(v.w)) {}
1323 
1324     bool operator==(const ivec4 &o) const { return x == o.x && y == o.y && z == o.z && w == o.w; }
1325     bool operator!=(const ivec4 &o) const { return x != o.x || y != o.y || z != o.z || w != o.w; }
1326 };
1327 
ivec(const ivec4 & v)1328 inline ivec::ivec(const ivec4 &v) : x(v.x), y(v.y), z(v.z) {}
1329 
htcmp(const ivec4 & x,const ivec4 & y)1330 static inline bool htcmp(const ivec4 &x, const ivec4 &y)
1331 {
1332     return x == y;
1333 }
1334 
hthash(const ivec4 & k)1335 static inline uint hthash(const ivec4 &k)
1336 {
1337     return k.x^k.y^k.z^k.w;
1338 }
1339 
1340 struct bvec4;
1341 
1342 struct bvec
1343 {
1344     union
1345     {
1346         struct { uchar x, y, z; };
1347         struct { uchar r, g, b; };
1348         uchar v[3];
1349     };
1350 
bvecbvec1351     bvec() {}
bvecbvec1352     bvec(uchar x, uchar y, uchar z) : x(x), y(y), z(z) {}
bvecbvec1353     bvec(const vec &v) : x((uchar)((v.x+1)*255/2)), y((uchar)((v.y+1)*255/2)), z((uchar)((v.z+1)*255/2)) {}
1354     explicit bvec(const bvec4 &v);
1355 
1356     uchar &operator[](int i)       { return v[i]; }
1357     uchar  operator[](int i) const { return v[i]; }
1358 
1359     bool operator==(const bvec &v) const { return x==v.x && y==v.y && z==v.z; }
1360     bool operator!=(const bvec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
1361 
iszerobvec1362     bool iszero() const { return x==0 && y==0 && z==0; }
1363 
tonormalbvec1364     vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); }
1365 
normalizebvec1366     bvec &normalize()
1367     {
1368         vec n(x-127.5f, y-127.5f, z-127.5f);
1369         float mag = 127.5f/n.magnitude();
1370         x = uchar(n.x*mag+127.5f);
1371         y = uchar(n.y*mag+127.5f);
1372         z = uchar(n.z*mag+127.5f);
1373         return *this;
1374     }
1375 
lerpbvec1376     void lerp(const bvec &a, const bvec &b, float t) { x = uchar(a.x + (b.x-a.x)*t); y = uchar(a.y + (b.y-a.y)*t); z = uchar(a.z + (b.z-a.z)*t); }
1377 
flipbvec1378     void flip() { x ^= 0x80; y ^= 0x80; z ^= 0x80; }
1379 
scalebvec1380     void scale(int k, int d) { x = uchar((x*k)/d); y = uchar((y*k)/d); z = uchar((z*k)/d); }
1381 
shlbvec1382     bvec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
shrbvec1383     bvec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
1384 
fromcolorbvec1385     static bvec fromcolor(const vec &v) { return bvec(uchar(v.x*255.0f), uchar(v.y*255.0f), uchar(v.z*255.0f)); }
tocolorbvec1386     vec tocolor() const { return vec(x*(1.0f/255.0f), y*(1.0f/255.0f), z*(1.0f/255.0f)); }
1387 
hexcolorbvec1388     static bvec hexcolor(int color)
1389     {
1390         return bvec((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
1391     }
tohexcolorbvec1392     int tohexcolor() const { return (int(r)<<16)|(int(g)<<8)|int(b); }
1393 };
1394 
1395 struct bvec4
1396 {
1397     union
1398     {
1399         struct { uchar x, y, z, w; };
1400         struct { uchar r, g, b, a; };
1401         uchar v[4];
1402         uint mask;
1403     };
1404 
bvec4bvec41405     bvec4() {}
bvec4bvec41406     bvec4(uchar x, uchar y, uchar z, uchar w) : x(x), y(y), z(z), w(w) {}
bvec4bvec41407     bvec4(const bvec &v, uchar w) : x(v.x), y(v.y), z(v.z), w(w) {}
1408 
1409     uchar &operator[](int i)       { return v[i]; }
1410     uchar  operator[](int i) const { return v[i]; }
1411 
1412     bool operator==(const bvec4 &v) const { return x==v.x && y==v.y && z==v.z && w==v.w; }
1413     bool operator!=(const bvec4 &v) const { return x!=v.x || y!=v.y || z!=v.z || w!=v.w; }
1414 
iszerobvec41415     bool iszero() const { return x==0 && y==0 && z==0 && w==0; }
1416 
flipbvec41417     void flip() { mask ^= 0x80808080; }
1418 };
1419 
bvec(const bvec4 & v)1420 inline bvec::bvec(const bvec4 &v) : x(v.x), y(v.y), z(v.z) {}
1421 
1422 struct usvec
1423 {
1424     union
1425     {
1426         struct { ushort x, y, z; };
1427         ushort v[3];
1428     };
1429 
1430     ushort &operator[](int i) { return v[i]; }
1431     ushort operator[](int i) const { return v[i]; }
1432 };
1433 
vec(const usvec & v)1434 inline vec::vec(const usvec &v) : x(v.x), y(v.y), z(v.z) {}
ivec(const usvec & v)1435 inline ivec::ivec(const usvec &v) : x(v.x), y(v.y), z(v.z) {}
1436 
1437 struct svec
1438 {
1439     union
1440     {
1441         struct { short x, y, z; };
1442         short v[3];
1443     };
1444 
svecsvec1445     svec() {}
svecsvec1446     svec(short x, short y, short z) : x(x), y(y), z(z) {}
svecsvec1447     svec(const ivec &v) : x(v.x), y(v.y), z(v.z) {}
1448 
1449     short &operator[](int i) { return v[i]; }
1450     short operator[](int i) const { return v[i]; }
1451 };
1452 
vec(const svec & v)1453 inline vec::vec(const svec &v) : x(v.x), y(v.y), z(v.z) {}
ivec(const svec & v)1454 inline ivec::ivec(const svec &v) : x(v.x), y(v.y), z(v.z) {}
1455 
1456 struct dvec4
1457 {
1458     double x, y, z, w;
1459 
dvec4dvec41460     dvec4() {}
dvec4dvec41461     dvec4(double x, double y, double z, double w) : x(x), y(y), z(z), w(w) {}
dvec4dvec41462     dvec4(const vec4 &v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
1463 
madddvec41464     template<class B> dvec4 &madd(const dvec4 &a, const B &b) { return add(dvec4(a).mul(b)); }
muldvec41465     dvec4 &mul(double f)       { x *= f; y *= f; z *= f; w *= f; return *this; }
muldvec41466     dvec4 &mul(const dvec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
adddvec41467     dvec4 &add(double f)       { x += f; y += f; z += f; w += f; return *this; }
adddvec41468     dvec4 &add(const dvec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
1469 
vec4dvec41470     operator vec4() const { return vec4(x, y, z, w); }
1471 };
1472 
1473 struct matrix4
1474 {
1475     vec4 a, b, c, d;
1476 
matrix4matrix41477     matrix4() {}
matrix4matrix41478     matrix4(const float *m) : a(m), b(m+4), c(m+8), d(m+12) {}
1479     matrix4(const vec &a, const vec &b, const vec &c = vec(0, 0, 1))
1480         : a(a.x, b.x, c.x, 0), b(a.y, b.y, c.y, 0), c(a.z, b.z, c.z, 0), d(0, 0, 0, 1)
1481     {}
1482     matrix4(const vec4 &a, const vec4 &b, const vec4 &c, const vec4 &d = vec4(0, 0, 0, 1))
amatrix41483         : a(a), b(b), c(c), d(d)
1484     {}
matrix4matrix41485     matrix4(const matrix4x3 &m)
1486         : a(m.a, 0), b(m.b, 0), c(m.c, 0), d(m.d, 1)
1487     {}
1488 
mulmatrix41489     void mul(const matrix4 &x, const matrix3 &y)
1490     {
1491         a = vec4(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z);
1492         b = vec4(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z);
1493         c = vec4(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z);
1494         d = x.d;
1495     }
mulmatrix41496     void mul(const matrix3 &y) { mul(matrix4(*this), y); }
1497 
multmatrix41498     template<class T> void mult(const matrix4 &x, const matrix4 &y)
1499     {
1500         a = T(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z).madd(x.d, y.a.w);
1501         b = T(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z).madd(x.d, y.b.w);
1502         c = T(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z).madd(x.d, y.c.w);
1503         d = T(x.a).mul(y.d.x).madd(x.b, y.d.y).madd(x.c, y.d.z).madd(x.d, y.d.w);
1504     }
1505 
mulmatrix41506     void mul(const matrix4 &x, const matrix4 &y) { mult<vec4>(x, y); }
mulmatrix41507     void mul(const matrix4 &y) { mult<vec4>(matrix4(*this), y); }
1508 
muldmatrix41509     void muld(const matrix4 &x, const matrix4 &y) { mult<dvec4>(x, y); }
muldmatrix41510     void muld(const matrix4 &y) { mult<dvec4>(matrix4(*this), y); }
1511 
rotate_around_xmatrix41512     void rotate_around_x(float ck, float sk)
1513     {
1514         vec4 rb = vec4(b).mul(ck).madd(c, sk),
1515              rc = vec4(c).mul(ck).msub(b, sk);
1516         b = rb;
1517         c = rc;
1518     }
rotate_around_xmatrix41519     void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
rotate_around_xmatrix41520     void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
1521 
rotate_around_ymatrix41522     void rotate_around_y(float ck, float sk)
1523     {
1524         vec4 rc = vec4(c).mul(ck).madd(a, sk),
1525              ra = vec4(a).mul(ck).msub(c, sk);
1526         c = rc;
1527         a = ra;
1528     }
rotate_around_ymatrix41529     void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
rotate_around_ymatrix41530     void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
1531 
rotate_around_zmatrix41532     void rotate_around_z(float ck, float sk)
1533     {
1534         vec4 ra = vec4(a).mul(ck).madd(b, sk),
1535              rb = vec4(b).mul(ck).msub(a, sk);
1536         a = ra;
1537         b = rb;
1538     }
rotate_around_zmatrix41539     void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
rotate_around_zmatrix41540     void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
1541 
rotatematrix41542     void rotate(float ck, float sk, const vec &axis)
1543     {
1544         matrix3 m;
1545         m.rotate(ck, sk, axis);
1546         mul(m);
1547     }
rotatematrix41548     void rotate(float angle, const vec &dir) { rotate(cosf(angle), sinf(angle), dir); }
rotatematrix41549     void rotate(const vec2 &sc, const vec &dir) { rotate(sc.x, sc.y, dir); }
1550 
identitymatrix41551     void identity()
1552     {
1553         a = vec4(1, 0, 0, 0);
1554         b = vec4(0, 1, 0, 0);
1555         c = vec4(0, 0, 1, 0);
1556         d = vec4(0, 0, 0, 1);
1557     }
1558 
settranslationmatrix41559     void settranslation(const vec &v) { d.setxyz(v); }
settranslationmatrix41560     void settranslation(float x, float y, float z) { d.x = x; d.y = y; d.z = z; }
1561 
translatematrix41562     void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); }
translatematrix41563     void translate(float x, float y, float z) { translate(vec(x, y, z)); }
translatematrix41564     void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); }
1565 
setscalematrix41566     void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; }
setscalematrix41567     void setscale(const vec &v) { setscale(v.x, v.y, v.z); }
setscalematrix41568     void setscale(float n) { setscale(n, n, n); }
1569 
scalematrix41570     void scale(float x, float y, float z)
1571     {
1572         a.mul(x);
1573         b.mul(y);
1574         c.mul(z);
1575     }
scalematrix41576     void scale(const vec &v) { scale(v.x, v.y, v.z); }
scalematrix41577     void scale(float n) { scale(n, n, n); }
1578 
scalexymatrix41579     void scalexy(float x, float y)
1580     {
1581         a.x *= x; a.y *= y;
1582         b.x *= x; b.y *= y;
1583         c.x *= x; c.y *= y;
1584         d.x *= x; d.y *= y;
1585     }
1586 
scalezmatrix41587     void scalez(float k)
1588     {
1589         a.z *= k;
1590         b.z *= k;
1591         c.z *= k;
1592         d.z *= k;
1593     }
1594 
reflectzmatrix41595     void reflectz(float z)
1596     {
1597         d.add(vec4(c).mul(2*z));
1598         c.neg();
1599     }
1600 
jittermatrix41601     void jitter(float x, float y)
1602     {
1603         a.x += x * a.w;
1604         a.y += y * a.w;
1605         b.x += x * b.w;
1606         b.y += y * b.w;
1607         c.x += x * c.w;
1608         c.y += y * c.w;
1609         d.x += x * d.w;
1610         d.y += y * d.w;
1611     }
1612 
transposematrix41613     void transpose()
1614     {
1615         swap(a.y, b.x); swap(a.z, c.x); swap(a.w, d.x);
1616         swap(b.z, c.y); swap(b.w, d.y);
1617         swap(c.w, d.z);
1618     }
1619 
transposematrix41620     void transpose(const matrix4 &m)
1621     {
1622         a = vec4(m.a.x, m.b.x, m.c.x, m.d.x);
1623         b = vec4(m.a.y, m.b.y, m.c.y, m.d.y);
1624         c = vec4(m.a.z, m.b.z, m.c.z, m.d.z);
1625         d = vec4(m.a.w, m.b.w, m.c.w, m.d.w);
1626     }
1627 
frustummatrix41628     void frustum(float left, float right, float bottom, float top, float znear, float zfar)
1629     {
1630         float width = right - left, height = top - bottom, zrange = znear - zfar;
1631         a = vec4(2*znear/width, 0, 0, 0);
1632         b = vec4(0, 2*znear/height, 0, 0);
1633         c = vec4((right + left)/width, (top + bottom)/height, (zfar + znear)/zrange, -1);
1634         d = vec4(0, 0, 2*znear*zfar/zrange, 0);
1635     }
1636 
perspectivematrix41637     void perspective(float fovy, float aspect, float znear, float zfar)
1638     {
1639         float ydist = znear * tan(fovy/2*RAD), xdist = ydist * aspect;
1640         frustum(-xdist, xdist, -ydist, ydist, znear, zfar);
1641     }
1642 
orthomatrix41643     void ortho(float left, float right, float bottom, float top, float znear, float zfar)
1644     {
1645         float width = right - left, height = top - bottom, zrange = znear - zfar;
1646         a = vec4(2/width, 0, 0, 0);
1647         b = vec4(0, 2/height, 0, 0);
1648         c = vec4(0, 0, 2/zrange, 0);
1649         d = vec4(-(right+left)/width, -(top+bottom)/height, (zfar+znear)/zrange, 1);
1650     }
1651 
clipmatrix41652     void clip(const plane &p, const matrix4 &m)
1653     {
1654         float x = ((p.x<0 ? -1 : (p.x>0 ? 1 : 0)) + m.c.x) / m.a.x,
1655               y = ((p.y<0 ? -1 : (p.y>0 ? 1 : 0)) + m.c.y) / m.b.y,
1656               w = (1 + m.c.z) / m.d.z,
1657             scale = 2 / (x*p.x + y*p.y - p.z + w*p.offset);
1658         a = vec4(m.a.x, m.a.y, p.x*scale, m.a.w);
1659         b = vec4(m.b.x, m.b.y, p.y*scale, m.b.w);
1660         c = vec4(m.c.x, m.c.y, p.z*scale + 1.0f, m.c.w);
1661         d = vec4(m.d.x, m.d.y, p.offset*scale, m.d.w);
1662     }
1663 
transformmatrix41664     void transform(const vec &in, vec &out) const
1665     {
1666         out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d));
1667     }
1668 
transformmatrix41669     void transform(const vec4 &in, vec &out) const
1670     {
1671         out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d).mul(in.w));
1672     }
1673 
transformmatrix41674     void transform(const vec &in, vec4 &out) const
1675     {
1676         out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).add(d);
1677     }
1678 
transformmatrix41679     void transform(const vec4 &in, vec4 &out) const
1680     {
1681         out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).madd(d, in.w);
1682     }
1683 
transformmatrix41684     template<class T, class U> T transform(const U &in) const
1685     {
1686         T v;
1687         transform(in, v);
1688         return v;
1689     }
1690 
perspectivetransformmatrix41691     template<class T> vec perspectivetransform(const T &in) const
1692     {
1693         vec4 v;
1694         transform(in, v);
1695         return vec(v).div(v.w);
1696     }
1697 
transformnormalmatrix41698     void transformnormal(const vec &in, vec &out) const
1699     {
1700         out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z));
1701     }
1702 
transformnormalmatrix41703     void transformnormal(const vec &in, vec4 &out) const
1704     {
1705         out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z);
1706     }
1707 
transformnormalmatrix41708     template<class T, class U> T transformnormal(const U &in) const
1709     {
1710         T v;
1711         transform(in, v);
1712         return v;
1713     }
1714 
transposedtransformmatrix41715     void transposedtransform(const vec &in, vec &out) const
1716     {
1717         vec p = vec(in).sub(vec(d));
1718         out.x = a.dot3(p);
1719         out.y = b.dot3(p);
1720         out.z = c.dot3(p);
1721     }
1722 
transposedtransformnormalmatrix41723     void transposedtransformnormal(const vec &in, vec &out) const
1724     {
1725         out.x = a.dot3(in);
1726         out.y = b.dot3(in);
1727         out.z = c.dot3(in);
1728     }
1729 
transposedtransformmatrix41730     void transposedtransform(const plane &in, plane &out) const
1731     {
1732         out.x = in.dist(a);
1733         out.y = in.dist(b);
1734         out.z = in.dist(c);
1735         out.offset = in.dist(d);
1736     }
1737 
getscalematrix41738     float getscale() const
1739     {
1740         return sqrtf(a.x*a.y + b.x*b.x + c.x*c.x);
1741     }
1742 
gettranslationmatrix41743     vec gettranslation() const
1744     {
1745         return vec(d);
1746     }
1747 
rowxmatrix41748     vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); }
rowymatrix41749     vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); }
rowzmatrix41750     vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); }
rowwmatrix41751     vec4 roww() const { return vec4(a.w, b.w, c.w, d.w); }
1752 
1753     bool invert(const matrix4 &m, double mindet = 1.0e-12);
1754 
lineardepthscalematrix41755     vec2 lineardepthscale() const
1756     {
1757         return vec2(d.w, -d.z).div(c.z*d.w - d.z*c.w);
1758     }
1759 };
1760 
matrix3(const matrix4 & m)1761 inline matrix3::matrix3(const matrix4 &m)
1762     : a(m.a), b(m.b), c(m.c)
1763 {}
1764 
matrix4x3(const matrix4 & m)1765 inline matrix4x3::matrix4x3(const matrix4 &m)
1766     : a(m.a), b(m.b), c(m.c), d(m.d)
1767 {}
1768 
1769 struct matrix2
1770 {
1771     vec2 a, b;
1772 
matrix2matrix21773     matrix2() {}
matrix2matrix21774     matrix2(const vec2 &a, const vec2 &b) : a(a), b(b) {}
matrix2matrix21775     explicit matrix2(const matrix4 &m) : a(m.a), b(m.b) {}
matrix2matrix21776     explicit matrix2(const matrix3 &m) : a(m.a), b(m.b) {}
1777 };
1778 
1779 struct half
1780 {
1781     ushort val;
1782 
halfhalf1783     half() {}
halfhalf1784     half(float f)
1785     {
1786         union { int i; float f; } conv;
1787         conv.f = f;
1788         ushort signbit = (conv.i>>(31-15)) & (1<<15), mantissa = (conv.i>>(23-10)) & 0x3FF;
1789         int exponent = ((conv.i>>23)&0xFF) - 127 + 15;
1790         if(exponent <= 0)
1791         {
1792             mantissa |= 0x400;
1793             mantissa >>= min(1-exponent, 10+1);
1794             exponent = 0;
1795         }
1796         else if(exponent >= 0x1F)
1797         {
1798             mantissa = 0;
1799             exponent = 0x1F;
1800         }
1801         val = signbit | (ushort(exponent)<<10) | mantissa;
1802     }
1803 
1804     bool operator==(const half &h) const { return val == h.val; }
1805     bool operator!=(const half &h) const { return val != h.val; }
1806 };
1807 
1808 struct hvec2
1809 {
1810     half x, y;
1811 
hvec2hvec21812     hvec2() {}
hvec2hvec21813     template<class T> hvec2(T x, T y) : x(x), y(y) {}
hvec2hvec21814     hvec2(const vec2 &v) : x(v.x), y(v.y) {}
1815 
1816     bool operator==(const hvec2 &h) const { return x == h.x && y == h.y; }
1817     bool operator!=(const hvec2 &h) const { return x != h.x || y != h.y; }
1818 };
1819 
1820 struct hvec
1821 {
1822     half x, y, z;
1823 
hvechvec1824     hvec() {}
hvechvec1825     template<class T> hvec(T x, T y, T z) : x(x), y(y), z(z) {}
hvechvec1826     hvec(const vec &v) : x(v.x), y(v.y), z(v.z) {}
1827 
1828     bool operator==(const hvec &h) const { return x == h.x && y == h.y && z == h.z; }
1829     bool operator!=(const hvec &h) const { return x != h.x || y != h.y || z != h.z; }
1830 };
1831 
1832 struct hvec4
1833 {
1834     half x, y, z, w;
1835 
hvec4hvec41836     hvec4() {}
hvec4hvec41837     template<class T> hvec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {}
1838     template<class T> hvec4(const vec &v, T w = 0) : x(v.x), y(v.y), z(v.z), w(w) {}
hvec4hvec41839     hvec4(const vec4 &v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
1840 
1841     bool operator==(const hvec4 &h) const { return x == h.x && y == h.y && z == h.z && w == h.w; }
1842     bool operator!=(const hvec4 &h) const { return x != h.x || y != h.y || z != h.z || w != h.w; }
1843 };
1844 
1845 struct squat
1846 {
1847     short x, y, z, w;
1848 
squatsquat1849     squat() {}
squatsquat1850     squat(const vec4 &q) { convert(q); }
1851 
convertsquat1852     void convert(const vec4 &q)
1853     {
1854         x = short(q.x*32767.5f-0.5f);
1855         y = short(q.y*32767.5f-0.5f);
1856         z = short(q.z*32767.5f-0.5f);
1857         w = short(q.w*32767.5f-0.5f);
1858     }
1859 
lerpsquat1860     void lerp(const vec4 &a, const vec4 &b, float t)
1861     {
1862         vec4 q;
1863         q.lerp(a, b, t);
1864         convert(q);
1865     }
1866 };
1867 
1868 extern bool raysphereintersect(const vec &center, float radius, const vec &o, const vec &ray, float &dist);
1869 extern bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec &ray, float &dist, int &orient);
1870 extern bool linecylinderintersect(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist);
1871 extern int polyclip(const vec *in, int numin, const vec &dir, float below, float above, vec *out);
1872 
1873 extern const vec2 sincos360[];
mod360(int angle)1874 static inline int mod360(int angle)
1875 {
1876     if(angle < 0) angle = 360 + (angle <= -360 ? angle%360 : angle);
1877     else if(angle >= 360) angle %= 360;
1878     return angle;
1879 }
sincosmod360(int angle)1880 static inline const vec2 &sincosmod360(int angle) { return sincos360[mod360(angle)]; }
cos360(int angle)1881 static inline float cos360(int angle) { return sincos360[angle].x; }
sin360(int angle)1882 static inline float sin360(int angle) { return sincos360[angle].y; }
tan360(int angle)1883 static inline float tan360(int angle) { const vec2 &sc = sincos360[angle]; return sc.y/sc.x; }
cotan360(int angle)1884 static inline float cotan360(int angle) { const vec2 &sc = sincos360[angle]; return sc.x/sc.y; }
1885 
1886