#pragma once const float M_PI = 3.1415926535897932; template class mat4_tl { public: typedef T value_type; typedef mat4_tl type; public: union { struct { value_type m00, m01, m02, m03; value_type m10, m11, m12, m13; value_type m20, m21, m22, m23; value_type m30, m31, m32, m33; }; value_type data[4*4]; }; public: mat4_tl() : mat4_tl( 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) { } /// mat4_tl( T const& v00, T const& v01, T const& v02, T const& v03, T const& v10, T const& v11, T const& v12, T const& v13, T const& v20, T const& v21, T const& v22, T const& v23, T const& v30, T const& v31, T const& v32, T const& v33) : m00(v00), m01(v01), m02(v02), m03(v03), m10(v10), m11(v11), m12(v12), m13(v13), m20(v20), m21(v21), m22(v22), m23(v23), m30(v30), m31(v31), m32(v32), m33(v33) { } /// static auto identity() -> mat4_tl { return mat4_tl( 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1); } }; template auto operator *(mat4_tl const& m1, mat4_tl const& m2) -> mat4_tl { return mul(m1, m2); } template auto mul(mat4_tl const& m1, mat4_tl const& m2) -> mat4_tl { mat4_tl m; m.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20 + m1.m03*m2.m30; m.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21 + m1.m03*m2.m31; m.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22 + m1.m03*m2.m32; m.m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + m1.m02*m2.m23 + m1.m03*m2.m33; m.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20 + m1.m13*m2.m30; m.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21 + m1.m13*m2.m31; m.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22 + m1.m13*m2.m32; m.m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + m1.m12*m2.m23 + m1.m13*m2.m33; m.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20 + m1.m23*m2.m30; m.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21 + m1.m23*m2.m31; m.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22 + m1.m23*m2.m32; m.m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + m1.m22*m2.m23 + m1.m23*m2.m33; m.m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + m1.m32*m2.m20 + m1.m33*m2.m30; m.m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + m1.m32*m2.m21 + m1.m33*m2.m31; m.m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + m1.m32*m2.m22 + m1.m33*m2.m32; m.m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + m1.m32*m2.m23 + m1.m33*m2.m33; return m; } template auto perspective(T fov, T aspect, T n, T f) -> mat4_tl { assert(fov > 0); assert(aspect > 0); const T rad = fov*T(M_PI)/T(180); const T a = T(1)/(std::tan(rad/T(2))); return mat4_tl( a/aspect, 0, 0, 0, 0, a, 0, 0, 0, 0, (n+f)/(n-f), 2*n*f/(n-f), 0, 0, -1, 0); } template class vec3_tl { public: union { struct { T x, y, z; }; struct { T s, t, r; }; struct { T r, g, b; }; T data[3]; }; public: /// Constructors vec3_tl() : x(0), y(0), z(0) {} vec3_tl(T const& v) : x(v), y(v), z(v) {} vec3_tl(T const& v1, T const& v2, T const& v3) : x(v1), y(v2), z(v3) {} vec3_tl(vec3_tl const& v) : x(v.x), y(v.y), z(v.z) {} /// Operators auto operator [](size_t pos) -> T & { assert(0<=pos && pos<3); return data[pos]; } auto operator [](size_t pos) const -> T const& { assert(0<=pos && pos<3); return data[pos]; } auto operator ==(vec3_tl const& v) const -> bool { return x==v.x && y==v.y && z==v.z; } auto operator +=(vec3_tl const& v) -> vec3_tl & { x+=v.x; y+=v.y; z+=v.z; return *this; } auto operator -=(vec3_tl const& v) -> vec3_tl & { x-=v.x; y-=v.y; z-=v.z; return *this; } auto operator *=(T const& v) -> vec3_tl & { x*=v; y*=v; z*=v; return *this; } auto operator /=(T const& v) -> vec3_tl & { x/=v; y/=v; z/=v; return *this; } auto operator -() const -> vec3_tl { return vec3_tl(-x, -y, -z); } friend auto operator +(vec3_tl const& v1, vec3_tl const& v2) -> vec3_tl { return vec3_tl(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z); } friend auto operator -(vec3_tl const& v1, vec3_tl const& v2) -> vec3_tl { return vec3_tl(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z); } friend auto operator *(vec3_tl const& v, T const& s) -> vec3_tl { return vec3_tl(v.x*s, v.y*s, v.z*s); } friend auto operator /(vec3_tl const& v, T const& s) -> vec3_tl { return vec3_tl(v.x/s, v.y/s, v.z/s); } }; template auto dot(vec3_tl const& v1, vec3_tl const& v2) -> T { return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); } template auto length(vec3_tl const& v) -> T { return std::sqrt(dot(v, v)); } template auto normalize(vec3_tl const& v) -> vec3_tl { return v/length(v); } template auto cross(vec3_tl const& v1, vec3_tl const& v2) -> vec3_tl { return vec3_tl( v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x ); } template auto look_at(vec3_tl const& eye, vec3_tl const& target, vec3_tl const& up) -> mat4_tl { vec3_tl axis_z = normalize(target-eye); vec3_tl axis_x = normalize(cross(axis_z, up)); vec3_tl axis_y = cross(axis_x, axis_z); return mat4_tl( axis_x.x, axis_x.y, axis_x.z, -dot(axis_x, eye), axis_y.x, axis_y.y, axis_y.z, -dot(axis_y, eye), -axis_z.x, -axis_z.y, -axis_z.z, dot(axis_z, eye), 0, 0, 0, 1 ); } typedef vec3_tl vec3; typedef mat4_tl mat4;