/* Copyright (c) 2017-2026 Hans-Kristian Arntzen * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include #include namespace muglm { template struct tvec2; template struct tvec3; template struct tvec4; template struct tmat2; template struct tmat3; template struct tmat4; template struct tvec2 { tvec2() = default; tvec2(const tvec2 &) = default; tvec2 &operator=(const tvec2 &) = default; explicit inline tvec2(T v) noexcept { x = v; y = v; } template explicit inline tvec2(const tvec2 &u) noexcept { x = T(u.x); y = T(u.y); } inline tvec2(T x_, T y_) noexcept { x = x_; y = y_; } union { T data[2]; struct { T x, y; }; }; inline T &operator[](size_t index) { return data[index]; } inline const T &operator[](size_t index) const { return data[index]; } inline tvec2 xx() const; inline tvec2 xy() const; inline tvec2 yx() const; inline tvec2 yy() const; inline tvec3 xxx() const; inline tvec3 xxy() const; inline tvec3 xyx() const; inline tvec3 xyy() const; inline tvec3 yxx() const; inline tvec3 yxy() const; inline tvec3 yyx() const; inline tvec3 yyy() const; inline tvec4 xxxx() const; inline tvec4 xxxy() const; inline tvec4 xxyx() const; inline tvec4 xxyy() const; inline tvec4 xyxx() const; inline tvec4 xyxy() const; inline tvec4 xyyx() const; inline tvec4 xyyy() const; inline tvec4 yxxx() const; inline tvec4 yxxy() const; inline tvec4 yxyx() const; inline tvec4 yxyy() const; inline tvec4 yyxx() const; inline tvec4 yyxy() const; inline tvec4 yyyx() const; inline tvec4 yyyy() const; }; template struct tvec3 { tvec3() = default; tvec3(const tvec3 &) = default; tvec3 &operator=(const tvec3 &) = default; template explicit inline tvec3(const tvec3 &u) noexcept { x = T(u.x); y = T(u.y); z = T(u.z); } inline tvec3(const tvec2 &a, T b) noexcept { x = a.x; y = a.y; z = b; } inline tvec3(T a, const tvec2 &b) noexcept { x = a; y = b.x; z = b.y; } explicit inline tvec3(T v) noexcept { x = v; y = v; z = v; } inline tvec3(T x_, T y_, T z_) noexcept { x = x_; y = y_; z = z_; } union { T data[3]; struct { T x, y, z; }; }; inline T &operator[](size_t index) { return data[index]; } inline const T &operator[](size_t index) const { return data[index]; } inline tvec2 xx() const; inline tvec2 xy() const; inline tvec2 xz() const; inline tvec2 yx() const; inline tvec2 yy() const; inline tvec2 yz() const; inline tvec2 zx() const; inline tvec2 zy() const; inline tvec2 zz() const; inline tvec3 xxx() const; inline tvec3 xxy() const; inline tvec3 xxz() const; inline tvec3 xyx() const; inline tvec3 xyy() const; inline tvec3 xyz() const; inline tvec3 xzx() const; inline tvec3 xzy() const; inline tvec3 xzz() const; inline tvec3 yxx() const; inline tvec3 yxy() const; inline tvec3 yxz() const; inline tvec3 yyx() const; inline tvec3 yyy() const; inline tvec3 yyz() const; inline tvec3 yzx() const; inline tvec3 yzy() const; inline tvec3 yzz() const; inline tvec3 zxx() const; inline tvec3 zxy() const; inline tvec3 zxz() const; inline tvec3 zyx() const; inline tvec3 zyy() const; inline tvec3 zyz() const; inline tvec3 zzx() const; inline tvec3 zzy() const; inline tvec3 zzz() const; inline tvec4 xxxx() const; inline tvec4 xxxy() const; inline tvec4 xxxz() const; inline tvec4 xxyx() const; inline tvec4 xxyy() const; inline tvec4 xxyz() const; inline tvec4 xxzx() const; inline tvec4 xxzy() const; inline tvec4 xxzz() const; inline tvec4 xyxx() const; inline tvec4 xyxy() const; inline tvec4 xyxz() const; inline tvec4 xyyx() const; inline tvec4 xyyy() const; inline tvec4 xyyz() const; inline tvec4 xyzx() const; inline tvec4 xyzy() const; inline tvec4 xyzz() const; inline tvec4 xzxx() const; inline tvec4 xzxy() const; inline tvec4 xzxz() const; inline tvec4 xzyx() const; inline tvec4 xzyy() const; inline tvec4 xzyz() const; inline tvec4 xzzx() const; inline tvec4 xzzy() const; inline tvec4 xzzz() const; inline tvec4 yxxx() const; inline tvec4 yxxy() const; inline tvec4 yxxz() const; inline tvec4 yxyx() const; inline tvec4 yxyy() const; inline tvec4 yxyz() const; inline tvec4 yxzx() const; inline tvec4 yxzy() const; inline tvec4 yxzz() const; inline tvec4 yyxx() const; inline tvec4 yyxy() const; inline tvec4 yyxz() const; inline tvec4 yyyx() const; inline tvec4 yyyy() const; inline tvec4 yyyz() const; inline tvec4 yyzx() const; inline tvec4 yyzy() const; inline tvec4 yyzz() const; inline tvec4 yzxx() const; inline tvec4 yzxy() const; inline tvec4 yzxz() const; inline tvec4 yzyx() const; inline tvec4 yzyy() const; inline tvec4 yzyz() const; inline tvec4 yzzx() const; inline tvec4 yzzy() const; inline tvec4 yzzz() const; inline tvec4 zxxx() const; inline tvec4 zxxy() const; inline tvec4 zxxz() const; inline tvec4 zxyx() const; inline tvec4 zxyy() const; inline tvec4 zxyz() const; inline tvec4 zxzx() const; inline tvec4 zxzy() const; inline tvec4 zxzz() const; inline tvec4 zyxx() const; inline tvec4 zyxy() const; inline tvec4 zyxz() const; inline tvec4 zyyx() const; inline tvec4 zyyy() const; inline tvec4 zyyz() const; inline tvec4 zyzx() const; inline tvec4 zyzy() const; inline tvec4 zyzz() const; inline tvec4 zzxx() const; inline tvec4 zzxy() const; inline tvec4 zzxz() const; inline tvec4 zzyx() const; inline tvec4 zzyy() const; inline tvec4 zzyz() const; inline tvec4 zzzx() const; inline tvec4 zzzy() const; inline tvec4 zzzz() const; }; template struct tvec4 { tvec4() = default; tvec4(const tvec4 &) = default; tvec4 &operator=(const tvec4 &) = default; template explicit inline tvec4(const tvec4 &u) noexcept { x = T(u.x); y = T(u.y); z = T(u.z); w = T(u.w); } inline tvec4(const tvec2 &a, const tvec2 &b) noexcept { x = a.x; y = a.y; z = b.x; w = b.y; } inline tvec4(const tvec3 &a, T b) noexcept { x = a.x; y = a.y; z = a.z; w = b; } inline tvec4(T a, const tvec3 &b) noexcept { x = a; y = b.x; z = b.y; w = b.z; } inline tvec4(const tvec2 &a, T b, T c) noexcept { x = a.x; y = a.y; z = b; w = c; } inline tvec4(T a, const tvec2 &b, T c) noexcept { x = a; y = b.x; z = b.y; w = c; } inline tvec4(T a, T b, const tvec2 &c) noexcept { x = a; y = b; z = c.x; w = c.y; } explicit inline tvec4(T v) noexcept { x = v; y = v; z = v; w = v; } inline tvec4(T x_, T y_, T z_, T w_) noexcept { x = x_; y = y_; z = z_; w = w_; } inline T &operator[](size_t index) { return data[index]; } inline const T &operator[](size_t index) const { return data[index]; } union { T data[4]; struct { T x, y, z, w; }; }; inline tvec2 xx() const; inline tvec2 xy() const; inline tvec2 xz() const; inline tvec2 xw() const; inline tvec2 yx() const; inline tvec2 yy() const; inline tvec2 yz() const; inline tvec2 yw() const; inline tvec2 zx() const; inline tvec2 zy() const; inline tvec2 zz() const; inline tvec2 zw() const; inline tvec2 wx() const; inline tvec2 wy() const; inline tvec2 wz() const; inline tvec2 ww() const; inline tvec3 xxx() const; inline tvec3 xxy() const; inline tvec3 xxz() const; inline tvec3 xxw() const; inline tvec3 xyx() const; inline tvec3 xyy() const; inline tvec3 xyz() const; inline tvec3 xyw() const; inline tvec3 xzx() const; inline tvec3 xzy() const; inline tvec3 xzz() const; inline tvec3 xzw() const; inline tvec3 xwx() const; inline tvec3 xwy() const; inline tvec3 xwz() const; inline tvec3 xww() const; inline tvec3 yxx() const; inline tvec3 yxy() const; inline tvec3 yxz() const; inline tvec3 yxw() const; inline tvec3 yyx() const; inline tvec3 yyy() const; inline tvec3 yyz() const; inline tvec3 yyw() const; inline tvec3 yzx() const; inline tvec3 yzy() const; inline tvec3 yzz() const; inline tvec3 yzw() const; inline tvec3 ywx() const; inline tvec3 ywy() const; inline tvec3 ywz() const; inline tvec3 yww() const; inline tvec3 zxx() const; inline tvec3 zxy() const; inline tvec3 zxz() const; inline tvec3 zxw() const; inline tvec3 zyx() const; inline tvec3 zyy() const; inline tvec3 zyz() const; inline tvec3 zyw() const; inline tvec3 zzx() const; inline tvec3 zzy() const; inline tvec3 zzz() const; inline tvec3 zzw() const; inline tvec3 zwx() const; inline tvec3 zwy() const; inline tvec3 zwz() const; inline tvec3 zww() const; inline tvec3 wxx() const; inline tvec3 wxy() const; inline tvec3 wxz() const; inline tvec3 wxw() const; inline tvec3 wyx() const; inline tvec3 wyy() const; inline tvec3 wyz() const; inline tvec3 wyw() const; inline tvec3 wzx() const; inline tvec3 wzy() const; inline tvec3 wzz() const; inline tvec3 wzw() const; inline tvec3 wwx() const; inline tvec3 wwy() const; inline tvec3 wwz() const; inline tvec3 www() const; inline tvec4 xxxx() const; inline tvec4 xxxy() const; inline tvec4 xxxz() const; inline tvec4 xxxw() const; inline tvec4 xxyx() const; inline tvec4 xxyy() const; inline tvec4 xxyz() const; inline tvec4 xxyw() const; inline tvec4 xxzx() const; inline tvec4 xxzy() const; inline tvec4 xxzz() const; inline tvec4 xxzw() const; inline tvec4 xxwx() const; inline tvec4 xxwy() const; inline tvec4 xxwz() const; inline tvec4 xxww() const; inline tvec4 xyxx() const; inline tvec4 xyxy() const; inline tvec4 xyxz() const; inline tvec4 xyxw() const; inline tvec4 xyyx() const; inline tvec4 xyyy() const; inline tvec4 xyyz() const; inline tvec4 xyyw() const; inline tvec4 xyzx() const; inline tvec4 xyzy() const; inline tvec4 xyzz() const; inline tvec4 xyzw() const; inline tvec4 xywx() const; inline tvec4 xywy() const; inline tvec4 xywz() const; inline tvec4 xyww() const; inline tvec4 xzxx() const; inline tvec4 xzxy() const; inline tvec4 xzxz() const; inline tvec4 xzxw() const; inline tvec4 xzyx() const; inline tvec4 xzyy() const; inline tvec4 xzyz() const; inline tvec4 xzyw() const; inline tvec4 xzzx() const; inline tvec4 xzzy() const; inline tvec4 xzzz() const; inline tvec4 xzzw() const; inline tvec4 xzwx() const; inline tvec4 xzwy() const; inline tvec4 xzwz() const; inline tvec4 xzww() const; inline tvec4 xwxx() const; inline tvec4 xwxy() const; inline tvec4 xwxz() const; inline tvec4 xwxw() const; inline tvec4 xwyx() const; inline tvec4 xwyy() const; inline tvec4 xwyz() const; inline tvec4 xwyw() const; inline tvec4 xwzx() const; inline tvec4 xwzy() const; inline tvec4 xwzz() const; inline tvec4 xwzw() const; inline tvec4 xwwx() const; inline tvec4 xwwy() const; inline tvec4 xwwz() const; inline tvec4 xwww() const; inline tvec4 yxxx() const; inline tvec4 yxxy() const; inline tvec4 yxxz() const; inline tvec4 yxxw() const; inline tvec4 yxyx() const; inline tvec4 yxyy() const; inline tvec4 yxyz() const; inline tvec4 yxyw() const; inline tvec4 yxzx() const; inline tvec4 yxzy() const; inline tvec4 yxzz() const; inline tvec4 yxzw() const; inline tvec4 yxwx() const; inline tvec4 yxwy() const; inline tvec4 yxwz() const; inline tvec4 yxww() const; inline tvec4 yyxx() const; inline tvec4 yyxy() const; inline tvec4 yyxz() const; inline tvec4 yyxw() const; inline tvec4 yyyx() const; inline tvec4 yyyy() const; inline tvec4 yyyz() const; inline tvec4 yyyw() const; inline tvec4 yyzx() const; inline tvec4 yyzy() const; inline tvec4 yyzz() const; inline tvec4 yyzw() const; inline tvec4 yywx() const; inline tvec4 yywy() const; inline tvec4 yywz() const; inline tvec4 yyww() const; inline tvec4 yzxx() const; inline tvec4 yzxy() const; inline tvec4 yzxz() const; inline tvec4 yzxw() const; inline tvec4 yzyx() const; inline tvec4 yzyy() const; inline tvec4 yzyz() const; inline tvec4 yzyw() const; inline tvec4 yzzx() const; inline tvec4 yzzy() const; inline tvec4 yzzz() const; inline tvec4 yzzw() const; inline tvec4 yzwx() const; inline tvec4 yzwy() const; inline tvec4 yzwz() const; inline tvec4 yzww() const; inline tvec4 ywxx() const; inline tvec4 ywxy() const; inline tvec4 ywxz() const; inline tvec4 ywxw() const; inline tvec4 ywyx() const; inline tvec4 ywyy() const; inline tvec4 ywyz() const; inline tvec4 ywyw() const; inline tvec4 ywzx() const; inline tvec4 ywzy() const; inline tvec4 ywzz() const; inline tvec4 ywzw() const; inline tvec4 ywwx() const; inline tvec4 ywwy() const; inline tvec4 ywwz() const; inline tvec4 ywww() const; inline tvec4 zxxx() const; inline tvec4 zxxy() const; inline tvec4 zxxz() const; inline tvec4 zxxw() const; inline tvec4 zxyx() const; inline tvec4 zxyy() const; inline tvec4 zxyz() const; inline tvec4 zxyw() const; inline tvec4 zxzx() const; inline tvec4 zxzy() const; inline tvec4 zxzz() const; inline tvec4 zxzw() const; inline tvec4 zxwx() const; inline tvec4 zxwy() const; inline tvec4 zxwz() const; inline tvec4 zxww() const; inline tvec4 zyxx() const; inline tvec4 zyxy() const; inline tvec4 zyxz() const; inline tvec4 zyxw() const; inline tvec4 zyyx() const; inline tvec4 zyyy() const; inline tvec4 zyyz() const; inline tvec4 zyyw() const; inline tvec4 zyzx() const; inline tvec4 zyzy() const; inline tvec4 zyzz() const; inline tvec4 zyzw() const; inline tvec4 zywx() const; inline tvec4 zywy() const; inline tvec4 zywz() const; inline tvec4 zyww() const; inline tvec4 zzxx() const; inline tvec4 zzxy() const; inline tvec4 zzxz() const; inline tvec4 zzxw() const; inline tvec4 zzyx() const; inline tvec4 zzyy() const; inline tvec4 zzyz() const; inline tvec4 zzyw() const; inline tvec4 zzzx() const; inline tvec4 zzzy() const; inline tvec4 zzzz() const; inline tvec4 zzzw() const; inline tvec4 zzwx() const; inline tvec4 zzwy() const; inline tvec4 zzwz() const; inline tvec4 zzww() const; inline tvec4 zwxx() const; inline tvec4 zwxy() const; inline tvec4 zwxz() const; inline tvec4 zwxw() const; inline tvec4 zwyx() const; inline tvec4 zwyy() const; inline tvec4 zwyz() const; inline tvec4 zwyw() const; inline tvec4 zwzx() const; inline tvec4 zwzy() const; inline tvec4 zwzz() const; inline tvec4 zwzw() const; inline tvec4 zwwx() const; inline tvec4 zwwy() const; inline tvec4 zwwz() const; inline tvec4 zwww() const; inline tvec4 wxxx() const; inline tvec4 wxxy() const; inline tvec4 wxxz() const; inline tvec4 wxxw() const; inline tvec4 wxyx() const; inline tvec4 wxyy() const; inline tvec4 wxyz() const; inline tvec4 wxyw() const; inline tvec4 wxzx() const; inline tvec4 wxzy() const; inline tvec4 wxzz() const; inline tvec4 wxzw() const; inline tvec4 wxwx() const; inline tvec4 wxwy() const; inline tvec4 wxwz() const; inline tvec4 wxww() const; inline tvec4 wyxx() const; inline tvec4 wyxy() const; inline tvec4 wyxz() const; inline tvec4 wyxw() const; inline tvec4 wyyx() const; inline tvec4 wyyy() const; inline tvec4 wyyz() const; inline tvec4 wyyw() const; inline tvec4 wyzx() const; inline tvec4 wyzy() const; inline tvec4 wyzz() const; inline tvec4 wyzw() const; inline tvec4 wywx() const; inline tvec4 wywy() const; inline tvec4 wywz() const; inline tvec4 wyww() const; inline tvec4 wzxx() const; inline tvec4 wzxy() const; inline tvec4 wzxz() const; inline tvec4 wzxw() const; inline tvec4 wzyx() const; inline tvec4 wzyy() const; inline tvec4 wzyz() const; inline tvec4 wzyw() const; inline tvec4 wzzx() const; inline tvec4 wzzy() const; inline tvec4 wzzz() const; inline tvec4 wzzw() const; inline tvec4 wzwx() const; inline tvec4 wzwy() const; inline tvec4 wzwz() const; inline tvec4 wzww() const; inline tvec4 wwxx() const; inline tvec4 wwxy() const; inline tvec4 wwxz() const; inline tvec4 wwxw() const; inline tvec4 wwyx() const; inline tvec4 wwyy() const; inline tvec4 wwyz() const; inline tvec4 wwyw() const; inline tvec4 wwzx() const; inline tvec4 wwzy() const; inline tvec4 wwzz() const; inline tvec4 wwzw() const; inline tvec4 wwwx() const; inline tvec4 wwwy() const; inline tvec4 wwwz() const; inline tvec4 wwww() const; }; template struct tmat2 { tmat2() = default; tmat2(const tmat2 &) = default; tmat2 &operator=(const tmat2 &) = default; explicit inline tmat2(T v) noexcept { vec[0] = tvec2(v, T(0)); vec[1] = tvec2(T(0), v); } inline tmat2(const tvec2 &a, const tvec2 &b) noexcept { vec[0] = a; vec[1] = b; } inline tvec2 &operator[](size_t index) { return vec[index]; } inline const tvec2 &operator[](size_t index) const { return vec[index]; } private: tvec2 vec[2]; }; template struct tmat3 { tmat3() = default; tmat3(const tmat3 &) = default; tmat3 &operator=(const tmat3 &) = default; explicit inline tmat3(T v) noexcept { vec[0] = tvec3(v, T(0), T(0)); vec[1] = tvec3(T(0), v, T(0)); vec[2] = tvec3(T(0), T(0), v); } inline tmat3(const tvec3 &a, const tvec3 &b, const tvec3 &c) noexcept { vec[0] = a; vec[1] = b; vec[2] = c; } explicit inline tmat3(const tmat4 &m) noexcept { for (int col = 0; col < 3; col++) for (int row = 0; row < 3; row++) vec[col][row] = m[col][row]; } inline tvec3 &operator[](size_t index) { return vec[index]; } inline const tvec3 &operator[](size_t index) const { return vec[index]; } private: tvec3 vec[3]; }; template struct tmat4 { tmat4() = default; tmat4(const tmat4 &) = default; tmat4 &operator=(const tmat4 &) = default; explicit inline tmat4(T v) noexcept { vec[0] = tvec4(v, T(0), T(0), T(0)); vec[1] = tvec4(T(0), v, T(0), T(0)); vec[2] = tvec4(T(0), T(0), v, T(0)); vec[3] = tvec4(T(0), T(0), T(0), v); } explicit inline tmat4(const tmat3 &m) noexcept { vec[0] = tvec4(m[0], T(0)); vec[1] = tvec4(m[1], T(0)); vec[2] = tvec4(m[2], T(0)); vec[3] = tvec4(T(0), T(0), T(0), T(1)); } inline tmat4(const tvec4 &a, const tvec4 &b, const tvec4 &c, const tvec4 &d) noexcept { vec[0] = a; vec[1] = b; vec[2] = c; vec[3] = d; } inline tvec4 &operator[](size_t index) { return vec[index]; } inline const tvec4 &operator[](size_t index) const { return vec[index]; } private: tvec4 vec[4]; }; using uint = uint32_t; using vec2 = tvec2; using vec3 = tvec3; using vec4 = tvec4; using mat2 = tmat2; using mat3 = tmat3; using mat4 = tmat4; using dvec2 = tvec2; using dvec3 = tvec3; using dvec4 = tvec4; using dmat2 = tmat2; using dmat3 = tmat3; using dmat4 = tmat4; using ivec2 = tvec2; using ivec3 = tvec3; using ivec4 = tvec4; using uvec2 = tvec2; using uvec3 = tvec3; using uvec4 = tvec4; using u16vec2 = tvec2; using u16vec3 = tvec3; using u16vec4 = tvec4; using i16vec2 = tvec2; using i16vec3 = tvec3; using i16vec4 = tvec4; using u8vec2 = tvec2; using u8vec3 = tvec3; using u8vec4 = tvec4; using i8vec2 = tvec2; using i8vec3 = tvec3; using i8vec4 = tvec4; using bvec2 = tvec2; using bvec3 = tvec3; using bvec4 = tvec4; void transpose(mat4 &dst, const mat4 &src); void transpose_to_affine(vec4 dst[3], const mat4 &src); struct mat_affine { mat_affine() = default; mat_affine(const mat_affine &) = default; mat_affine &operator=(const mat_affine &) = default; explicit inline mat_affine(const mat4 &m) { transpose_to_affine(vec, m); } explicit inline mat_affine(const mat3 &m) : vec{{m[0][0], m[1][0], m[2][0], 0.0f}, {m[0][1], m[1][1], m[2][1], 0.0f}, {m[0][2], m[1][2], m[2][2], 0.0f}} { } explicit inline mat_affine(float v) : vec{{v, 0, 0, 0}, {0, v, 0, 0}, {0, 0, v, 0}} { } inline mat_affine(const vec4 &r0, const vec4 &r1, const vec4 &r2) : vec{r0, r1, r2} { } inline vec4 &operator[](size_t index) { return vec[index]; } inline const vec4 &operator[](size_t index) const { return vec[index]; } float get_uniform_scale() const; vec3 get_translation() const; // Based on identity view pointing to -Z axis, Y up. vec3 get_forward() const; vec3 get_right() const; vec3 get_up() const; mat4 to_mat4() const; void to_mat4(mat4 &m) const; inline mat3 to_mat3() const { return { vec3(vec[0][0], vec[1][0], vec[2][0]), vec3(vec[0][1], vec[1][1], vec[2][1]), vec3(vec[0][2], vec[1][2], vec[2][2]), }; } private: vec4 vec[3]; }; struct quat : private vec4 { quat() = default; quat(const quat &) = default; quat(float w_, float x_, float y_, float z_) : vec4(x_, y_, z_, w_) {} explicit inline quat(const vec4 &v) : vec4(v) {} inline quat(float w_, const vec3 &v_) : vec4(v_, w_) {} inline const vec4 &as_vec4() const { return *static_cast(this); } quat &operator=(const quat &) = default; using vec4::x; using vec4::y; using vec4::z; using vec4::w; }; template constexpr inline T pi() { return T(3.1415926535897932384626433832795028841971); } template constexpr inline T half_pi() { return T(0.5) * pi(); } template constexpr inline T one_over_root_two() { return T(0.7071067811865476); } }