Last active
January 16, 2019 00:44
-
-
Save romanlarionov/e5dd854b52f371b320a00a846c8da8fd to your computer and use it in GitHub Desktop.
Single header file for templated vectors.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _VECTOR_H | |
#define _VECTOR_H | |
#include <iostream> | |
#include <cmath> | |
template <class t> | |
struct Vec4; | |
template <class t> | |
struct Vec2 | |
{ | |
union | |
{ | |
struct { t x, y; }; | |
struct { t u, v; }; | |
t raw[2]; | |
}; | |
Vec2() : u(0), v(0) {} | |
Vec2(t _u) : u(_u), v(_u) {} | |
Vec2(t _u, t _v) : u(_u),v(_v) {} | |
Vec2<t> operator *(t n) const { return Vec2<t>(x * n, y * n); } | |
Vec2<t> operator +(const Vec2<t> &v) const { return Vec2<t>(x + v.x, y + v.y); } | |
Vec2<t> operator -(const Vec2<t> &v) const { return Vec2<t>(x - v.x, y - v.y); } | |
Vec2<t> operator *(const Vec2<t> &v) const { return Vec2<t>(x * v.x, y * v.y); } | |
Vec2<t> operator /(const Vec2<t> &v) const { return Vec2<t>(x / v.x, y / v.y); } | |
Vec2<t> operator -() const { return Vec2<t>(-x, -y); } | |
Vec2<t>& operator +=(Vec2<t> const& o) { x += o.x; y += o.y; return *this; } | |
Vec2<t>& operator -=(Vec2<t> const& o) { x -= o.x; y -= o.y; return *this; } | |
Vec2<t>& operator *=(Vec2<t> const& o) { x *= o.x; y *= o.y; return *this; } | |
Vec2<t>& operator /=(Vec2<t> const& o) { x /= o.x; y /= o.y; return *this; } | |
Vec2<t>& operator *=(t c) { x *= c; y *= c; return *this; } | |
Vec2<t>& operator /=(double c) { double cinv = 1.0 / c; x *= cinv; y *= cinv; return *this; } | |
t& operator [](int i) { return raw[i]; } | |
t operator [](int i) const { return raw[i]; } | |
template <class > friend std::ostream& operator<<(std::ostream &s, const Vec2<t> &v); | |
template <class > friend Vec2<t> operator *(t n, const Vec2<t> &v); | |
template <class > friend Vec2<t> operator +(t n, const Vec2<t> &v); | |
template <class > friend Vec2<t> operator -(t n, const Vec2<t> &v); | |
}; | |
template <class t> | |
struct Vec3 | |
{ | |
union | |
{ | |
struct { t x, y, z; }; | |
struct { t r, g, b; }; | |
struct { t ivert, iuv, inorm; }; | |
t raw[3]; | |
}; | |
Vec3() : x(0), y(0), z(0) {} | |
Vec3(t _x) : x(_x), y(_x), z(_x) {} | |
Vec3(Vec2<t> _v) : x(_v.x), y(_v.y), z(0) {} | |
Vec3(Vec2<t> _v, t _z) : x(_v.x), y(_v.y), z(_z) {} | |
Vec3(Vec4<t> _v) : x(_v.x), y(_v.y), z(_v.z) {} | |
Vec3(t _x, t _y, t _z) : x(_x),y(_y),z(_z) {} | |
Vec3<t> operator +(const Vec3<t> &v) const { return Vec3<t>(x + v.x, y + v.y, z + v.z); } | |
Vec3<t> operator -(const Vec3<t> &v) const { return Vec3<t>(x - v.x, y - v.y, z - v.z); } | |
Vec3<t> operator *(const Vec3<t> &v) const { return Vec3<t>(x * v.x, y * v.y, z * v.z); } | |
Vec3<t> operator -(t n) const { return Vec3<t>(x - n, y - n, z - n); } | |
Vec3<t> operator +(t n) const { return Vec3<t>(x + n, y + n, z + n); } | |
Vec3<t> operator *(t n) const { return Vec3<t>(x * n, y * n, z * n); } | |
Vec3<t> operator -() const { return Vec3<t>(-x, -y, -z); } | |
Vec3<t>& operator +=(Vec3<t> const& o) { x += o.x; y += o.y; z += o.z; return *this; } | |
Vec3<t>& operator -=(Vec3<t> const& o) { x -= o.x; y -= o.y; z -= o.z; return *this; } | |
Vec3<t>& operator *=(Vec3<t> const& o) { x *= o.x; y *= o.y; z *= o.z; return *this; } | |
Vec3<t>& operator /=(Vec3<t> const& o) { x /= o.x; y /= o.y; z /= o.z; return *this; } | |
Vec3<t>& operator *=(t c) { x *= c; y *= c; z *= c; return *this; } | |
Vec3<t>& operator /=(double c) { double cinv = 1.0 / c; x *= cinv; y *= cinv; z *= cinv; return *this; } | |
t& operator [](int i) { return raw[i]; } | |
t operator [](int i) const { return raw[i]; } | |
Vec3<t> textureToNormalSpace(Vec3<t> v) const { return Vec3<t>(2.0f * v - 1.0f); } | |
Vec3<t> normalToTextureSpace(Vec3<t> v) const { return Vec3<t>(0.5f * (1.0f + v)); } | |
double norm() const { return std::sqrt(x * x + y * y + z * z); } | |
double sqnorm() const { return x * x + y * y + z * z; } | |
Vec3<t>& normalize() { *this = (*this) * (1.0 / norm()); return *this; } | |
template <class > friend std::ostream& operator<<(std::ostream &s, const Vec3<t> &v); | |
template <class > friend Vec3<t> operator *(t n, const Vec3<t> &v); | |
template <class > friend Vec3<t> operator +(t n, const Vec3<t> &v); | |
template <class > friend Vec3<t> operator -(t n, const Vec3<t> &v); | |
}; | |
template <class t> | |
struct Vec4 | |
{ | |
union | |
{ | |
struct { t x, y, z, w; }; | |
struct { t r, g, b, a; }; | |
t raw[4]; | |
}; | |
Vec4() : x(0), y(0), z(0), w(0) {} | |
Vec4(t _x) : x(_x), y(_x), z(_x), w(_x) {} | |
Vec4(Vec2<t> _v) : x(_v.x), y(_v.y), z(0), w(0) {} | |
Vec4(Vec3<t> _v) : x(_v.x), y(_v.y), z(_v.z), w(0) {} | |
Vec4(Vec3<t> _v, t _w) : x(_v.x), y(_v.y), z(_v.z), w(_w) {} | |
Vec4(t _x, t _y, t _z, t _w) : x(_x),y(_y),z(_z),w(_w) {} | |
Vec4<t> operator +(const Vec4<t> &v) const { return Vec4<t>(x + v.x, y + v.y, z + v.z, w + v.w); } | |
Vec4<t> operator -(const Vec4<t> &v) const { return Vec4<t>(x - v.x, y - v.y, z - v.z, w - v.w); } | |
Vec4<t> operator *(const Vec4<t> &v) const { return Vec4<t>(x * v.x, y * v.y, z * v.z, w * v.w); } | |
Vec4<t> operator *(t n) const { return Vec4<t>(x * n, y * n, z * n, w * n); } | |
Vec4<t> operator -() const { return Vec4<t>(-x, -y, -z, -w); } | |
Vec4<t>& operator +=(Vec4<t> const& o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; } | |
Vec4<t>& operator -=(Vec4<t> const& o) { x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this; } | |
Vec4<t>& operator *=(Vec4<t> const& o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; } | |
Vec4<t>& operator /=(Vec4<t> const& o) { x /= o.x; y /= o.y; z /= o.z; w /= o.w; return *this; } | |
Vec4<t>& operator *=(t c) { x *= c; y *= c; z *= c; w *= c; return *this; } | |
Vec4<t>& operator /=(double c) { double cinv = 1.0 / c; x *= cinv; y *= cinv; z *= cinv; w *= cinv; return *this; } | |
t& operator [](int i) { return raw[i]; } | |
t operator [](int i) const { return raw[i]; } | |
Vec4<t> textureToNormalSpace(Vec4<t> v) const { Vec4<t>(2.0f * v - 1.0f); } | |
Vec4<t> normalToTextureSpace(Vec4<t> v) const { Vec4<t>(0.5f * (1.0f + v)); } | |
double norm() const { return std::sqrt(x * x + y * y + z * z + w * w); } | |
double sqnorm() const { return x * x + y * y + z * z + w * w; } | |
Vec4<t>& normalize() { *this = (*this) * (1.0 / norm()); return *this; } | |
template <class > friend std::ostream& operator<<(std::ostream &s, const Vec4<t> &v); | |
template <class > friend Vec4<t> operator *(t n, const Vec4<t> &v); | |
template <class > friend Vec4<t> operator +(t n, const Vec4<t> &v); | |
template <class > friend Vec4<t> operator -(t n, const Vec4<t> &v); | |
}; | |
/////////// | |
// Typedefs | |
typedef Vec2<float> Vec2f; | |
typedef Vec2<int> Vec2i; | |
typedef Vec2<unsigned int> Vec2u; | |
typedef Vec3<float> Vec3f; | |
typedef Vec3<int> Vec3i; | |
typedef Vec3<unsigned int> Vec3u; | |
typedef Vec4<float> Vec4f; | |
typedef Vec4<int> Vec4i; | |
typedef Vec4<unsigned int> Vec4u; | |
////////////////////// | |
// Left-hand operators | |
template <class t> | |
std::ostream& operator<<(std::ostream &s, const Vec2<t> &v) | |
{ | |
s << "(" << v.x << ", " << v.y << ")\n"; | |
return s; | |
} | |
template <class t> | |
std::ostream& operator<<(std::ostream &s, const Vec3<t> &v) | |
{ | |
s << "(" << v.x << ", " << v.y << ", " << v.z << ")\n"; | |
return s; | |
} | |
template <class t> | |
std::ostream& operator<<(std::ostream &s, const Vec4<t> &v) | |
{ | |
s << "(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")\n"; | |
return s; | |
} | |
template <class t> Vec2<t> operator +(t n, const Vec2<t> &v) { return Vec2<t>(n + v.x, n + v.y); } | |
template <class t> Vec2<t> operator -(t n, const Vec2<t> &v) { return Vec2<t>(n - v.x, n - v.y); } | |
template <class t> Vec2<t> operator *(t n, const Vec2<t> &v) { return Vec2<t>(v.x * n, v.y * n); } | |
template <class t> Vec3<t> operator +(t n, const Vec3<t> &v) { return Vec3<t>(n + v.x, n + v.y, n + v.z); } | |
template <class t> Vec3<t> operator -(t n, const Vec3<t> &v) { return Vec3<t>(n - v.x, n - v.y, n - v.z); } | |
template <class t> Vec3<t> operator *(t n, const Vec3<t> &v) { return Vec3<t>(v.x * n, v.y * n, v.z * n); } | |
template <class t> Vec4<t> operator +(t n, const Vec4<t> &v) { return Vec4<t>(n + v.x, n + v.y, n + v.z, n + v.w); } | |
template <class t> Vec4<t> operator -(t n, const Vec4<t> &v) { return Vec4<t>(n - v.x, n - v.y, n - v.z, n - v.w); } | |
template <class t> Vec4<t> operator *(t n, const Vec4<t> &v) { return Vec4<t>(v.x * n, v.y * n, v.z * n, v.w * n); } | |
////////////////////// | |
// Function operations | |
template <class t> t dot(const Vec2<t> &a, const Vec2<t> &b) { return a.x * b.x + a.y * b.y; } | |
template <class t> t dot(const Vec3<t> &a, const Vec3<t> &b) { return a.x * b.x + a.y * b.y + a.z * b.z; } | |
template <class t> t dot(const Vec4<t> &a, const Vec4<t> &b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } | |
template <class t> | |
Vec3<t> cross(const Vec3<t> &a, const Vec3<t> &b) | |
{ | |
return Vec3<t>(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); | |
} | |
template <class t> | |
Vec3<t> normalize(const Vec3<t> &a) | |
{ | |
return (1.0f / (float)a.norm()) * a; | |
} | |
template <class t> | |
Vec4<t> normalize(const Vec4<t> &a) | |
{ | |
return (1.0f / (float)a.norm()) * a; | |
} | |
template<class t> t min(const t &a, const t &b) { return (a < b) ? a : b; } | |
template<class t> t min(const Vec2<t> &a) { return min(a.x, a.y); } | |
template<class t> t min(const Vec3<t> &a) { return min(min(a.x, a.y), a.z); } | |
template<class t> t min(const Vec4<t> &a) { return min(min(min(a.x, a.y), a.z), a.w); } | |
template<class t> t max(const t &a, const t &b) { return (a > b) ? a : b; } | |
template<class t> t max(const Vec2<t> &a) { return max(a.x, a.y); } | |
template<class t> t max(const Vec3<t> &a) { return max(max(a.x, a.y), a.z); } | |
template<class t> t max(const Vec4<t> &a) { return max(max(max(a.x, a.y), a.z), a.w); } | |
template <class t> | |
t clamp(const t &n, const t a, const t b) | |
{ | |
return max(min(n, b), a); | |
} | |
template <class t> | |
Vec2<t> clamp(const Vec2<t> &v, const t a, const t b) | |
{ | |
return Vec2<t>(clamp(v.x, a, b), clamp(v.y, a, b)); | |
} | |
template <class t> | |
Vec3<t> clamp(const Vec3<t> &v, const t a, const t b) | |
{ | |
return Vec3<t>(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b)); | |
} | |
template <class t> | |
Vec4<t> clamp(const Vec4<t> &v, const t a, const t b) | |
{ | |
return Vec4<t>(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b), clamp(v.w, a, b)); | |
} | |
#endif // _VECTOR_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment