Skip to content

Instantly share code, notes, and snippets.

@romanlarionov
Last active January 16, 2019 00:44
Show Gist options
  • Save romanlarionov/e5dd854b52f371b320a00a846c8da8fd to your computer and use it in GitHub Desktop.
Save romanlarionov/e5dd854b52f371b320a00a846c8da8fd to your computer and use it in GitHub Desktop.
Single header file for templated vectors.
#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