mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
1323 lines
37 KiB
C++
1323 lines
37 KiB
C++
#pragma once
|
|
#include <blah_common.h>
|
|
#include <blah_calc.h>
|
|
|
|
namespace Blah
|
|
{
|
|
static constexpr double epsilon = 0.000001;
|
|
|
|
template<class T> struct Vec2;
|
|
template<class T> struct Vec3;
|
|
template<class T> struct Vec4;
|
|
template<class T> struct Mat3x2;
|
|
template<class T> struct Mat4x4;
|
|
template<class T> struct Rect;
|
|
template<class T> struct Quad;
|
|
template<class T> struct Line;
|
|
template<class T> struct Circle;
|
|
|
|
using Vec2f = Vec2<float>;
|
|
using Vec2d = Vec2<double>;
|
|
using Vec2i = Vec2<int>;
|
|
using Point = Vec2<int>;
|
|
using Vec3f = Vec3<float>;
|
|
using Vec3d = Vec3<double>;
|
|
using Vec4f = Vec4<float>;
|
|
using Vec4d = Vec4<double>;
|
|
using Mat3x2f = Mat3x2<float>;
|
|
using Mat3x2d = Mat3x2<double>;
|
|
using Mat4x4f = Mat4x4<float>;
|
|
using Mat4x4d = Mat4x4<double>;
|
|
using Rectf = Rect<float>;
|
|
using Rectd = Rect<double>;
|
|
using Recti = Rect<int>;
|
|
using Quadf = Quad<float>;
|
|
using Quadd = Quad<double>;
|
|
using Linef = Line<float>;
|
|
using Lined = Line<double>;
|
|
using Circlef = Circle<float>;
|
|
using Circled = Circle<double>;
|
|
|
|
template<class T>
|
|
struct Vec2
|
|
{
|
|
T x;
|
|
T y;
|
|
|
|
constexpr Vec2();
|
|
|
|
template<class X, class Y>
|
|
constexpr Vec2(X x, Y y);
|
|
|
|
template<class K>
|
|
constexpr Vec2(const Vec2<K>& vector);
|
|
|
|
constexpr Vec2 operator+(const Vec2& rhs) const;
|
|
constexpr Vec2 operator-(const Vec2& rhs) const;
|
|
constexpr Vec2 operator/(const T rhs) const;
|
|
constexpr Vec2 operator*(const T rhs) const;
|
|
constexpr Vec2 operator*(const Vec2& rhs);
|
|
constexpr Vec2 operator-() const;
|
|
constexpr Vec2& operator+=(const Vec2& rhs);
|
|
constexpr Vec2& operator-=(const Vec2& rhs);
|
|
constexpr Vec2& operator/=(const Vec2& rhs);
|
|
constexpr Vec2& operator*=(const Vec2& rhs);
|
|
constexpr Vec2& operator/=(T rhs);
|
|
constexpr Vec2& operator*=(T rhs);
|
|
constexpr bool operator==(const Vec2& rhs) const;
|
|
constexpr bool operator!=(const Vec2& rhs) const;
|
|
|
|
constexpr Vec2 abs() const;
|
|
Vec2 normal() const;
|
|
constexpr Vec2 turn_right() const;
|
|
constexpr Vec2 turn_left() const;
|
|
T length() const;
|
|
constexpr T length_squared() const;
|
|
T angle() const;
|
|
static constexpr T dot(const Vec2& a, const Vec2& b);
|
|
static constexpr Vec2 transform(const Vec2& vec, const Mat3x2<T>& matrix);
|
|
static constexpr Vec2 transform_normal(const Vec2& vec, const Mat3x2<T>& matrix);
|
|
static Vec2 from_angle(T radians, T length = 1);
|
|
static constexpr Vec2 approach(const Vec2& t, const Vec2& target, T delta);
|
|
static constexpr Vec2 lerp(const Vec2& a, const Vec2& b, T t);
|
|
static constexpr Vec2 lerp_bezier(const Vec2& a, const Vec2& b, const Vec2& end, T t);
|
|
static constexpr Vec2 lerp_bezier(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& end, T t);
|
|
static constexpr Vec2 reflect(const Vec2& vector, const Vec2& normal);
|
|
static constexpr Vec2 min(const Vec2& a, const Vec2& b);
|
|
static constexpr Vec2 max(const Vec2& a, const Vec2& b);
|
|
|
|
static const Vec2 unit_x;
|
|
static const Vec2 unit_y;
|
|
static const Vec2 right;
|
|
static const Vec2 up;
|
|
static const Vec2 down;
|
|
static const Vec2 left;
|
|
static const Vec2 zero;
|
|
static const Vec2 one;
|
|
};
|
|
|
|
template<class T> const Vec2<T> Vec2<T>::unit_x = Vec2<T>(1, 0);
|
|
template<class T> const Vec2<T> Vec2<T>::unit_y = Vec2<T>(0, 1);
|
|
template<class T> const Vec2<T> Vec2<T>::right = Vec2<T>(1, 0);
|
|
template<class T> const Vec2<T> Vec2<T>::up = Vec2<T>(0, -1);
|
|
template<class T> const Vec2<T> Vec2<T>::down = Vec2<T>(0, 1);
|
|
template<class T> const Vec2<T> Vec2<T>::left = Vec2<T>(-1, 0);
|
|
template<class T> const Vec2<T> Vec2<T>::zero = Vec2<T>(0, 0);
|
|
template<class T> const Vec2<T> Vec2<T>::one = Vec2<T>(1, 1);
|
|
|
|
template<class T>
|
|
struct Vec3
|
|
{
|
|
T x;
|
|
T y;
|
|
T z;
|
|
|
|
constexpr Vec3();
|
|
|
|
template<class X, class Y, class Z>
|
|
constexpr Vec3(X x, Y y, Z z);
|
|
|
|
template<class K>
|
|
constexpr Vec3(const Vec3<K>& vector);
|
|
|
|
constexpr Vec3 operator +(const Vec3& rhs) const;
|
|
constexpr Vec3 operator -(const Vec3& rhs) const;
|
|
|
|
T length() const;
|
|
Vec3 normal() const;
|
|
|
|
static constexpr T dot(const Vec3& a, const Vec3& b);
|
|
static constexpr Vec3 cross(const Vec3& a, const Vec3& b);
|
|
};
|
|
|
|
template<class T>
|
|
struct Vec4
|
|
{
|
|
T x;
|
|
T y;
|
|
T z;
|
|
T w;
|
|
|
|
constexpr Vec4();
|
|
|
|
template<class X, class Y, class Z, class W>
|
|
constexpr Vec4(X x, Y y, Z z, W w);
|
|
|
|
template<class K>
|
|
constexpr Vec4(const Vec4<K>& vector);
|
|
};
|
|
|
|
template<class T>
|
|
struct Rect
|
|
{
|
|
T x;
|
|
T y;
|
|
T w;
|
|
T h;
|
|
|
|
constexpr Rect();
|
|
constexpr Rect(T x, T y, T w, T h);
|
|
|
|
template<class X, class Y, class W, class H>
|
|
constexpr Rect(X x, Y y, W w, H h);
|
|
|
|
template<class K>
|
|
constexpr Rect(const Rect<K>& rect);
|
|
|
|
constexpr Rect operator+(const Vec2<T>& rhs) const;
|
|
constexpr Rect operator-(const Vec2<T>& rhs) const;
|
|
constexpr Rect& operator+=(const Vec2<T>& rhs);
|
|
constexpr Rect& operator-=(const Vec2<T>& rhs);
|
|
constexpr bool operator==(const Rect& rhs) const;
|
|
constexpr bool operator!=(const Rect& rhs) const;
|
|
|
|
constexpr T left() const;
|
|
constexpr T right() const;
|
|
constexpr T top() const;
|
|
constexpr T bottom() const;
|
|
constexpr Vec2<T> center() const;
|
|
constexpr T center_x() const;
|
|
constexpr T center_y() const;
|
|
constexpr Vec2<T> top_left() const;
|
|
constexpr Vec2<T> top_right() const;
|
|
constexpr Vec2<T> bottom_right() const;
|
|
constexpr Vec2<T> bottom_left() const;
|
|
constexpr Vec2<T> center_left() const;
|
|
constexpr Vec2<T> center_right() const;
|
|
constexpr Vec2<T> middle_top() const;
|
|
constexpr Vec2<T> middle_bottom() const;
|
|
constexpr Line<T> left_line() const;
|
|
constexpr Line<T> right_line() const;
|
|
constexpr Line<T> top_line() const;
|
|
constexpr Line<T> bottom_line() const;
|
|
|
|
constexpr bool contains(const Vec2<T>& pt) const;
|
|
constexpr bool contains(const Rect& rect) const;
|
|
constexpr bool overlaps(const Rect& rect) const;
|
|
constexpr Rect overlap_rect(const Rect& other) const;
|
|
constexpr bool intersects(const Line<T>& line) const;
|
|
constexpr bool intersects(const Line<T>& line, Vec2<T>* out_intersection_point) const;
|
|
constexpr bool intersects(const Vec2<T>& line_from, const Vec2<T>& line_to) const;
|
|
constexpr bool intersects(const Vec2<T>& line_from, const Vec2<T>& line_to, Vec2<T>* out_intersection_point) const;
|
|
constexpr Vec2<T> intersection_point(const Line<T>& line) const;
|
|
constexpr Vec2<T> intersection_point(const Vec2<T>& line_from, const Vec2<T>& line_to) const;
|
|
|
|
constexpr Rect scale(T s) const;
|
|
constexpr Rect scale(T sx, T sy) const;
|
|
constexpr Rect inflate(T amount) const;
|
|
constexpr Rect inflate(T amount_x, T amount_y) const;
|
|
|
|
// Rect Sectors:
|
|
// 0101 0100 0110
|
|
// 0001 0000 0010
|
|
// 1001 1000 1010
|
|
// 0000 = inside rectangle, all others refer to sectors relative to the rectangle
|
|
constexpr u8 get_sector(const Vec2<T>& pt) const;
|
|
|
|
static constexpr Rect transform(const Rect& rect, const Mat3x2<T>& matrix);
|
|
static constexpr Rect from_points(const Vec2<T>& from, const Vec2<T>& to);
|
|
};
|
|
|
|
template<class T>
|
|
struct Circle
|
|
{
|
|
Vec2<T> center;
|
|
T radius;
|
|
|
|
constexpr Circle();
|
|
constexpr Circle(T x, T y, T radius);
|
|
constexpr Circle(const Vec2<T>& center, T radius);
|
|
|
|
template<class K>
|
|
constexpr Circle(const Circle<K>& circle);
|
|
|
|
constexpr void project(const Vec2<T>& axis, T* min, T* max) const;
|
|
};
|
|
|
|
template<class T>
|
|
struct Quad
|
|
{
|
|
Vec2<T> a;
|
|
Vec2<T> b;
|
|
Vec2<T> c;
|
|
Vec2<T> d;
|
|
|
|
constexpr Quad();
|
|
constexpr Quad(const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c, const Vec2<T>& d);
|
|
|
|
constexpr void project(const Vec2<T>& axis, T* min, T* max) const;
|
|
};
|
|
|
|
template<class T>
|
|
struct Line
|
|
{
|
|
Vec2<T> a;
|
|
Vec2<T> b;
|
|
|
|
constexpr Line();
|
|
constexpr Line(const Vec2<T>& a, const Vec2<T>& b);
|
|
constexpr Line(T x0, T y0, T x1, T y1);
|
|
|
|
constexpr Rect<T> bounds() const;
|
|
constexpr Vec2<T> closest_point(const Vec2<T>& pt) const;
|
|
constexpr bool intersects(const Rect<T>& rect, Vec2<T>* out_intersection_point = nullptr) const;
|
|
constexpr bool intersects(const Line<T>& line, Vec2<T>* out_intersection_point = nullptr) const;
|
|
|
|
constexpr void project(const Vec2<T>& axis, T* min, T* max) const;
|
|
|
|
constexpr Line operator +(const Vec2<T>& rhs) const;
|
|
constexpr Line operator -(const Vec2<T>& rhs) const;
|
|
};
|
|
|
|
template<class T>
|
|
struct Mat3x2
|
|
{
|
|
T m11;
|
|
T m12;
|
|
T m21;
|
|
T m22;
|
|
T m31;
|
|
T m32;
|
|
|
|
constexpr Mat3x2();
|
|
constexpr Mat3x2(T m11, T m12, T m21, T m22, T m31, T m32);
|
|
|
|
template<class K>
|
|
constexpr Mat3x2(const Mat3x2<K>& matrix);
|
|
|
|
static const Mat3x2 identity;
|
|
|
|
constexpr Mat3x2 invert() const;
|
|
T scaling_factor() const;
|
|
|
|
static constexpr Mat3x2 create_translation(const Vec2<T>& position);
|
|
static constexpr Mat3x2 create_translation(T x, T y);
|
|
static constexpr Mat3x2 create_scale(T scale);
|
|
static constexpr Mat3x2 create_scale(T x, T y);
|
|
static constexpr Mat3x2 create_scale(const Vec2<T>& scale);
|
|
static constexpr Mat3x2 create_scale(T scale, const Vec2<T>& center_point);
|
|
static constexpr Mat3x2 create_scale(const Vec2<T>& scale, const Vec2<T>& center_point);
|
|
static constexpr Mat3x2 create_scale(T scale_x, T scale_y, const Vec2<T>& center_point);
|
|
static Mat3x2 create_rotation(T radians);
|
|
static Mat3x2 create_transform(const Vec2<T>& position, const Vec2<T>& origin, const Vec2<T>& scale, T rotation);
|
|
static constexpr Mat3x2 add(const Mat3x2& a, const Mat3x2& b);
|
|
static constexpr Mat3x2 subtract(const Mat3x2& a, const Mat3x2& b);
|
|
static constexpr Mat3x2 multiply(const Mat3x2& a, const Mat3x2& b);
|
|
|
|
constexpr Mat3x2 operator *(const Mat3x2& rhs) const;
|
|
constexpr Mat3x2 operator +(const Mat3x2& rhs) const;
|
|
constexpr Mat3x2 operator -(const Mat3x2& rhs) const;
|
|
constexpr Mat3x2& operator *=(const Mat3x2& rhs);
|
|
constexpr bool operator==(const Mat3x2& rhs);
|
|
constexpr bool operator!=(const Mat3x2& rhs);
|
|
};
|
|
|
|
template<class T> const Mat3x2<T> Mat3x2<T>::identity = Mat3x2<T>(1, 0, 0, 1, 0, 0);
|
|
|
|
template<class T>
|
|
struct Mat4x4
|
|
{
|
|
T m11;
|
|
T m12;
|
|
T m13;
|
|
T m14;
|
|
|
|
T m21;
|
|
T m22;
|
|
T m23;
|
|
T m24;
|
|
|
|
T m31;
|
|
T m32;
|
|
T m33;
|
|
T m34;
|
|
|
|
T m41;
|
|
T m42;
|
|
T m43;
|
|
T m44;
|
|
|
|
Mat4x4();
|
|
Mat4x4(
|
|
T m11, T m12, T m13, T m14,
|
|
T m21, T m22, T m23, T m24,
|
|
T m31, T m32, T m33, T m34,
|
|
T m41, T m42, T m43, T m44);
|
|
|
|
static const Mat4x4 identity;
|
|
|
|
static constexpr Mat4x4 create_ortho(T width, T height, T z_near_plane, T z_far_plane);
|
|
static constexpr Mat4x4 create_ortho_offcenter(T left, T right, T bottom, T top, T z_near_plane, T z_far_plane);
|
|
static Mat4x4 create_perspective(T field_of_view, T ratio, T z_near_plane, T z_far_plane);
|
|
static constexpr Mat4x4 create_translation(T x, T y, T z);
|
|
static constexpr Mat4x4 create_scale(T x, T y, T z);
|
|
static Mat4x4 create_lookat(const Vec3<T>& position, const Vec3<T>& target, const Vec3<T>& up);
|
|
|
|
constexpr Mat4x4 operator* (const Mat4x4& rhs);
|
|
};
|
|
|
|
template<class T> const Mat4x4<T> Mat4x4<T>::identity = Mat4x4<T>(
|
|
1.0f, 0.0f, 0.0f, 0.0f,
|
|
0.0f, 1.0f, 0.0f, 0.0f,
|
|
0.0f, 0.0f, 1.0f, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
template<class T>
|
|
constexpr Vec2<T>::Vec2()
|
|
: x(0), y(0) {}
|
|
|
|
template<class T>
|
|
template<class X, class Y>
|
|
constexpr Vec2<T>::Vec2(X x, Y y)
|
|
: x(static_cast<T>(x)), y(static_cast<T>(y)) {}
|
|
|
|
template<class T>
|
|
template<class K>
|
|
constexpr Vec2<T>::Vec2(const Vec2<K>& vector)
|
|
: x(static_cast<T>(vector.x)), y(static_cast<T>(vector.y)) {}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::operator+(const Vec2& rhs) const {
|
|
return Vec2(x + rhs.x, y + rhs.y);
|
|
}
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::operator-(const Vec2& rhs) const {
|
|
return Vec2(x - rhs.x, y - rhs.y);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::operator-() const {
|
|
return Vec2(-x, -y);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::operator/(const T rhs) const {
|
|
return Vec2(x / rhs, y / rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::operator* (const T rhs) const {
|
|
return Vec2(x * rhs, y * rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::operator *(const Vec2& rhs) {
|
|
return Vec2(x * rhs.x, y * rhs.y);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T>& Vec2<T>::operator += (const Vec2& rhs) {
|
|
x += rhs.x;
|
|
y += rhs.y;
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T>& Vec2<T>::operator -= (const Vec2& rhs) {
|
|
x -= rhs.x;
|
|
y -= rhs.y;
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T>& Vec2<T>::operator /= (T rhs) {
|
|
x /= rhs;
|
|
y /= rhs;
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T>& Vec2<T>::operator *= (const Vec2 & rhs) {
|
|
x *= rhs.x;
|
|
y *= rhs.y;
|
|
return this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T>& Vec2<T>::operator *=(T rhs) {
|
|
x *= rhs;
|
|
y *= rhs;
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Vec2<T>::operator ==(const Vec2& rhs) const {
|
|
return Calc::abs(x - rhs.x) < epsilon && Calc::abs(y - rhs.y) < epsilon;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Vec2<T>::operator !=(const Vec2& rhs) const {
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::abs() const {
|
|
return Vec2(Calc::abs(x), Calc::abs(y));
|
|
}
|
|
|
|
template<class T>
|
|
Vec2<T> Vec2<T>::normal() const {
|
|
auto len = Calc::sqrt(x * x + y * y);
|
|
if (len <= 0)
|
|
return Vec2<T>(0, 0);
|
|
return Vec2(x / len, y / len);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::turn_right() const {
|
|
return Vec2(-y, x);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::turn_left() const {
|
|
return Vec2(y, -x);
|
|
}
|
|
|
|
template<class T>
|
|
T Vec2<T>::length() const {
|
|
return static_cast<T>(Calc::sqrt(static_cast<f32>(x * x + y * y)));
|
|
}
|
|
|
|
template<class T>
|
|
constexpr T Vec2<T>::length_squared() const {
|
|
return x * x + y * y;
|
|
}
|
|
|
|
template<class T>
|
|
T Vec2<T>::angle() const {
|
|
return Calc::atan2(y, x);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr T Vec2<T>::dot(const Vec2& a, const Vec2& b) {
|
|
return a.x * b.x + a.y * b.y;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::transform(const Vec2& vec, const Mat3x2<T>& matrix) {
|
|
return Vec2(
|
|
(vec.x * matrix.m11) + (vec.y * matrix.m21) + matrix.m31,
|
|
(vec.x * matrix.m12) + (vec.y * matrix.m22) + matrix.m32);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::transform_normal(const Vec2& vec, const Mat3x2<T>& matrix) {
|
|
return Vec2(
|
|
vec.x * matrix.m11 + vec.y * matrix.m21,
|
|
vec.x * matrix.m12 + vec.y * matrix.m22);
|
|
}
|
|
|
|
template<class T>
|
|
Vec2<T> Vec2<T>::from_angle(T radians, T length) {
|
|
return Vec2(
|
|
Calc::cos(radians) * length,
|
|
Calc::sin(radians) * length);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::approach(const Vec2& value, const Vec2& target, T delta) {
|
|
if ((value - target).length_squared() <= delta * delta)
|
|
return target;
|
|
return value + (target - value).normal() * delta;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::lerp(const Vec2& a, const Vec2& b, T t) {
|
|
if (t == 0)
|
|
return a;
|
|
else if (t == 1)
|
|
return b;
|
|
else
|
|
return a + (b - a) * t;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::lerp_bezier(const Vec2& a, const Vec2& b, const Vec2& end, T t) {
|
|
return lerp(lerp(a, b, t), lerp(b, end, t), t);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::lerp_bezier(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& end, T t) {
|
|
return lerp_bezier(lerp(a, b, t), lerp(b, c, t), lerp(c, end, t), t);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::reflect(const Vec2& vector, const Vec2& normal) {
|
|
auto dot = vector.x * normal.x + vector.y * normal.y;
|
|
return Vec2(
|
|
vector.x - 2 * dot * normal.x,
|
|
vector.y - 2 * dot * normal.y);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::min(const Vec2& a, const Vec2& b) {
|
|
return Vec2(Calc::min(a.x, b.x), Calc::min(a.y, b.y));
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Vec2<T>::max(const Vec2& a, const Vec2& b) {
|
|
return Vec2(Calc::max(a.x, b.x), Calc::max(a.y, b.y));
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec3<T>::Vec3()
|
|
: x(0), y(0), z(0) {}
|
|
|
|
template<class T>
|
|
template<class X, class Y, class Z>
|
|
constexpr Vec3<T>::Vec3(X x, Y y, Z z)
|
|
: x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)) {}
|
|
|
|
template<class T>
|
|
template<class K>
|
|
constexpr Vec3<T>::Vec3(const Vec3<K>& vector)
|
|
: x(static_cast<T>(vector.x)), y(static_cast<T>(vector.y)), z(static_cast<T>(vector.z)) {}
|
|
|
|
template<class T>
|
|
constexpr Vec3<T> Vec3<T>::operator+(const Vec3& rhs) const {
|
|
return Vec3(x + rhs.x, y + rhs.y, z + rhs.z);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec3<T> Vec3<T>::operator-(const Vec3& rhs) const {
|
|
return Vec3(x - rhs.x, y - rhs.y, z - rhs.z);
|
|
}
|
|
|
|
template<class T>
|
|
T Vec3<T>::length() const {
|
|
return Calc::sqrt(x * x + y * y + z * z);
|
|
}
|
|
|
|
template<class T>
|
|
Vec3<T> Vec3<T>::normal() const {
|
|
T len = length();
|
|
return Vec3(x / len, y / len, z / len);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr T Vec3<T>::dot(const Vec3& a, const Vec3& b) {
|
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec3<T> Vec3<T>::cross(const Vec3& a, const Vec3& b) {
|
|
return Vec3(
|
|
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>
|
|
constexpr Vec4<T>::Vec4()
|
|
: x(0), y(0), z(0), w(0) {}
|
|
|
|
template<class T>
|
|
template<class X, class Y, class Z, class W>
|
|
constexpr Vec4<T>::Vec4(X x, Y y, Z z, W w)
|
|
: x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)), w(static_cast<T>(w)) {}
|
|
|
|
template<class T>
|
|
template<class K>
|
|
constexpr Vec4<T>::Vec4(const Vec4<K>& vector)
|
|
: x(static_cast<T>(vector.x)), y(static_cast<T>(vector.y)), z(static_cast<T>(vector.z)), w(static_cast<T>(vector.w)) {}
|
|
|
|
template<class T>
|
|
constexpr Rect<T>::Rect()
|
|
: x(0), y(0), w(0), h(0) {}
|
|
|
|
template<class T>
|
|
constexpr Rect<T>::Rect(T x, T y, T w, T h)
|
|
: x(x), y(y), w(w), h(h) {}
|
|
|
|
template<class T>
|
|
template<class X, class Y, class W, class H>
|
|
constexpr Rect<T>::Rect(X x, Y y, W w, H h)
|
|
: x(static_cast<T>(x)), y(static_cast<T>(y)), w(static_cast<T>(w)), h(static_cast<T>(h)) {}
|
|
|
|
template<class T>
|
|
template<class K>
|
|
constexpr Rect<T>::Rect(const Rect<K>& rect)
|
|
: x(static_cast<T>(rect.x)), y(static_cast<T>(rect.y)), w(static_cast<T>(rect.w)), h(static_cast<T>(rect.h)) {}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::operator+(const Vec2<T>& rhs) const {
|
|
return Rect(x + rhs.x, y + rhs.y, w, h);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::operator-(const Vec2<T>& rhs) const {
|
|
return Rect(x - rhs.x, y - rhs.y, w, h);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T>& Rect<T>::operator+=(const Vec2<T>& rhs) {
|
|
x += rhs.x;
|
|
y += rhs.y;
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T>& Rect<T>::operator-=(const Vec2<T>& rhs) {
|
|
x -= rhs.x;
|
|
y -= rhs.y;
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::operator==(const Rect& rhs) const {
|
|
return Calc::abs(x - rhs.x) < epsilon && Calc::abs(y - rhs.y) < epsilon && Calc::abs(w - rhs.w) < epsilon && Calc::abs(h - rhs.h) < epsilon;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::operator!=(const Rect& rhs) const {
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr T Rect<T>::left() const { return x; }
|
|
template<class T>
|
|
constexpr T Rect<T>::right() const { return x + w; }
|
|
template<class T>
|
|
constexpr T Rect<T>::top() const { return y; }
|
|
template<class T>
|
|
constexpr T Rect<T>::bottom() const { return y + h; }
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::center() const { return Vec2<T>(x + w / 2, y + h / 2); }
|
|
template<class T>
|
|
constexpr T Rect<T>::center_x() const { return x + w / 2; }
|
|
template<class T>
|
|
constexpr T Rect<T>::center_y() const { return y + h / 2; }
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::top_left() const { return Vec2<T>(x, y); }
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::top_right() const { return Vec2<T>(x + w, y); }
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::bottom_right() const { return Vec2<T>(x + w, y + h); }
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::bottom_left() const { return Vec2<T>(x, y + h); }
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::center_left() const { return Vec2<T>(x, y + h / 2); }
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::center_right() const { return Vec2<T>(x + w, y + h / 2); }
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::middle_top() const { return Vec2<T>(x + w / 2, y); }
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::middle_bottom() const { return Vec2<T>(x + w / 2, y + h); }
|
|
|
|
template<class T>
|
|
constexpr Line<T> Rect<T>::left_line() const { return Line<T>(left(), top(), left(), bottom()); }
|
|
template<class T>
|
|
constexpr Line<T> Rect<T>::right_line() const { return Line<T>(right(), top(), right(), bottom()); }
|
|
template<class T>
|
|
constexpr Line<T> Rect<T>::top_line() const { return Line<T>(left(), top(), right(), top()); }
|
|
template<class T>
|
|
constexpr Line<T> Rect<T>::bottom_line() const { return Line<T>(left(), bottom(), right(), bottom()); }
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::contains(const Vec2<T>& pt) const {
|
|
return pt.x >= x && pt.x < x + w && pt.y >= y && pt.y < y + h;
|
|
}
|
|
template<class T>
|
|
constexpr bool Rect<T>::contains(const Rect& rect) const {
|
|
return rect.x >= x && rect.x + rect.w < x + w && rect.y >= y && rect.y + rect.h < y + h;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::overlaps(const Rect& rect) const {
|
|
return x + w >= rect.x && y + h >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::overlap_rect(const Rect& against) const {
|
|
Rect result;
|
|
|
|
if (x + w >= against.x && x < against.x + against.w)
|
|
{
|
|
result.x = Calc::max(x, against.x);
|
|
result.w = Calc::min(x + w, against.x + against.w) - result.x;
|
|
}
|
|
|
|
if (y + h >= against.y && y < against.y + against.h)
|
|
{
|
|
result.y = Calc::max(y, against.y);
|
|
result.h = Calc::min(y + h, against.y + against.h) - result.y;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::intersects(const Line<T>& line) const {
|
|
return line.intersects(*this);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::intersects(const Line<T>& line, Vec2<T>* out_intersection_point) const {
|
|
return line.intersects(*this, out_intersection_point);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::intersects(const Vec2<T>& line_from, const Vec2<T>& line_to) const {
|
|
return intersects(Line<T>(line_from, line_to));
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Rect<T>::intersects(const Vec2<T>& line_from, const Vec2<T>& line_to, Vec2<T>* out_intersection_point) const {
|
|
return intersects(Line<T>(line_from, line_to), out_intersection_point);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::intersection_point(const Line<T>& line) const {
|
|
Vec2<T> ret;
|
|
if (line.intersects(*this, &ret))
|
|
return ret;
|
|
return Vec2<T>::zero;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Rect<T>::intersection_point(const Vec2<T>& line_from, const Vec2<T>& line_to) const {
|
|
Vec2<T> ret;
|
|
if (Line<T>(line_from, line_to).intersects(*this, &ret))
|
|
return ret;
|
|
return Vec2<T>::zero;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::scale(T s) const {
|
|
return Rect<T>(x * s, y * s, w * s, h * s);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::scale(T sx, T sy) const {
|
|
return Rect<T>(x * sx, y * sy, w * sx, h * sy);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::inflate(T amount) const {
|
|
return Rect(x - amount, y - amount, w + amount * 2, h + amount * 2);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::inflate(T amount_x, T amount_y) const {
|
|
return Rect(x - amount_x, y - amount_y, w + amount_x * 2, h + amount_y * 2);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr u8 Rect<T>::get_sector(const Vec2<T>& pt) const
|
|
{
|
|
u8 result = 0;
|
|
if (pt.x < left())
|
|
result |= 0b0001;
|
|
else if (pt.x >= right())
|
|
result |= 0b0010;
|
|
if (pt.y < top())
|
|
result |= 0b0100;
|
|
else if (pt.y >= bottom())
|
|
result |= 0b1000;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::transform(const Rect& rect, const Mat3x2<T>& matrix) {
|
|
return Rect<T>(
|
|
(rect.x * matrix.m11) + (rect.y * matrix.m21) + matrix.m31,
|
|
(rect.x * matrix.m12) + (rect.y * matrix.m22) + matrix.m32,
|
|
(rect.w * matrix.m11) + (rect.h * matrix.m21),
|
|
(rect.w * matrix.m12) + (rect.h * matrix.m22));
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Rect<T>::from_points(const Vec2<T>& from, const Vec2<T>& to) {
|
|
auto min = Vec2<T>::min(from, to);
|
|
auto max = Vec2<T>::max(from, to);
|
|
return Rect<T>(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Quad<T>::Quad()
|
|
: a(), b(), c(), d() {}
|
|
|
|
template<class T>
|
|
constexpr Quad<T>::Quad(const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c, const Vec2<T>& d)
|
|
: a(a), b(b), c(c), d(d) {}
|
|
|
|
template<class T>
|
|
constexpr void Quad<T>::project(const Vec2<T>& axis, T* min, T* max) const {
|
|
T dot = Vec2<T>::dot(a, axis);
|
|
*min = dot;
|
|
*max = dot;
|
|
dot = Vec2<T>::dot(b, axis);
|
|
*min = dot < *min ? dot : *min;
|
|
*max = dot > *max ? dot : *max;
|
|
dot = Vec2<T>::dot(c, axis);
|
|
*min = dot < *min ? dot : *min;
|
|
*max = dot > *max ? dot : *max;
|
|
dot = Vec2<T>::dot(d, axis);
|
|
*min = dot < *min ? dot : *min;
|
|
*max = dot > *max ? dot : *max;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Circle<T>::Circle()
|
|
: center(0, 0), radius(0) {}
|
|
template<class T>
|
|
constexpr Circle<T>::Circle(T x, T y, T radius)
|
|
: center(x, y), radius(radius) {}
|
|
template<class T>
|
|
constexpr Circle<T>::Circle(const Vec2<T>& center, T radius)
|
|
: center(center), radius(radius) {}
|
|
|
|
template<class T>
|
|
template<class K>
|
|
constexpr Circle<T>::Circle(const Circle<K>& circle)
|
|
: center(Vec2<T>(static_cast<T>(circle.center.x), static_cast<T>(circle.center.y))), radius(static_cast<T>(circle.radius)) {}
|
|
|
|
template<class T>
|
|
constexpr void Circle<T>::project(const Vec2<T>& axis, T* min, T* max) const
|
|
{
|
|
*min = Vec2<T>::dot(center - axis * radius, axis);
|
|
*max = Vec2<T>::dot(center + axis * radius, axis);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Line<T>::Line()
|
|
: a(0, 0), b(0, 0) {}
|
|
|
|
template<class T>
|
|
constexpr Line<T>::Line(T x0, T y0, T x1, T y1)
|
|
: a(x0, y0), b(x1, y1) {}
|
|
|
|
template<class T>
|
|
constexpr Line<T>::Line(const Vec2<T>& a, const Vec2<T>& b)
|
|
: a(a), b(b) {}
|
|
|
|
template<class T>
|
|
constexpr Rect<T> Line<T>::bounds() const {
|
|
return Rect<T>::from_points(a, b);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Vec2<T> Line<T>::closest_point(const Vec2<T>& pt) const {
|
|
auto v = b - a;
|
|
auto w = pt - a;
|
|
auto t = Vec2<T>::dot(w, v) / (v.x * v.x + v.y * v.y);
|
|
if (t < 0) t = 0;
|
|
else if (t > 1) t = 1;
|
|
return v * t + a;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Line<T>::intersects(const Rect<T>& rect, Vec2<T>* out_intersection_point) const
|
|
{
|
|
u8 ca = rect.get_sector(a);
|
|
u8 cb = rect.get_sector(b);
|
|
|
|
if (ca == cb || (ca & cb) != 0)
|
|
return false;
|
|
|
|
u8 both = ca | cb;
|
|
|
|
// top
|
|
if ((both & 0b0100) != 0 && intersects(rect.top_line(), out_intersection_point))
|
|
return true;
|
|
|
|
// bottom
|
|
if ((both & 0b1000) != 0 && intersects(rect.bottom_line(), out_intersection_point))
|
|
return true;
|
|
|
|
// left
|
|
if ((both & 0b0001) != 0 && intersects(rect.left_line(), out_intersection_point))
|
|
return true;
|
|
|
|
// right
|
|
if ((both & 0b0010) != 0 && intersects(rect.right_line(), out_intersection_point))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Line<T>::intersects(const Line<T>& line, Vec2<T>* out_intersection_point) const
|
|
{
|
|
Vec2<T> e = b - a;
|
|
Vec2<T> d = line.b - line.a;
|
|
T e_dot_d_perp = e.x * d.y - e.y * d.x;
|
|
|
|
// if e dot d == 0, it means the lines are parallel
|
|
// so have infinite intersection points
|
|
if (e_dot_d_perp > -epsilon && e_dot_d_perp < epsilon)
|
|
return false;
|
|
|
|
Vec2<T> c = line.a - a;
|
|
T t = (c.x * d.y - c.y * d.x) / e_dot_d_perp;
|
|
if (t < 0 || t > 1)
|
|
return false;
|
|
|
|
T u = (c.x * e.y - c.y * e.x) / e_dot_d_perp;
|
|
if (u < 0 || u > 1)
|
|
return false;
|
|
|
|
if (out_intersection_point)
|
|
*out_intersection_point = (e * t) + a;
|
|
|
|
return true;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr void Line<T>::project(const Vec2<T>& axis, T* min, T* max) const {
|
|
T dot = a.x * axis.x + a.y * axis.y;
|
|
*min = dot;
|
|
*max = dot;
|
|
dot = b.x * axis.x + b.y * axis.y;
|
|
*min = dot < *min ? dot : *min;
|
|
*max = dot > *max ? dot : *max;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Line<T> Line<T>::operator+(const Vec2<T>& rhs) const {
|
|
return Line(a + rhs, b + rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Line<T> Line<T>::operator-(const Vec2<T>& rhs) const {
|
|
return Line(a - rhs, b - rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T>::Mat3x2()
|
|
: m11(0), m12(0), m21(0), m22(0), m31(0), m32(0) {}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T>::Mat3x2(T m11, T m12, T m21, T m22, T m31, T m32)
|
|
: m11(m11), m12(m12), m21(m21), m22(m22), m31(m31), m32(m32) {}
|
|
|
|
template<class T>
|
|
template<class K>
|
|
constexpr Mat3x2<T>::Mat3x2(const Mat3x2<K>& m)
|
|
: m11(static_cast<T>(m.m11)), m12(static_cast<T>(m.m12))
|
|
, m21(static_cast<T>(m.m21)), m22(static_cast<T>(m.m22))
|
|
, m31(static_cast<T>(m.m31)), m32(static_cast<T>(m.m32)) {}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::invert() const {
|
|
auto det = (m11 * m22) - (m21 * m12);
|
|
auto inv_det = 1 / det;
|
|
|
|
return Mat3x2<T>
|
|
(
|
|
m22 * inv_det,
|
|
-m12 * inv_det,
|
|
-m21 * inv_det,
|
|
m11 * inv_det,
|
|
(m21 * m32 - m31 * m22) * inv_det,
|
|
(m31 * m12 - m11 * m32) * inv_det
|
|
);
|
|
}
|
|
|
|
template<class T>
|
|
T Mat3x2<T>::scaling_factor() const {
|
|
return Calc::sqrt(m11 * m11 + m12 * m12);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_translation(const Vec2<T>& position) {
|
|
return Mat3x2(1, 0, 0, 1, position.x, position.y);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_translation(T x, T y) {
|
|
return Mat3x2(1, 0, 0, 1, x, y);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_scale(T scale) {
|
|
return Mat3x2(scale, 0, 0, scale, 0, 0);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_scale(T x, T y) {
|
|
return Mat3x2(x, 0, 0, y, 0, 0);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_scale(const Vec2<T>& scale) {
|
|
return Mat3x2(scale.x, 0, 0, scale.y, 0, 0);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_scale(T scale, const Vec2<T>& center_point) {
|
|
auto tx = center_point.x * (1 - scale);
|
|
auto ty = center_point.y * (1 - scale);
|
|
|
|
Mat3x2<T> result;
|
|
result.m11 = scale;
|
|
result.m12 = 0;
|
|
result.m21 = 0;
|
|
result.m22 = scale;
|
|
result.m31 = tx;
|
|
result.m32 = ty;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_scale(const Vec2<T>& scale, const Vec2<T>& center_point) {
|
|
auto tx = center_point.x * (1 - scale.x);
|
|
auto ty = center_point.y * (1 - scale.y);
|
|
|
|
Mat3x2<T> result;
|
|
result.m11 = scale.x;
|
|
result.m12 = 0;
|
|
result.m21 = 0;
|
|
result.m22 = scale.y;
|
|
result.m31 = tx;
|
|
result.m32 = ty;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::create_scale(T scale_x, T scale_y, const Vec2<T>& center_point) {
|
|
auto tx = center_point.x * (1 - scale_x);
|
|
auto ty = center_point.y * (1 - scale_y);
|
|
|
|
Mat3x2<T> result;
|
|
result.m11 = scale_x;
|
|
result.m12 = 0;
|
|
result.m21 = 0;
|
|
result.m22 = scale_y;
|
|
result.m31 = tx;
|
|
result.m32 = ty;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
Mat3x2<T> Mat3x2<T>::create_rotation(T radians) {
|
|
auto c = Calc::cos(radians);
|
|
auto s = Calc::sin(radians);
|
|
return Mat3x2<T>(c, s, -s, c, 0, 0);
|
|
}
|
|
|
|
template<class T>
|
|
Mat3x2<T> Mat3x2<T>::create_transform(const Vec2<T>& position, const Vec2<T>& origin, const Vec2<T>& scale, T rotation) {
|
|
Mat3x2<T> matrix = identity;
|
|
if (origin.x != 0 || origin.y != 0)
|
|
matrix = create_translation(-origin.x, -origin.y);
|
|
if (scale.x != 1 || scale.y != 1)
|
|
matrix = matrix * create_scale(scale);
|
|
if (rotation != 0)
|
|
matrix = matrix * create_rotation(rotation);
|
|
if (position.x != 0 || position.y != 0)
|
|
matrix = matrix * create_translation(position);
|
|
return matrix;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::add(const Mat3x2& a, const Mat3x2& b) {
|
|
return Mat3x2(
|
|
a.m11 + b.m11,
|
|
a.m12 + b.m12,
|
|
a.m21 + b.m21,
|
|
a.m22 + b.m22,
|
|
a.m31 + b.m31,
|
|
a.m32 + b.m32);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::subtract(const Mat3x2& a, const Mat3x2& b) {
|
|
return Mat3x2(
|
|
a.m11 - b.m11,
|
|
a.m12 - b.m12,
|
|
a.m21 - b.m21,
|
|
a.m22 - b.m22,
|
|
a.m31 - b.m31,
|
|
a.m32 - b.m32);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::multiply(const Mat3x2& a, const Mat3x2& b) {
|
|
return Mat3x2(a.m11 * b.m11 + a.m12 * b.m21,
|
|
a.m11 * b.m12 + a.m12 * b.m22,
|
|
a.m21 * b.m11 + a.m22 * b.m21,
|
|
a.m21 * b.m12 + a.m22 * b.m22,
|
|
a.m31 * b.m11 + a.m32 * b.m21 + b.m31,
|
|
a.m31 * b.m12 + a.m32 * b.m22 + b.m32);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::operator *(const Mat3x2& rhs) const {
|
|
return multiply(*this, rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::operator +(const Mat3x2& rhs) const {
|
|
return add(*this, rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T> Mat3x2<T>::operator -(const Mat3x2& rhs) const {
|
|
return subtract(*this, rhs);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat3x2<T>& Mat3x2<T>::operator *=(const Mat3x2& rhs) {
|
|
*this = multiply(*this, rhs);
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Mat3x2<T>::operator==(const Mat3x2& rhs) {
|
|
return
|
|
Calc::abs(m11 - rhs.m11) < epsilon &&
|
|
Calc::abs(m12 - rhs.m12) < epsilon &&
|
|
Calc::abs(m21 - rhs.m21) < epsilon &&
|
|
Calc::abs(m22 - rhs.m22) < epsilon &&
|
|
Calc::abs(m31 - rhs.m31) < epsilon &&
|
|
Calc::abs(m32 - rhs.m32) < epsilon;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr bool Mat3x2<T>::operator!=(const Mat3x2& rhs) {
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
template<class T>
|
|
Mat4x4<T>::Mat4x4() :
|
|
m11(0.0f), m12(0.0f), m13(0.0f), m14(0.0f),
|
|
m21(0.0f), m22(0.0f), m23(0.0f), m24(0.0f),
|
|
m31(0.0f), m32(0.0f), m33(0.0f), m34(0.0f),
|
|
m41(0.0f), m42(0.0f), m43(0.0f), m44(0.0f) {}
|
|
|
|
template<class T>
|
|
Mat4x4<T>::Mat4x4(
|
|
T m11, T m12, T m13, T m14,
|
|
T m21, T m22, T m23, T m24,
|
|
T m31, T m32, T m33, T m34,
|
|
T m41, T m42, T m43, T m44) :
|
|
m11(m11), m12(m12), m13(m13), m14(m14),
|
|
m21(m21), m22(m22), m23(m23), m24(m24),
|
|
m31(m31), m32(m32), m33(m33), m34(m34),
|
|
m41(m41), m42(m42), m43(m43), m44(m44) {}
|
|
|
|
template<class T>
|
|
constexpr Mat4x4<T> Mat4x4<T>::create_ortho(T width, T height, T z_near_plane, T z_far_plane) {
|
|
Mat4x4<T> result = identity;
|
|
result.m11 = 2 / width;
|
|
result.m12 = result.m13 = result.m14 = 0;
|
|
result.m22 = -2 / height;
|
|
result.m21 = result.m23 = result.m24 = 0;
|
|
result.m33 = 1 / (z_near_plane - z_far_plane);
|
|
result.m31 = result.m32 = result.m34 = 0;
|
|
result.m41 = result.m42 = 0;
|
|
result.m43 = z_near_plane / (z_near_plane - z_far_plane);
|
|
result.m44 = 1;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat4x4<T> Mat4x4<T>::create_ortho_offcenter(T left, T right, T bottom, T top, T z_near_plane, T z_far_plane) {
|
|
Mat4x4<T> result = identity;
|
|
result.m11 = 2 / (right - left);
|
|
result.m12 = result.m13 = result.m14 = 0;
|
|
result.m22 = 2 / (top - bottom);
|
|
result.m21 = result.m23 = result.m24 = 0;
|
|
result.m33 = 1 / (z_near_plane - z_far_plane);
|
|
result.m31 = result.m32 = result.m34 = 0;
|
|
result.m41 = (left + right) / (left - right);
|
|
result.m42 = (top + bottom) / (bottom - top);
|
|
result.m43 = z_near_plane / (z_near_plane - z_far_plane);
|
|
result.m44 = 1;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
Mat4x4<T> Mat4x4<T>::create_perspective(T field_of_view, T ratio, T z_near_plane, T z_far_plane) {
|
|
auto scale_x = 1 / Calc::tan(field_of_view * 0.5);
|
|
auto scale_y = scale_x / ratio;
|
|
|
|
Mat4x4 result;
|
|
result.m11 = scale_y;
|
|
result.m12 = result.m13 = result.m14 = 0;
|
|
result.m22 = scale_x;
|
|
result.m21 = result.m23 = result.m24 = 0;
|
|
result.m31 = result.m32 = 0;
|
|
result.m33 = z_far_plane / (z_near_plane - z_far_plane);
|
|
result.m34 = -1;
|
|
result.m41 = result.m42 = result.m44 = 0;
|
|
result.m43 = z_near_plane * z_far_plane / (z_near_plane - z_far_plane);
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat4x4<T> Mat4x4<T>::create_translation(T x, T y, T z) {
|
|
Mat4x4 result = identity;
|
|
result.m41 = x;
|
|
result.m42 = y;
|
|
result.m43 = z;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat4x4<T> Mat4x4<T>::create_scale(T x, T y, T z) {
|
|
Mat4x4 result = identity;
|
|
result.m11 = x;
|
|
result.m22 = y;
|
|
result.m33 = z;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
Mat4x4<T> Mat4x4<T>::create_lookat(const Vec3<T>& position, const Vec3<T>& target, const Vec3<T>& up) {
|
|
auto zaxis = (position - target).normal();
|
|
auto xaxis = Vec3<T>::cross(up, zaxis).normal();
|
|
auto yaxis = Vec3<T>::cross(zaxis, xaxis);
|
|
|
|
Mat4x4 result;
|
|
result.m11 = xaxis.x;
|
|
result.m12 = yaxis.x;
|
|
result.m13 = zaxis.x;
|
|
result.m14 = 0.0f;
|
|
result.m21 = xaxis.y;
|
|
result.m22 = yaxis.y;
|
|
result.m23 = zaxis.y;
|
|
result.m24 = 0.0f;
|
|
result.m31 = xaxis.z;
|
|
result.m32 = yaxis.z;
|
|
result.m33 = zaxis.z;
|
|
result.m34 = 0.0f;
|
|
result.m41 = -Vec3<T>::dot(xaxis, position);
|
|
result.m42 = -Vec3<T>::dot(yaxis, position);
|
|
result.m43 = -Vec3<T>::dot(zaxis, position);
|
|
result.m44 = 1.0f;
|
|
return result;
|
|
}
|
|
|
|
template<class T>
|
|
constexpr Mat4x4<T> Mat4x4<T>::operator*(const Mat4x4& rhs) {
|
|
Mat4x4 m;
|
|
|
|
m.m11 = m11 * rhs.m11 + m12 * rhs.m21 + m13 * rhs.m31 + m14 * rhs.m41;
|
|
m.m12 = m11 * rhs.m12 + m12 * rhs.m22 + m13 * rhs.m32 + m14 * rhs.m42;
|
|
m.m13 = m11 * rhs.m13 + m12 * rhs.m23 + m13 * rhs.m33 + m14 * rhs.m43;
|
|
m.m14 = m11 * rhs.m14 + m12 * rhs.m24 + m13 * rhs.m34 + m14 * rhs.m44;
|
|
|
|
m.m21 = m21 * rhs.m11 + m22 * rhs.m21 + m23 * rhs.m31 + m24 * rhs.m41;
|
|
m.m22 = m21 * rhs.m12 + m22 * rhs.m22 + m23 * rhs.m32 + m24 * rhs.m42;
|
|
m.m23 = m21 * rhs.m13 + m22 * rhs.m23 + m23 * rhs.m33 + m24 * rhs.m43;
|
|
m.m24 = m21 * rhs.m14 + m22 * rhs.m24 + m23 * rhs.m34 + m24 * rhs.m44;
|
|
|
|
m.m31 = m31 * rhs.m11 + m32 * rhs.m21 + m33 * rhs.m31 + m34 * rhs.m41;
|
|
m.m32 = m31 * rhs.m12 + m32 * rhs.m22 + m33 * rhs.m32 + m34 * rhs.m42;
|
|
m.m33 = m31 * rhs.m13 + m32 * rhs.m23 + m33 * rhs.m33 + m34 * rhs.m43;
|
|
m.m34 = m31 * rhs.m14 + m32 * rhs.m24 + m33 * rhs.m34 + m34 * rhs.m44;
|
|
|
|
m.m41 = m41 * rhs.m11 + m42 * rhs.m21 + m43 * rhs.m31 + m44 * rhs.m41;
|
|
m.m42 = m41 * rhs.m12 + m42 * rhs.m22 + m43 * rhs.m32 + m44 * rhs.m42;
|
|
m.m43 = m41 * rhs.m13 + m42 * rhs.m23 + m43 * rhs.m33 + m44 * rhs.m43;
|
|
m.m44 = m41 * rhs.m14 + m42 * rhs.m24 + m43 * rhs.m34 + m44 * rhs.m44;
|
|
|
|
return m;
|
|
}
|
|
}
|