Skip to content

Instantly share code, notes, and snippets.

@W4RH4WK
Created October 13, 2023 22:20
Show Gist options
  • Save W4RH4WK/962a181472c941285e4866b698207d84 to your computer and use it in GitHub Desktop.
Save W4RH4WK/962a181472c941285e4866b698207d84 to your computer and use it in GitHub Desktop.
////////////////////////////////////////////////////////////
// Vector 2D
template <typename T>
struct Vec2T {
constexpr Vec2T() = default;
constexpr Vec2T(T v) : x(v), y(v) {}
constexpr Vec2T(T x, T y) : x(x), y(y) {}
constexpr Vec2T(const Vec2T&) = default;
constexpr Vec2T& operator=(const Vec2T&) = default;
constexpr Vec2T(Vec2T&&) noexcept = default;
constexpr Vec2T& operator=(Vec2T&&) noexcept = default;
constexpr Vec2T(glm::vec<2, T> v) : x(v.x), y(v.y) {}
constexpr operator glm::vec<2, T>() const { return {x, y}; }
constexpr Vec2T(b2Vec2 v) requires(std::is_same_v<T, float>) : x(v.x), y(v.y) {}
constexpr operator b2Vec2() const requires(std::is_same_v<T, float>) { return {x, y}; }
template <typename TT>
explicit constexpr operator Vec2T<TT>() const
{
return {TT(x), TT(y)};
}
constexpr double length() const { return glm::length(glm::vec<2, T>(*this)); }
constexpr double lengthSquared() const { return glm::length2(glm::vec<2, T>(*this)); }
constexpr double ratio() const { return double(x) / double(y); }
constexpr Vec2T& clampLength(double maximum)
{
if (lengthSquared() > maximum * maximum) {
auto l = length();
x = T(maximum * x / l);
y = T(maximum * y / l);
}
return *this;
}
constexpr Vec2T& rotate(T angle) { return *this = glm::rotate(glm::vec<2, T>(*this), angle); }
constexpr Vec2T& moveTowards(Vec2T target, Vec2T speed, float dt, T epsilon = T(1e-6))
{
x = Anker::moveTowards(x, target.x, speed.x, dt, epsilon);
y = Anker::moveTowards(y, target.y, speed.y, dt, epsilon);
return *this;
}
friend constexpr auto operator<=>(Vec2T, Vec2T) = default;
T x = 0;
T y = 0;
static const Vec2T Up, Down, Left, Right;
static const Vec2T WorldUp, WorldDown, WorldLeft, WorldRight;
};
// Default coordinate system: -Y is up
template <typename T>
const Vec2T<T> Vec2T<T>::Up{0, -1};
template <typename T>
const Vec2T<T> Vec2T<T>::Down{0, 1};
template <typename T>
const Vec2T<T> Vec2T<T>::Left{-1, 0};
template <typename T>
const Vec2T<T> Vec2T<T>::Right{1, 0};
// World coordinate system: +Y is up
template <typename T>
const Vec2T<T> Vec2T<T>::WorldUp{0, 1};
template <typename T>
const Vec2T<T> Vec2T<T>::WorldDown{0, -1};
template <typename T>
const Vec2T<T> Vec2T<T>::WorldLeft{-1, 0};
template <typename T>
const Vec2T<T> Vec2T<T>::WorldRight{1, 0};
template <typename T>
constexpr T dot(Vec2T<T> a, Vec2T<T> b)
{
return a.x * b.x + a.y * b.y;
}
template <typename T>
constexpr Vec2T<T>& operator+=(Vec2T<T>& a, Vec2T<T> b)
{
a.x += b.x;
a.y += b.y;
return a;
}
template <typename T>
constexpr Vec2T<T>& operator-=(Vec2T<T>& a, Vec2T<T> b)
{
a.x -= b.x;
a.y -= b.y;
return a;
}
template <typename T, typename C>
constexpr Vec2T<T>& operator*=(Vec2T<T>& v, C c)
{
v.x *= c;
v.y *= c;
return v;
}
template <typename T>
constexpr Vec2T<T>& operator*=(Vec2T<T>& a, Vec2T<T> b)
{
a.x *= b.x;
a.y *= b.y;
return a;
}
template <typename T, typename C>
constexpr Vec2T<T>& operator/=(Vec2T<T>& v, C c)
{
v.x /= c;
v.y /= c;
return v;
}
template <typename T>
constexpr Vec2T<T>& operator/=(Vec2T<T>& a, Vec2T<T> b)
{
a.x /= b.x;
a.y /= b.y;
return a;
}
// clang-format off
template <typename T>
constexpr Vec2T<T> operator-(Vec2T<T> v) { return {-v.x, -v.y}; }
template <typename T>
constexpr Vec2T<T> operator+(Vec2T<T> a, Vec2T<T> b) { return a += b; }
template <typename T>
constexpr Vec2T<T> operator-(Vec2T<T> a, Vec2T<T> b) { return a -= b; }
template <typename T, typename C>
constexpr Vec2T<T> operator*(C c, Vec2T<T> v) { return v *= c; }
template <typename T, typename C>
constexpr Vec2T<T> operator*(Vec2T<T> v, C c) { return v *= c; }
template <typename T>
constexpr Vec2T<T> operator*(Vec2T<T> a, Vec2T<T> b) { return a *= b; }
template <typename T, typename C>
constexpr Vec2T<T> operator/(Vec2T<T> v, C c) { return v /= c; }
template <typename T, typename C>
constexpr Vec2T<T> operator/(C c, Vec2T<T> v) { return {c / v.x, c / v.y}; }
template <typename T>
constexpr Vec2T<T> operator/(Vec2T<T> a, Vec2T<T> b) { return a /= b; }
// clang-format on
using Vec2 = Vec2T<float>;
using Vec2i = Vec2T<int>;
using Vec2u = Vec2T<unsigned>;
using Vec2d = Vec2T<double>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment