diff --git a/build/android/app/CMakeLists.txt b/build/android/app/CMakeLists.txt index 3a59605..4b4763c 100644 --- a/build/android/app/CMakeLists.txt +++ b/build/android/app/CMakeLists.txt @@ -54,7 +54,6 @@ add_library(kaliber SHARED ../../../src/base/sinc_resampler.cc ../../../src/base/task_runner.cc ../../../src/base/timer.cc - ../../../src/base/vecmath.cc ../../../src/base/worker.cc ../../../src/demo/credits.cc ../../../src/demo/demo.cc diff --git a/build/linux/Makefile b/build/linux/Makefile index e180b78..0311be3 100644 --- a/build/linux/Makefile +++ b/build/linux/Makefile @@ -79,7 +79,6 @@ GLTEST_SRC := \ $(SRC_ROOT)/base/sinc_resampler.cc \ $(SRC_ROOT)/base/task_runner.cc \ $(SRC_ROOT)/base/timer.cc \ - $(SRC_ROOT)/base/vecmath.cc \ $(SRC_ROOT)/base/worker.cc \ $(SRC_ROOT)/demo/credits.cc \ $(SRC_ROOT)/demo/demo.cc \ diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn index 6603e69..c1bd97b 100644 --- a/src/base/BUILD.gn +++ b/src/base/BUILD.gn @@ -18,7 +18,6 @@ source_set("base") { "task_runner.h", "timer.cc", "timer.h", - "vecmath.cc", "vecmath.h", "worker.cc", "worker.h", diff --git a/src/base/collusion_test.cc b/src/base/collusion_test.cc index f783913..7e5e4f6 100644 --- a/src/base/collusion_test.cc +++ b/src/base/collusion_test.cc @@ -6,9 +6,9 @@ namespace base { -bool Intersection(const Vector2& center, - const Vector2& size, - const Vector2& point) { +bool Intersection(const Vector2f& center, + const Vector2f& size, + const Vector2f& point) { float dx = point.x - center.x; float px = size.x / 2 - fabs(dx); if (px <= 0) @@ -19,12 +19,12 @@ bool Intersection(const Vector2& center, return py > 0; } -bool Intersection(const Vector2& center, - const Vector2& size, - const Vector2& origin, - const Vector2& dir) { - Vector2 min = center - size / 2; - Vector2 max = center + size / 2; +bool Intersection(const Vector2f& center, + const Vector2f& size, + const Vector2f& origin, + const Vector2f& dir) { + Vector2f min = center - size / 2; + Vector2f max = center + size / 2; float tmin = std::numeric_limits::min(); float tmax = std::numeric_limits::max(); diff --git a/src/base/collusion_test.h b/src/base/collusion_test.h index a62b896..3d9bcb4 100644 --- a/src/base/collusion_test.h +++ b/src/base/collusion_test.h @@ -6,17 +6,17 @@ namespace base { // AABB vs point. -bool Intersection(const Vector2& center, - const Vector2& size, - const Vector2& point); +bool Intersection(const Vector2f& center, + const Vector2f& size, + const Vector2f& point); // Ray-AABB intersection test. // center, size: Center and size of the box. // origin, dir: Origin and direction of the ray. -bool Intersection(const Vector2& center, - const Vector2& size, - const Vector2& origin, - const Vector2& dir); +bool Intersection(const Vector2f& center, + const Vector2f& size, + const Vector2f& origin, + const Vector2f& dir); } // namespace base diff --git a/src/base/vecmath.cc b/src/base/vecmath.cc deleted file mode 100644 index 6f012a1..0000000 --- a/src/base/vecmath.cc +++ /dev/null @@ -1,21 +0,0 @@ -#include "vecmath.h" - -using namespace std::string_literals; - -namespace base { - -std::string Vector2::ToString() { - return "("s + std::to_string(x) + ", "s + std::to_string(y) + ")"s; -} - -Matrix4x4 Ortho(float left, float right, float bottom, float top) { - Matrix4x4 m(1); - m.c[0].x = 2.0f / (right - left); - m.c[1].y = 2.0f / (top - bottom); - m.c[2].z = -1.0f; - m.c[3].x = -(right + left) / (right - left); - m.c[3].y = -(top + bottom) / (top - bottom); - return m; -} - -} // namespace base diff --git a/src/base/vecmath.h b/src/base/vecmath.h index 8310d40..6326dad 100644 --- a/src/base/vecmath.h +++ b/src/base/vecmath.h @@ -1,165 +1,1848 @@ #ifndef VEC_MATH_H #define VEC_MATH_H -#include #include #include +#include + +#include "interpolation.h" +#include "log.h" + +// +// Miscellaneous helper macros. +// + +#define _PI 3.14159265358979323846264338327950288419716939937510582097494459 + +#define _M_SET_ROW(row, k0, k1, k2, k3) \ + k[row][0] = k0; \ + k[row][1] = k1; \ + k[row][2] = k2; \ + k[row][3] = k3 + +#define _M_SET_ROW3x3(row, k0, k1, k2) \ + k[row][0] = k0; \ + k[row][1] = k1; \ + k[row][2] = k2 + +#define _M_SET_ROW_D(mat, row, k0, k1, k2, k3) \ + mat.k[row][0] = k0; \ + mat.k[row][1] = k1; \ + mat.k[row][2] = k2; \ + mat.k[row][3] = k3 + +#define _M_DET2x2(V, r0, r1, k0, k1) \ + Determinant2x2(V[r0][k0], V[r1][k0], V[r0][k1], V[r1][k1]) + +#define _M_DET3x3(V, r0, r1, r2, k0, k1, k2) \ + ((V[r0][k0] * Determinant2x2(V[r1][k1], V[r2][k1], V[r1][k2], V[r2][k2])) - \ + (V[r1][k0] * Determinant2x2(V[r0][k1], V[r2][k1], V[r0][k2], V[r2][k2])) + \ + (V[r2][k0] * Determinant2x2(V[r0][k1], V[r1][k1], V[r0][k2], V[r1][k2]))) namespace base { -struct Vector2 { - float x, y; +// Forward decleration. +template +class Vector3; +template +class Matrix4; +template +class Quaternion; + +// +// Standard constants. +// + +template +struct Constants { + static constexpr T PI = T(_PI); + static constexpr T PI2 = T(_PI * 2.0); + static constexpr T PIHALF = T(_PI * 0.5); +}; + +constexpr float PIf = Constants::PI; +constexpr float PI2f = Constants::PI2; +constexpr float PIHALFf = Constants::PIHALF; + +constexpr double PId = Constants::PI; +constexpr double PI2d = Constants::PI2; +constexpr double PIHALFd = Constants::PIHALF; + +// +// Miscellaneous helper templates. +// + +template +T Sel(T cmp, T ge, T lt) { + return (cmp < T(-0.0)) ? lt : ge; +} + +template +T Sqr(T v) { + return v * v; +} + +template +T Abs(T v) { + if (v < 0) + return -v; + return v; +} + +template +T Length3(T a, T b, T c) { + return (T)std::sqrt(Sqr(a) + Sqr(b) + Sqr(c)); +} + +template +void RotateElements(T& e0, T& e1, T c, T s) { + T tmp = e0 * c + e1 * s; + e1 = (-e0 * s) + e1 * c; + e0 = tmp; +} + +template +T Determinant2x2(T a, T b, T c, T d) { + return ((a * d) - (b * c)); +} + +template +T Determinant3x3(T a, T b, T c, T d, T e, T f, T g, T h, T i) { + return ((a * Determinant2x2(e, f, h, i)) - (b * Determinant2x2(d, f, g, i)) + + (c * Determinant2x2(d, e, g, h))); +} + +template +T Determinant4x4(T a, + T b, + T c, + T d, + T e, + T f, + T g, + T h, + T i, + T j, + T k, + T l, + T m, + T n, + T o, + T p) { + return ((a * Determinant3x3(f, g, h, j, k, l, n, o, p)) - + (b * Determinant3x3(e, g, h, i, k, l, m, o, p)) + + (c * Determinant3x3(e, f, h, i, j, l, m, n, p)) - + (d * Determinant3x3(e, f, g, i, j, k, m, n, o))); +} + +// Get angle from 2D-vector. +template +T AngleFromVector(T x, T z) { + T absx = Abs(x); + T absz = Abs(z); + + if (absx > absz) { + T v = std::atan(absz / absx) * ((T(1.0) / T(PId)) * T(0.5)); + if (x > T(0)) { + if (z < T(0)) + return -v; + return v; + } else { + if (z < T(0)) + return v + T(0.5); + return -v + T(0.5); + } + } else { + T v = std::atan(absx / absz) * ((T(1.0) / T(PId)) * T(0.5)); + if (z > T(0)) { + if (x < T(0)) + return v + T(0.25); + return -v + T(0.25); + } else { + if (x < T(0)) + return -v + T(0.75); + return v + T(0.75); + } + } +} + +template +void CreateAngleZYXFromMatrix(Vector3& v, + T e00, + T e01, + T e02, + T e10, + T e11, + T e12, + T e20, + T e21, + T e22) { + T sb = -e20; + T q1 = Abs(e00) + Abs(e10); + T q2 = Abs(e21) + Abs(e22); + if ((q1 < T(0.00001)) || (q2 < T(0.00001))) { + if (sb <= T(0.0)) + v[1] = T(0.25); + else + v[1] = -T(0.25); + v[2] = -AngleFromVector(e11, -e01); + v[0] = 0; + } else { + T tmp = std::sqrt(Abs(T(1.0) - Sqr(sb))); + v[1] = -AngleFromVector(tmp, sb); + v[2] = -AngleFromVector(e00, e10); + v[0] = AngleFromVector(e22, -e21); + } +} + +// +// Vector2 +// + +template +class Vector2 { + public: + union { + struct { + T x; + T y; + }; + T k[2]; + }; Vector2() {} - Vector2(float _x, float _y) : x(_x), y(_y) {} - float Magnitude() { return sqrt(x * x + y * y); } + explicit Vector2(T v) { k[0] = k[1] = v; } - Vector2 Normalize() { - float m = Magnitude(); - x /= m; - y /= m; + Vector2(T x, T y) { + k[0] = x; + k[1] = y; + } + + Vector2(const Vector2& other) { + k[0] = other.k[0]; + k[1] = other.k[1]; + } + + void operator=(const Vector2& other) { + k[0] = other.k[0]; + k[1] = other.k[1]; + } + + void operator=(T s) { k[0] = k[1] = s; } + + T& operator[](int i) { return k[i]; } + const T& operator[](int i) const { return k[i]; } + + bool operator==(const Vector2& other) const { + return k[0] == other.k[0] && k[1] == other.k[1]; + } + + bool operator==(T v) const { return k[0] == v && k[1] == v; } + + bool operator!=(const Vector2& other) const { + return k[0] != other.k[0] || k[1] != other.k[1]; + } + + bool operator!=(T v) const { return k[0] != v || k[1] != v; } + + bool AlmostEqual(const Vector2& other, T epsilon) const { + if (Abs(k[0] - other.k[0]) > epsilon) + return false; + if (Abs(k[1] - other.k[1]) > epsilon) + return false; + return true; + } + + Vector2 operator+(const Vector2& other) const { + return Vector2(k[0] + other.k[0], k[1] + other.k[1]); + } + + Vector2 operator-(const Vector2& other) const { + return Vector2(k[0] - other.k[0], k[1] - other.k[1]); + } + + Vector2 operator-() const { return Vector2(-k[0], -k[1]); } + + Vector2 operator*(const Vector2& other) const { + return Vector2(k[0] * other.k[0], k[1] * other.k[1]); + } + + Vector2 operator*(T scalar) const { + return Vector2(k[0] * scalar, k[1] * scalar); + } + + Vector2 operator/(const Vector2& other) const { + return Vector2(k[0] / other.k[0], k[1] / other.k[1]); + } + + Vector2 operator/(T scalar) const { + return Vector2(k[0] / scalar, k[1] / scalar); + } + + void operator+=(const Vector2& other) { + k[0] += other.k[0]; + k[1] += other.k[1]; + } + + void operator-=(const Vector2& other) { + k[0] -= other.k[0]; + k[1] -= other.k[1]; + } + + void operator*=(const Vector2& other) { + k[0] *= other.k[0]; + k[1] *= other.k[1]; + } + + void operator*=(T v) { + k[0] *= v; + k[1] *= v; + } + + void operator/=(const Vector2& other) { + k[0] /= other.k[0]; + k[1] /= other.k[1]; + } + + void operator/=(T v) { + k[0] /= v; + k[1] /= v; + } + + T DotProduct(const Vector2& v) { return k[0] * v.k[0] + k[1] * v.k[1]; } + + T CrossProduct(const Vector2& v) { return k[0] * v.k[1] - k[1] * v.k[0]; } + + Vector2 Project(const Vector2& v) const { + T vv = v.DotProduct(v); + if (vv == T(0.0)) + return Vector2(0); + T s = DotProduct(v) / vv; + return v * s; + } + + Vector2 Reflect(const Vector2& n) const { + return (*this) + (Project(n) * T(-2)); + } + + T Length() const { return std::sqrt(Sqr(k[0]) + Sqr(k[1])); } + + T LengthSqr() const { return Sqr(k[0]) + Sqr(k[1]); } + + T Distance(const Vector2& other) const { + return std::sqrt(Sqr(k[0] - other.k[0]) + Sqr(k[1] - other.k[1])); + } + + T DistanceSqr(const Vector2& other) const { + return Sqr(k[0] - other.k[0]) + Sqr(k[1] - other.k[1]); + } + + Vector2& Normalize() { + T len = Length(); + k[0] /= len; + k[1] /= len; return *this; } - float DotProduct(const Vector2& v) { return x * v.x + y * v.y; } - - float CrossProduct(const Vector2& v) { return x * v.y - y * v.x; } - - Vector2 operator-() { return Vector2(x * -1.0f, y * -1.0f); } - - Vector2 operator+=(const Vector2& v) { - x += v.x; - y += v.y; + Vector2& SafeNormalize() { + T len_sqr = LengthSqr(); + len_sqr = Sel(-len_sqr, T(1), len_sqr); // protect against 0 vector + T len = std::sqrt(len_sqr); + k[0] /= len; + k[1] /= len; return *this; } - Vector2 operator-=(const Vector2& v) { - x -= v.x; - y -= v.y; + Vector2& SetLength(T len) { + T len_sqr = LengthSqr(); + len_sqr = Sel(-len_sqr, T(1), len_sqr); // protect against 0 vector + T s = len / std::sqrt(len_sqr); + k[0] *= s; + k[1] *= s; return *this; } - Vector2 operator*=(const Vector2& v) { - x *= v.x; - y *= v.y; + Vector2& SetMaxLength(T max_len) { + if (LengthSqr() > Sqr(max_len)) + SetLength(max_len); return *this; } - Vector2 operator*=(float s) { - x *= s; - y *= s; - return *this; + const T* GetData() const { return &k[0]; } + + std::string ToString() { + using namespace std::string_literals; + return "("s + std::to_string(k[0]) + ", "s + std::to_string(k[1]) + ")"s; } - - Vector2 operator/=(const Vector2& v) { - x /= v.x; - y /= v.y; - return *this; - } - - Vector2 operator/=(float s) { - x /= s; - y /= s; - return *this; - } - - const float* GetData() const { return &x; } - - std::string ToString(); }; -inline Vector2 operator+(const Vector2& v1, const Vector2& v2) { - return Vector2(v1.x + v2.x, v1.y + v2.y); -} +// +// Vector3 +// -inline Vector2 operator-(const Vector2& v1, const Vector2& v2) { - return Vector2(v1.x - v2.x, v1.y - v2.y); -} - -inline Vector2 operator*(const Vector2& v1, const Vector2& v2) { - return Vector2(v1.x * v2.x, v1.y * v2.y); -} - -inline Vector2 operator/(const Vector2& v1, const Vector2& v2) { - return Vector2(v1.x / v2.x, v1.y / v2.y); -} - -inline Vector2 operator*(const Vector2& v, float s) { - return Vector2(v.x * s, v.y * s); -} - -inline Vector2 operator/(const Vector2& v, float s) { - return Vector2(v.x / s, v.y / s); -} - -inline bool operator==(const Vector2& v1, const Vector2& v2) { - return v1.x == v2.x && v1.y == v2.y; -} - -inline bool operator!=(const Vector2& v1, const Vector2& v2) { - return v1.x != v2.x || v1.y != v2.y; -} - -struct Vector3 { - float x, y, z; +template +class Vector3 { + public: + union { + struct { + T x; + T y; + T z; + }; + T k[3]; + }; Vector3() {} - Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} - const float* GetData() const { return &x; } -}; + explicit Vector3(T v) { k[0] = k[1] = k[2] = v; } -inline Vector3 operator+(const Vector3& v1, const Vector3& v2) { - return Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); -} + Vector3(T x, T y, T z) { + k[0] = x; + k[1] = y; + k[2] = z; + } -struct Vector4 { - float x, y, z, w; + Vector3(const Vector3& other) { + k[0] = other.k[0]; + k[1] = other.k[1]; + k[2] = other.k[2]; + } - Vector4() {} - Vector4(float _x, float _y, float _z, float _w) - : x(_x), y(_y), z(_z), w(_w) {} + void operator=(const Vector3& other) { + k[0] = other.k[0]; + k[1] = other.k[1]; + k[2] = other.k[2]; + } - Vector4 operator+=(const Vector4& v) { - x += v.x; - y += v.y; - z += v.z; - w += v.w; + void operator=(T s) { k[0] = k[1] = k[2] = s; } + + T& operator[](int i) { return k[i]; } + const T& operator[](int i) const { return k[i]; } + + bool operator==(const Vector3& other) const { + return k[0] == other.k[0] && k[1] == other.k[1] && k[2] == other.k[2]; + } + + bool operator==(T v) const { return k[0] == v && k[1] == v && k[2] == v; } + + bool operator!=(const Vector3& other) const { + return k[0] != other.k[0] || k[1] != other.k[1] || k[2] != other.k[2]; + } + + bool operator!=(T v) const { return k[0] != v || k[1] != v || k[2] != v; } + + bool AlmostEqual(const Vector3& other, T epsilon) const { + if (Abs(k[0] - other.k[0]) > epsilon) + return false; + if (Abs(k[1] - other.k[1]) > epsilon) + return false; + if (Abs(k[2] - other.k[2]) > epsilon) + return false; + return true; + } + + Vector3 operator+(const Vector3& other) const { + return Vector3(k[0] + other.k[0], k[1] + other.k[1], k[2] + other.k[2]); + } + + Vector3 operator-(const Vector3& other) const { + return Vector3(k[0] - other.k[0], k[1] - other.k[1], k[2] - other.k[2]); + } + + Vector3 operator-() const { return Vector3(-k[0], -k[1], -k[2]); } + + Vector3 operator*(const Vector3& other) const { + return Vector3(k[0] * other.k[0], k[1] * other.k[1], k[2] * other.k[2]); + } + + Vector3 operator*(T scalar) const { + return Vector3(k[0] * scalar, k[1] * scalar, k[2] * scalar); + } + + Vector3 operator*(const Matrix4& mat) { + Vector3 r; + for (int i = 0; i < 3; i++) + r.k[i] = mat.k[0][i] * k[0] + mat.k[1][i] * k[1] + mat.k[2][i] * k[2] + + mat.k[3][i]; + return r; + } + + Vector3 operator/(const Vector3& other) const { + return Vector3(k[0] / other.k[0], k[1] / other.k[1], k[2] / other.k[2]); + } + + Vector3 operator/(T scalar) const { + return Vector3(k[0] / scalar, k[1] / scalar, k[2] / scalar); + } + + void operator+=(const Vector3& other) { + k[0] += other.k[0]; + k[1] += other.k[1]; + k[2] += other.k[2]; + } + + void operator-=(const Vector3& other) { + k[0] -= other.k[0]; + k[1] -= other.k[1]; + k[2] -= other.k[2]; + } + + void operator*=(const Vector3& other) { + k[0] *= other.k[0]; + k[1] *= other.k[1]; + k[2] *= other.k[2]; + } + + void operator*=(T v) { + k[0] *= v; + k[1] *= v; + k[2] *= v; + } + + void operator*=(const Matrix4& mat) { + Vector3 r; + for (int i = 0; i < 3; i++) + r.k[i] = mat.k[0][i] * k[0] + mat.k[1][i] * k[1] + mat.k[2][i] * k[2] + + mat.k[3][i]; + k[0] = r.k[0]; + k[1] = r.k[1]; + k[2] = r.k[2]; + } + + void operator/=(const Vector3& other) { + k[0] /= other.k[0]; + k[1] /= other.k[1]; + k[2] /= other.k[2]; + } + + void operator/=(T v) { + k[0] /= v; + k[1] /= v; + k[2] /= v; + } + + T DotProduct(const Vector3& other) const { + return k[0] * other.k[0] + k[1] * other.k[1] + k[2] * other.k[2]; + } + + Vector3 CrossProduct(const Vector3& other) const { + return Vector3(k[1] * other.k[2] - k[2] * other.k[1], + -k[0] * other.k[2] + k[2] * other.k[0], + k[0] * other.k[1] - k[1] * other.k[0]); + } + + Vector3 Project(const Vector3& v) const { + T vv = v.DotProduct(v); + if (vv == T(0.0)) + return Vector3(0); + T s = DotProduct(v) / vv; + return v * s; + } + + Vector3 ProjectPlane(const Vector3& n) const { + T nn = n.DotProduct(n); + if (nn == T(0.0)) + return Vector3(0); + T s = DotProduct(n) / nn; + return *this - (n * s); + } + + Vector3 Reflect(const Vector3& n) const { + return (*this) + (Project(n) * T(-2)); + } + + T Length() const { return std::sqrt(Sqr(k[0]) + Sqr(k[1]) + Sqr(k[2])); } + + T LengthSqr() const { return Sqr(k[0]) + Sqr(k[1]) + Sqr(k[2]); } + + T Distance(const Vector3& other) const { + return std::sqrt(Sqr(k[0] - other.k[0]) + Sqr(k[1] - other.k[1]) + + Sqr(k[2] - other.k[2])); + } + + T DistanceSqr(const Vector3& other) const { + return Sqr(k[0] - other.k[0]) + Sqr(k[1] - other.k[1]) + + Sqr(k[2] - other.k[2]); + } + + Vector3& Normalize() { + T len = Length(); + k[0] /= len; + k[1] /= len; + k[2] /= len; return *this; } - const float* GetData() const { return &x; } + Vector3& SafeNormalize() { + T len_sqr = LengthSqr(); + len_sqr = Sel(-len_sqr, T(1), len_sqr); // protect against 0 vector + T len = std::sqrt(len_sqr); + k[0] /= len; + k[1] /= len; + k[2] /= len; + return *this; + } + + Vector3& SetLength(T len) { + T len_sqr = LengthSqr(); + len_sqr = Sel(-len_sqr, T(1), len_sqr); // protect against 0 vector + T s = len / std::sqrt(len_sqr); + k[0] *= s; + k[1] *= s; + k[2] *= s; + return *this; + } + + Vector3& SetMaxLength(T max_len) { + if (LengthSqr() > Sqr(max_len)) + SetLength(max_len); + return *this; + } + + const T* GetData() const { return &k[0]; } + + std::string ToString() { + using namespace std::string_literals; + return "("s + std::to_string(k[0]) + ", "s + std::to_string(k[1]) + ", "s + + std::to_string(k[2]) + ")"s; + } }; -inline Vector4 operator*(const Vector4& v1, const Vector4& v2) { - return Vector4(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w); -} +// +// Vector4 +// -inline Vector4 operator*(const Vector4& v, float s) { - return Vector4(v.x * s, v.y * s, v.z * s, v.w * s); -} +template +class Vector4 { + public: + union { + struct { + T x; + T y; + T z; + T w; + }; + T k[4]; + }; -inline Vector4 operator+(const Vector4& v1, const Vector4& v2) { - return Vector4(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w); -} + Vector4() {} -inline Vector4 operator-(const Vector4& v1, const Vector4& v2) { - return Vector4(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w); -} + explicit Vector4(T v) { k[0] = k[1] = k[2] = k[3] = v; } -struct Matrix4x4 { - Vector4 c[4]; + Vector4(T x, T y, T z, T w) { + k[0] = x; + k[1] = y; + k[2] = z; + k[3] = w; + } - Matrix4x4() {} - Matrix4x4(float s) - : c{Vector4(s, 0, 0, 0), Vector4(0, s, 0, 0), Vector4(0, 0, s, 0), - Vector4(0, 0, 0, s)} {} + Vector4(const Vector4& other) { + k[0] = other.k[0]; + k[1] = other.k[1]; + k[2] = other.k[2]; + k[3] = other.k[3]; + } - const float* GetData() const { return &c[0].x; } + void operator=(const Vector4& other) { + k[0] = other.k[0]; + k[1] = other.k[1]; + k[2] = other.k[2]; + k[3] = other.k[3]; + } + + void operator=(T s) { k[0] = k[1] = k[2] = k[3] = s; } + + T& operator[](int i) { return k[i]; } + const T& operator[](int i) const { return k[i]; } + + bool operator==(const Vector4& other) const { + return k[0] == other.k[0] && k[1] == other.k[1] && k[2] == other.k[2] && + k[3] == other.k[3]; + } + + bool operator==(T v) const { + return k[0] == v && k[1] == v && k[2] == v && k[3] == v; + } + + bool operator!=(const Vector4& other) const { + return k[0] != other.k[0] || k[1] != other.k[1] || k[2] != other.k[2] || + k[3] != other.k[3]; + } + + bool operator!=(T v) const { + return k[0] != v || k[1] != v || k[2] != v || k[3] != v; + } + + bool AlmostEqual(const Vector4& other, T epsilon) const { + if (Abs(k[0] - other.k[0]) > epsilon) + return false; + if (Abs(k[1] - other.k[1]) > epsilon) + return false; + if (Abs(k[2] - other.k[2]) > epsilon) + return false; + if (Abs(k[3] - other.k[3]) > epsilon) + return false; + return true; + } + + Vector4 operator+(const Vector4& other) const { + return Vector4(k[0] + other.k[0], k[1] + other.k[1], k[2] + other.k[2], + k[3] + other.k[3]); + } + + Vector4 operator-(const Vector4& other) const { + return Vector4(k[0] - other.k[0], k[1] - other.k[1], k[2] - other.k[2], + k[3] - other.k[3]); + } + + Vector4 operator-() const { return Vector4(-k[0], -k[1], -k[2], -k[3]); } + + Vector4 operator*(const Vector4& other) const { + return Vector4(k[0] * other.k[0], k[1] * other.k[1], k[2] * other.k[2], + k[3] * other.k[3]); + } + + Vector4 operator*(T scalar) const { + return Vector4(k[0] * scalar, k[1] * scalar, k[2] * scalar, k[3] * scalar); + } + + Vector4 operator*(const Matrix4& mat) { + Vector4 r; + for (int i = 0; i < 3; i++) + r.k[i] = mat.k[0][i] * k[0] + mat.k[1][i] * k[1] + mat.k[2][i] * k[2] + + mat.k[3][i] * k[3]; + return r; + } + + Vector4 operator/(const Vector4& other) const { + return Vector4(k[0] / other.k[0], k[1] / other.k[1], k[2] / other.k[2], + k[3] / other.k[3]); + } + + Vector4 operator/(T scalar) const { + return Vector4(k[0] / scalar, k[1] / scalar, k[2] / scalar, k[3] / scalar); + } + + void operator+=(const Vector4& other) { + k[0] += other.k[0]; + k[1] += other.k[1]; + k[2] += other.k[2]; + k[3] += other.k[3]; + } + + void operator-=(const Vector4& other) { + k[0] -= other.k[0]; + k[1] -= other.k[1]; + k[2] -= other.k[2]; + k[3] -= other.k[3]; + } + + void operator*=(const Vector4& other) { + k[0] *= other.k[0]; + k[1] *= other.k[1]; + k[2] *= other.k[2]; + k[3] *= other.k[3]; + } + + void operator*=(T v) { + k[0] *= v; + k[1] *= v; + k[2] *= v; + k[3] *= v; + } + + void operator*=(const Matrix4& mat) { + Vector4 r; + for (int i = 0; i < 3; i++) + r.k[i] = mat.k[0][i] * k[0] + mat.k[1][i] * k[1] + mat.k[2][i] * k[2] + + mat.k[3][i] * k[3]; + k[0] = r.k[0]; + k[1] = r.k[1]; + k[2] = r.k[2]; + k[3] = r.k[3]; + } + + void operator/=(const Vector4& other) { + k[0] /= other.k[0]; + k[1] /= other.k[1]; + k[2] /= other.k[2]; + k[3] /= other.k[3]; + } + + void operator/=(T v) { + k[0] /= v; + k[1] /= v; + k[2] /= v; + k[3] /= v; + } + + T DotProduct(const Vector4& other) const { + return k[0] * other.k[0] + k[1] * other.k[1] + k[2] * other.k[2] + + k[3] * other.k[3]; + } + + T Length() const { + return std::sqrt(Sqr(k[0]) + Sqr(k[1]) + Sqr(k[2]) + Sqr(k[3])); + } + + T LengthSqr() const { return Sqr(k[0]) + Sqr(k[1]) + Sqr(k[2]) + Sqr(k[3]); } + + T Distance(const Vector4& other) const { + return std::sqrt(Sqr(k[0] - other.k[0]) + Sqr(k[1] - other.k[1]) + + Sqr(k[2] - other.k[2]) + Sqr(k[3] - other.k[3])); + } + + T DistanceSqr(const Vector4& other) const { + return Sqr(k[0] - other.k[0]) + Sqr(k[1] - other.k[1]) + + Sqr(k[2] - other.k[2]) + Sqr(k[3] - other.k[3]); + } + + Vector4& Normalize() { + T len = Length(); + k[0] /= len; + k[1] /= len; + k[2] /= len; + k[3] /= len; + return *this; + } + + Vector4& SafeNormalize() { + T len_sqr = LengthSqr(); + len_sqr = Sel(-len_sqr, T(1), len_sqr); // protect against 0 vector + T len = std::sqrt(len_sqr); + k[0] /= len; + k[1] /= len; + k[2] /= len; + k[3] /= len; + return *this; + } + + Vector4& SetLength(T len) { + T len_sqr = LengthSqr(); + len_sqr = Sel(-len_sqr, T(1), len_sqr); // protect against 0 vector + T s = len / std::sqrt(len_sqr); + k[0] *= s; + k[1] *= s; + k[2] *= s; + k[3] *= s; + return *this; + } + + Vector4& SetMaxLength(T max_len) { + if (LengthSqr() > Sqr(max_len)) + SetLength(max_len); + return *this; + } + + const T* GetData() const { return &k[0]; } + + std::string ToString() { + using namespace std::string_literals; + return "("s + std::to_string(k[0]) + ", "s + std::to_string(k[1]) + ", "s + + std::to_string(k[2]) + ", "s + std::to_string(k[3]) + ")"s; + } }; -Matrix4x4 Ortho(float left, float right, float bottom, float top); +// +// Matrix4 +// + +template +class Matrix4 { + public: + T k[4][4]; // row-major layout. + + Matrix4() {} + + explicit Matrix4(T s) + : k{ + {s, 0, 0, 0}, + {0, s, 0, 0}, + {0, 0, s, 0}, + {0, 0, 0, s}, + } {} + + Matrix4(T v00, + T v01, + T v02, + T v03, + T v10, + T v11, + T v12, + T v13, + T v20, + T v21, + T v22, + T v23, + T v30, + T v31, + T v32, + T v33) + : k{ + {v00, v01, v02, v03}, + {v10, v11, v12, v13}, + {v20, v21, v22, v23}, + {v30, v31, v32, v33}, + } {} + + Matrix4(const Matrix4& other) + : k{ + {other.k[0][0], other.k[0][1], other.k[0][2], other.k[0][3]}, + {other.k[1][0], other.k[1][1], other.k[1][2], other.k[1][3]}, + {other.k[2][0], other.k[2][1], other.k[2][2], other.k[2][3]}, + {other.k[3][0], other.k[3][1], other.k[3][2], other.k[3][3]}, + } {} + + void operator=(const Matrix4& other) { + _M_SET_ROW(0, other.k[0][0], other.k[0][1], other.k[0][2], other.k[0][3]); + _M_SET_ROW(1, other.k[1][0], other.k[1][1], other.k[1][2], other.k[1][3]); + _M_SET_ROW(2, other.k[2][0], other.k[2][1], other.k[2][2], other.k[2][3]); + _M_SET_ROW(3, other.k[3][0], other.k[3][1], other.k[3][2], other.k[3][3]); + } + + void operator=(T s) { + _M_SET_ROW(0, s, 0, 0, 0); + _M_SET_ROW(1, 0, s, 0, 0); + _M_SET_ROW(2, 0, 0, s, 0); + _M_SET_ROW(3, 0, 0, 0, s); + } + + // Load identity. + void Unit() { + _M_SET_ROW(0, 1, 0, 0, 0); + _M_SET_ROW(1, 0, 1, 0, 0); + _M_SET_ROW(2, 0, 0, 1, 0); + _M_SET_ROW(3, 0, 0, 0, 1); + } + + // Load identity into 3x3. + void Unit3x3() { + k[0][0] = T(1); + k[1][0] = T(0); + k[2][0] = T(0); + k[0][1] = T(0); + k[1][1] = T(1); + k[2][1] = T(0); + k[0][2] = T(0); + k[1][2] = T(0); + k[2][2] = T(1); + } + + // Load identity into row and column 4, leaving 3x3 part unchanged. + void UnitNot3x3() { + k[0][3] = T(0); + k[1][3] = T(0); + k[2][3] = T(0); + k[3][3] = T(1); + k[3][2] = T(0); + k[3][1] = T(0); + k[3][0] = T(0); + } + + void Transpose() { + std::swap(k[0][1], k[1][0]); + std::swap(k[0][2], k[2][0]); + std::swap(k[0][3], k[3][0]); + std::swap(k[1][2], k[2][1]); + std::swap(k[1][3], k[3][1]); + std::swap(k[2][3], k[3][2]); + } + + void Transpose(Matrix4& dst) const { + _M_SET_ROW_D(dst, 0, (k[0][0]), (k[1][0]), (k[2][0]), (k[3][0])); + _M_SET_ROW_D(dst, 1, (k[0][1]), (k[1][1]), (k[2][1]), (k[3][1])); + _M_SET_ROW_D(dst, 2, (k[0][2]), (k[1][2]), (k[2][2]), (k[3][2])); + _M_SET_ROW_D(dst, 3, (k[0][3]), (k[1][3]), (k[2][3]), (k[3][3])); + } + + void Transpose3x3() { + std::swap(k[0][1], k[1][0]); + std::swap(k[0][2], k[2][0]); + std::swap(k[1][2], k[2][1]); + } + + void Transpose3x3(Matrix4& dst) const { + dst.k[0][0] = k[0][0]; + dst.k[1][1] = k[1][1]; + dst.k[2][2] = k[2][2]; + dst.k[0][1] = k[1][0]; + dst.k[0][2] = k[2][0]; + dst.k[1][2] = k[2][1]; + dst.k[1][0] = k[0][1]; + dst.k[2][0] = k[0][2]; + dst.k[2][1] = k[1][2]; + } + + bool Inverse() { + T d = Determinant4x4((k[0][0]), (k[0][1]), (k[0][2]), (k[0][3]), (k[1][0]), + (k[1][1]), (k[1][2]), (k[1][3]), (k[2][0]), (k[2][1]), + (k[2][2]), (k[2][3]), (k[3][0]), (k[3][1]), (k[3][2]), + (k[3][3])); + if (d == T(0.0)) { + Unit(); + return false; + } + + T d_inv = T(1.0) / d; + T k00 = d_inv * _M_DET3x3(k, 1, 2, 3, 1, 2, 3); + T k01 = -d_inv * _M_DET3x3(k, 0, 2, 3, 1, 2, 3); + T k02 = d_inv * _M_DET3x3(k, 0, 1, 3, 1, 2, 3); + T k03 = -d_inv * _M_DET3x3(k, 0, 1, 2, 1, 2, 3); + T k10 = -d_inv * _M_DET3x3(k, 1, 2, 3, 0, 2, 3); + T k11 = d_inv * _M_DET3x3(k, 0, 2, 3, 0, 2, 3); + T k12 = -d_inv * _M_DET3x3(k, 0, 1, 3, 0, 2, 3); + T k13 = d_inv * _M_DET3x3(k, 0, 1, 2, 0, 2, 3); + T k20 = d_inv * _M_DET3x3(k, 1, 2, 3, 0, 1, 3); + T k21 = -d_inv * _M_DET3x3(k, 0, 2, 3, 0, 1, 3); + T k22 = d_inv * _M_DET3x3(k, 0, 1, 3, 0, 1, 3); + T k23 = -d_inv * _M_DET3x3(k, 0, 1, 2, 0, 1, 3); + T k30 = -d_inv * _M_DET3x3(k, 1, 2, 3, 0, 1, 2); + T k31 = d_inv * _M_DET3x3(k, 0, 2, 3, 0, 1, 2); + T k32 = -d_inv * _M_DET3x3(k, 0, 1, 3, 0, 1, 2); + T k33 = d_inv * _M_DET3x3(k, 0, 1, 2, 0, 1, 2); + + _M_SET_ROW(0, k00, k01, k02, k03); + _M_SET_ROW(1, k10, k11, k12, k13); + _M_SET_ROW(2, k20, k21, k22, k23); + _M_SET_ROW(3, k30, k31, k32, k33); + return true; + } + + bool Inverse(Matrix4& dst) const { + T d = Determinant4x4((k[0][0]), (k[0][1]), (k[0][2]), (k[0][3]), (k[1][0]), + (k[1][1]), (k[1][2]), (k[1][3]), (k[2][0]), (k[2][1]), + (k[2][2]), (k[2][3]), (k[3][0]), (k[3][1]), (k[3][2]), + (k[3][3])); + if (d == T(0.0)) { + dst.Unit(); + return false; + } + + T d_inv = T(1.0) / d; + dst.k[0][0] = d_inv * _M_DET3x3(k, 1, 2, 3, 1, 2, 3); + dst.k[0][1] = -d_inv * _M_DET3x3(k, 0, 2, 3, 1, 2, 3); + dst.k[0][2] = d_inv * _M_DET3x3(k, 0, 1, 3, 1, 2, 3); + dst.k[0][3] = -d_inv * _M_DET3x3(k, 0, 1, 2, 1, 2, 3); + dst.k[1][0] = -d_inv * _M_DET3x3(k, 1, 2, 3, 0, 2, 3); + dst.k[1][1] = d_inv * _M_DET3x3(k, 0, 2, 3, 0, 2, 3); + dst.k[1][2] = -d_inv * _M_DET3x3(k, 0, 1, 3, 0, 2, 3); + dst.k[1][3] = d_inv * _M_DET3x3(k, 0, 1, 2, 0, 2, 3); + dst.k[2][0] = d_inv * _M_DET3x3(k, 1, 2, 3, 0, 1, 3); + dst.k[2][1] = -d_inv * _M_DET3x3(k, 0, 2, 3, 0, 1, 3); + dst.k[2][2] = d_inv * _M_DET3x3(k, 0, 1, 3, 0, 1, 3); + dst.k[2][3] = -d_inv * _M_DET3x3(k, 0, 1, 2, 0, 1, 3); + dst.k[3][0] = -d_inv * _M_DET3x3(k, 1, 2, 3, 0, 1, 2); + dst.k[3][1] = d_inv * _M_DET3x3(k, 0, 2, 3, 0, 1, 2); + dst.k[3][2] = -d_inv * _M_DET3x3(k, 0, 1, 3, 0, 1, 2); + dst.k[3][3] = d_inv * _M_DET3x3(k, 0, 1, 2, 0, 1, 2); + return true; + } + + bool Inverse3x3() { + T d = Determinant3x3((k[0][0]), (k[0][1]), (k[0][2]), (k[1][0]), (k[1][1]), + (k[1][2]), (k[2][0]), (k[2][1]), (k[2][2])); + if (d == T(0.0)) { + Unit3x3(); + return false; + } + + T d_inv = T(1.0) / d; + T k00 = d_inv * _M_DET2x2(k, 1, 2, 1, 2); + T k01 = -d_inv * _M_DET2x2(k, 0, 2, 1, 2); + T k02 = d_inv * _M_DET2x2(k, 0, 1, 1, 2); + T k10 = -d_inv * _M_DET2x2(k, 1, 2, 0, 2); + T k11 = d_inv * _M_DET2x2(k, 0, 2, 0, 2); + T k12 = -d_inv * _M_DET2x2(k, 0, 1, 0, 2); + T k20 = d_inv * _M_DET2x2(k, 1, 2, 0, 1); + T k21 = -d_inv * _M_DET2x2(k, 0, 2, 0, 1); + T k22 = d_inv * _M_DET2x2(k, 0, 1, 0, 1); + + k[0][0] = k00; + k[0][1] = k01; + k[0][2] = k02; + k[1][0] = k10; + k[1][1] = k11; + k[1][2] = k12; + k[2][0] = k20; + k[2][1] = k21; + k[2][2] = k22; + return true; + } + + bool Inverse3x3(Matrix4& dst) const { + T d = Determinant3x3((k[0][0]), (k[0][1]), (k[0][2]), (k[1][0]), (k[1][1]), + (k[1][2]), (k[2][0]), (k[2][1]), (k[2][2])); + if (d == T(0.0)) { + dst.Unit3x3(); + return false; + } + + T d_inv = T(1.0) / d; + dst.k[0][0] = d_inv * _M_DET2x2(k, 1, 2, 1, 2); + dst.k[0][1] = -d_inv * _M_DET2x2(k, 0, 2, 1, 2); + dst.k[0][2] = d_inv * _M_DET2x2(k, 0, 1, 1, 2); + dst.k[1][0] = -d_inv * _M_DET2x2(k, 1, 2, 0, 2); + dst.k[1][1] = d_inv * _M_DET2x2(k, 0, 2, 0, 2); + dst.k[1][2] = -d_inv * _M_DET2x2(k, 0, 1, 0, 2); + dst.k[2][0] = d_inv * _M_DET2x2(k, 1, 2, 0, 1); + dst.k[2][1] = -d_inv * _M_DET2x2(k, 0, 2, 0, 1); + dst.k[2][2] = d_inv * _M_DET2x2(k, 0, 1, 0, 1); + return true; + } + + void InverseOrthogonal() { + T k00 = k[0][0]; + T k11 = k[1][1]; + T k22 = k[2][2]; + T k10 = k[1][0]; + T k20 = k[2][0]; + T k21 = k[2][1]; + T k01 = k[0][1]; + T k02 = k[0][2]; + T k12 = k[1][2]; + T k30 = k[3][0]; + T k31 = k[3][1]; + T k32 = k[3][2]; + + // (T*R)^-1 = (R^-1)*(T^-1) = transpose(R)*(-T) + k[0][0] = k00; + k[1][1] = k11; + k[2][2] = k22; + k[0][1] = k10; + k[0][2] = k20; + k[1][2] = k21; + k[1][0] = k01; + k[2][0] = k02; + k[2][1] = k12; + k[3][0] = -(k30 * k00 + k31 * k01 + k32 * k02); + k[3][1] = -(k30 * k10 + k31 * k11 + k32 * k12); + k[3][2] = -(k30 * k20 + k31 * k21 + k32 * k22); + k[3][3] = 1; + k[0][3] = 0; + k[1][3] = 0; + k[2][3] = 0; + } + + void InverseOrthogonal(Matrix4& dst) const { + dst.k[0][0] = k[0][0]; + dst.k[1][1] = k[1][1]; + dst.k[2][2] = k[2][2]; + dst.k[0][1] = k[1][0]; + dst.k[0][2] = k[2][0]; + dst.k[1][2] = k[2][1]; + dst.k[1][0] = k[0][1]; + dst.k[2][0] = k[0][2]; + dst.k[2][1] = k[1][2]; + dst.k[3][0] = -(k[3][0] * k[0][0] + k[3][1] * k[0][1] + k[3][2] * k[0][2]); + dst.k[3][1] = -(k[3][0] * k[1][0] + k[3][1] * k[1][1] + k[3][2] * k[1][2]); + dst.k[3][2] = -(k[3][0] * k[2][0] + k[3][1] * k[2][1] + k[3][2] * k[2][2]); + dst.k[3][3] = 1; + dst.k[0][3] = 0; + dst.k[1][3] = 0; + dst.k[2][3] = 0; + } + + // Scale 4x4 + void Multiply(T s) { + for (int row = 0; row < 4; row++) + for (int col = 0; col < 4; col++) + k[row][col] *= s; + } + + void Multiply(T s, Matrix4& dst) { + for (int row = 0; row < 4; row++) + for (int col = 0; col < 4; col++) + dst.k[row][col] *= s; + } + + // Scale 3x3 + void Multiply3x3(T s) { + for (int row = 0; row < 3; row++) + for (int col = 0; col < 3; col++) + k[row][col] *= s; + } + + void Multiply3x3(T s, Matrix4& dst) { + for (int row = 0; row < 3; row++) + for (int col = 0; col < 3; col++) + dst.k[row][col] *= s; + } + + // Multiply 4x4 + void Multiply(const Matrix4& m, Matrix4& dst) const { + for (int row = 0; row < 4; row++) + for (int col = 0; col < 4; col++) + dst.k[row][col] = (k[row][0] * m.k[0][col]) + + (k[row][1] * m.k[1][col]) + + (k[row][2] * m.k[2][col]) + (k[row][3] * m.k[3][col]); + } + + // Multiply 3x3 + void Multiply3x3(const Matrix4& m, Matrix4& dst) const { + for (int row = 0; row < 3; row++) + for (int col = 0; col < 3; col++) + dst.k[row][col] = (k[row][0] * m.k[0][col]) + + (k[row][1] * m.k[1][col]) + (k[row][2] * m.k[2][col]); + } + + void Normalize3x3() { + T len = std::max(std::max(Length3(k[0][0], k[1][0], k[2][0]), + Length3(k[0][1], k[1][1], k[2][1])), + Length3(k[0][2], k[1][2], k[2][2])); + + if (len != 0) { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + k[i][j] = k[i][j] / len; + } + } + + void NormalizeRows3x3() { + for (int i = 0; i < 3; i++) { + T len_sqr = Sqr(k[i][0]) + Sqr(k[i][1]) + Sqr(k[i][2]); + if (len_sqr != 0) { + T len = std::sqrt(len_sqr); + k[i][0] = k[i][0] / len; + k[i][1] = k[i][1] / len; + k[i][2] = k[i][2] / len; + } else { + k[i][0] = k[i][1] = k[i][2] = 0; + k[i][i] = 1; + } + } + } + + void Create(const Quaternion& rotation, const Vector3& translation) { + rotation.CreateMatrix3x3(*this); + k[0][3] = T(0); + k[1][3] = T(0); + k[2][3] = T(0); + k[3][3] = T(1); + GetRow(3) = translation; + } + + void CreateLookAt(const Vector3& from, + const Vector3& to, + const Vector3& up = {T(0), T(1), T(0)}) { + GetRow(2) = to - from; + GetRow(1) = up; + RecreateMatrix<2, 1>(); + UnitNot3x3(); + GetRow(3) = from; + } + + void CreateOrthoProjection(T left, T right, T bottom, T top) { + T rml = right - left; + T rpl = right + left; + T tmb = top - bottom; + T tpb = top + bottom; + _M_SET_ROW(0, T(2) / rml, 0, 0, 0); + _M_SET_ROW(1, 0, T(2) / tmb, 0, 0); + _M_SET_ROW(2, 0, 0, T(-1), 0); + _M_SET_ROW(3, -rpl / rml, -tpb / tmb, 0, 1); + } + + void CreateFovProjection(T fov, + T fov_aspect, + T width, + T height, + T near, + T far) { + // Calc x and y scale from FOV. + T scale = + T(2.0) / + std::sqrt(Sqr(T(1.0) / std::cos((T(PId) * fov) / T(360.0))) - T(1.0)); + T y_scale = scale * fov_aspect / (width / height); + T x_scale = y_scale / (width / height); + _M_SET_ROW(0, x_scale / T(2.0), 0, 0, 0); + _M_SET_ROW(1, 0, (-y_scale) / T(2.0), 0, 0); + _M_SET_ROW(2, 0, 0, far / (far - near), 1); + _M_SET_ROW(3, 0, 0, -near * far / (far - near), 0); + } + + void CreateTranslation(const Vector3& t) { + _M_SET_ROW(0, 1, 0, 0, 0); + _M_SET_ROW(1, 0, 1, 0, 0); + _M_SET_ROW(2, 0, 0, 1, 0); + _M_SET_ROW(3, t[0], t[1], t[2], 1); + } + + // Create matrix from axis-angle. + void CreateAxisRotation(const Vector3& rotation_axis, T angle) const { + // rotation_axis must be normalized. + // angle = degrees / 360 (ie. 0..1) + T x = rotation_axis[0]; + T y = rotation_axis[1]; + T z = rotation_axis[2]; + + T a = Sqr(x); + T b = Sqr(y); + T c = Sqr(z); + T cs = std::cos(angle * T(2.0) * T(PI2d)); + T sn = std::sin(angle * T(2.0) * T(PI2d)); + T z_sn = z * sn; + T x_sn = x * sn; + T y_sn = y * sn; + T xz_cs = x * z * (T(1.0) - cs); + T xy_cs = x * y * (T(1.0) - cs); + T yz_cs = y * z * (T(1.0) - cs); + + k[0][0] = a + cs * (T(1.0) - a); + k[0][1] = xy_cs - z_sn; + k[0][2] = y_sn + xz_cs; + k[1][0] = z_sn + xy_cs; + k[1][1] = b + cs * (T(1.0) - b); + k[1][2] = yz_cs - x_sn; + k[2][0] = xz_cs - y_sn; + k[2][1] = x_sn + yz_cs; + k[2][2] = c + cs * (T(1.0) - c); + + UnitNot3x3(); + } + + // Create matrix from euler-angles. + void CreateFromAngles(const Vector3& angles, int angle_priority) { + // Rotation priorities: + // 0: [mat] = [z]*[y]*[x] + // 1: [mat] = [z]*[x]*[y] + // 2: [mat] = [y]*[z]*[x] + // 3: [mat] = [y]*[x]*[z] + // 4: [mat] = [x]*[z]*[y] + // 5: [mat] = [x]*[y]*[z] + Unit(); + switch (angle_priority) { + case 5: + M_x_RotZ(angles[2]); + M_x_RotY(angles[1]); + M_x_RotX(angles[0]); + break; + case 3: + M_x_RotZ(angles[2]); + M_x_RotX(angles[0]); + M_x_RotY(angles[1]); + break; + case 4: + M_x_RotY(angles[1]); + M_x_RotZ(angles[2]); + M_x_RotX(angles[0]); + break; + case 1: + M_x_RotY(angles[1]); + M_x_RotX(angles[0]); + M_x_RotZ(angles[2]); + break; + case 2: + M_x_RotX(angles[0]); + M_x_RotZ(angles[2]); + M_x_RotY(angles[1]); + break; + case 0: + M_x_RotX(angles[0]); + M_x_RotY(angles[1]); + M_x_RotZ(angles[2]); + break; + default: + NOTREACHED; + } + } + + // Load euler rotations (v %= 1). + + void CreateXRotation(T v) { + T s = (T)std::sin(v * T(PI2d)); + T c = (T)std::cos(v * T(PI2d)); + _M_SET_ROW(0, 1, 0, 0, 0); + _M_SET_ROW(1, 0, c, s, 0); + _M_SET_ROW(2, 0, -s, c, 0); + _M_SET_ROW(3, 0, 0, 0, 1); + } + + void CreateYRotation(T v) { + T s = (T)std::sin(v * T(PI2d)); + T c = (T)std::cos(v * T(PI2d)); + _M_SET_ROW(0, c, 0, -s, 0); + _M_SET_ROW(1, 0, 1, 0, 0); + _M_SET_ROW(2, s, 0, c, 0); + _M_SET_ROW(3, 0, 0, 0, 1); + } + + void CreateZRotation(T v) { + T s = (T)std::sin(v * T(PI2d)); + T c = (T)std::cos(v * T(PI2d)); + _M_SET_ROW(0, c, s, 0, 0); + _M_SET_ROW(1, -s, c, 0, 0); + _M_SET_ROW(2, 0, 0, 1, 0); + _M_SET_ROW(3, 0, 0, 0, 1); + } + + // Load euler rotations (v %= 1). + + void CreateXRotation3x3(T v) { + T s = (T)std::sin(v * T(PI2d)); + T c = (T)std::cos(v * T(PI2d)); + _M_SET_ROW3x3(0, 1, 0, 0); + _M_SET_ROW3x3(1, 0, c, s); + _M_SET_ROW3x3(2, 0, -s, c); + } + + void CreateYRotation3x3(T v) { + T s = (T)std::sin(v * T(PI2d)); + T c = (T)std::cos(v * T(PI2d)); + _M_SET_ROW3x3(0, c, 0, -s); + _M_SET_ROW3x3(1, 0, 1, 0); + _M_SET_ROW3x3(2, s, 0, c); + } + + void CreateZRotation3x3(T v) { + T s = (T)std::sin(v * T(PI2d)); + T c = (T)std::cos(v * T(PI2d)); + _M_SET_ROW3x3(0, c, s, 0); + _M_SET_ROW3x3(1, -s, c, 0); + _M_SET_ROW3x3(2, 0, 0, 1); + } + + // Multiply by euler rotations (v %= 1). + + void M_x_RotX(T v) { + T v2pi = v * T(PI2d); + T sn = (T)std::sin(v2pi); + T cs = (T)std::cos(v2pi); + RotateElements(k[0][1], k[0][2], cs, sn); + RotateElements(k[1][1], k[1][2], cs, sn); + RotateElements(k[2][1], k[2][2], cs, sn); + } + + void RotX_x_M(T v) { + T v2pi = v * T(PI2d); + T sn = (T)std::sin(v2pi); + T cs = (T)std::cos(v2pi); + RotateElements(k[1][0], k[2][0], cs, sn); + RotateElements(k[1][1], k[2][1], cs, sn); + RotateElements(k[1][2], k[2][2], cs, sn); + } + + void M_x_RotY(T v) { + T v2pi = v * T(PI2d); + T sn = (T)-std::sin(v2pi); + T cs = (T)std::cos(v2pi); + RotateElements(k[0][0], k[0][2], cs, sn); + RotateElements(k[1][0], k[1][2], cs, sn); + RotateElements(k[2][0], k[2][2], cs, sn); + } + + void RotY_x_M(T v) { + T v2pi = v * T(PI2d); + T sn = (T)-std::sin(v2pi); + T cs = (T)std::cos(v2pi); + RotateElements(k[0][0], k[2][0], cs, sn); + RotateElements(k[0][1], k[2][1], cs, sn); + RotateElements(k[0][2], k[2][2], cs, sn); + } + + void M_x_RotZ(T v) { + T v2pi = v * T(PI2d); + T sn = (T)std::sin(v2pi); + T cs = (T)std::cos(v2pi); + RotateElements(k[0][0], k[0][1], cs, sn); + RotateElements(k[1][0], k[1][1], cs, sn); + RotateElements(k[2][0], k[2][1], cs, sn); + } + + void RotZ_x_M(T v) { + T v2pi = v * T(PI2d); + T sn = (T)std::sin(v2pi); + T cs = (T)std::cos(v2pi); + RotateElements(k[0][0], k[1][0], cs, sn); + RotateElements(k[0][1], k[1][1], cs, sn); + RotateElements(k[0][2], k[1][2], cs, sn); + } + + // Normalize and make it orthogonal. + template + void RecreateMatrix() { + // Normalize the priority0 row, and use it together with the priority1 row + // to create an orthogonal matrix. The third row is ignored. + DCHECK(priority0 >= 0 && priority1 <= 2); + int missing = 3 - (priority0 + priority1); + constexpr int type = priority0 - priority1; + if constexpr (type == -1 || type == 2) { + GetRow(priority0).Normalize(); + GetRow(missing) = + -(GetRow(priority1).CrossProduct(GetRow(priority0))).Normalize(); + GetRow(priority1) = GetRow(missing).CrossProduct(GetRow(priority0)); + } else { + GetRow(priority0).Normalize(); + GetRow(missing) = + (GetRow(priority1).CrossProduct(GetRow(priority0))).Normalize(); + GetRow(priority1) = GetRow(priority0).CrossProduct(GetRow(missing)); + } + } + + // Get euler-angles. + Vector3 GetAngles(int angle_priority) const { + Vector3 angles; + switch (angle_priority) { + case 5: { + CreateAngleZYXFromMatrix(angles, k[0][0], k[0][1], k[0][2], k[1][1], + k[1][1], k[1][2], k[2][2], k[2][1], k[2][2]); + break; + } + case 3: { + Vector3 a; + CreateAngleZYXFromMatrix(a, k[1][1], k[1][0], k[1][2], k[0][1], k[0][0], + k[0][2], k[2][1], k[2][0], k[2][2]); + angles[0] = -a[1]; + angles[1] = -a[0]; + angles[2] = -a[2]; + break; + } + case 4: { + Vector3 a; + CreateAngleZYXFromMatrix(a, k[0][0], k[0][2], k[0][1], k[2][0], k[2][2], + k[2][1], k[1][0], k[1][2], k[1][1]); + angles[0] = -a[0]; + angles[1] = -a[2]; + angles[2] = -a[1]; + break; + } + case 1: { + Vector3 a; + CreateAngleZYXFromMatrix(a, k[0][0], k[0][1], k[0][2], k[1][0], k[1][1], + k[1][2], k[2][0], k[2][1], k[2][2]); + angles[0] = a[1]; + angles[1] = a[2]; + angles[2] = a[0]; + break; + } + case 2: { + Vector3 a; + CreateAngleZYXFromMatrix(a, k[1][1], k[1][2], k[1][0], k[2][1], k[2][2], + k[2][0], k[0][1], k[0][2], k[0][0]); + angles[2] = a[1]; + angles[1] = a[0]; + angles[0] = a[2]; + break; + } + case 0: { + Vector3 a; + CreateAngleZYXFromMatrix(a, k[2][2], k[2][1], k[2][0], k[1][2], k[1][1], + k[1][0], k[0][2], k[0][1], k[0][0]); + angles[1] = -a[1]; + angles[2] = -a[0]; + angles[0] = -a[2]; + break; + } + default: + NOTREACHED; + } + return -angles; + } + + void Lerp(const Matrix4& other, float t, Matrix4& dst) const { + Quaternion q1, q2, qr; + q1.Create(*this); + q2.Create(other); + q1.Lerp(q2, t, qr); + qr.CreateMatrix(dst); + dst.GetRow(3) = base::Lerp(GetRow(3), other.GetRow(3), t); + } + + Vector3& GetRow(int row) { return *((Vector3*)&k[row][0]); } + + const Vector3& GetRow(int row) const { + return *((const Vector3*)&k[row][0]); + } + + const T* GetData() const { return &k[0][0]; } + + std::string ToString() { + using namespace std::string_literals; + std::string str = "("; + for (int row = 0; row < 4; row++) + str += "("s + std::to_string(k[row][0]) + ", "s + + std::to_string(k[row][1]) + ", "s + std::to_string(k[row][2]) + + ", "s + std::to_string(k[row][3]) + "), "s; + str.pop_back(); + str.pop_back(); + return str + ")"; + } +}; + +// +// Quaternion +// + +template +class Quaternion { + public: + T k[4]; + + Quaternion() {} + + Quaternion(const Vector3& v, T w) { Create(v, w); } + + Quaternion(T x, T y, T z, T w) { + k[0] = x; + k[1] = y; + k[2] = z; + k[3] = w; + } + + void operator=(const Quaternion& q) { k = q.k; } + + // Create from axis-angle + void Create(const Vector3& v, T angle) { + T x = v[0]; + T y = v[1]; + T z = v[2]; + T len_sqr = Sqr(x) + Sqr(y) + Sqr(z); + + if (Abs(len_sqr - T(1.0)) > 0) { + T len = std::sqrt(len_sqr); + x = x / len; + y = y / len; + z = z / len; + } + + T a = angle * (T(1.0) / T(2.0) * T(PId) * T(2.0)); + k[3] = std::cos(a); + T sn = std::sin(a); + k[0] = x * sn; + k[1] = y * sn; + k[2] = z * sn; + } + + // Create from euler angles + void Create(const Vector3& v) { + Quaternion roll(Vector3(0, 0, 1), v[2]); + Quaternion pitch(Vector3(1, 0, 0), v[0]); + Quaternion yaw(Vector3(0, 1, 0), v[1]); + + *this = roll; + Multiply(pitch); + Multiply(yaw); + } + + // Create from matrix + void Create(const Matrix4& mat) { + T trace = T(0); + for (int i = 0; i < 3; i++) + trace += mat.k[i][i]; + + if (trace > T(0)) { + T s = std::sqrt(trace + T(1.0)); + k[3] = s * T(0.5); + s = T(0.5) / s; + + for (int i = 0; i < 3; i++) { + int j = (i == 2) ? 0 : (i + 1); + int m = (j == 2) ? 0 : (j + 1); + k[i] = (mat.k[m][j] - mat.k[j][m]) * s; + } + } else { + int i = 0; + if (mat.k[1][1] > mat.k[0][0]) + i = 1; + if (mat.k[2][2] > mat.k[i][i]) + i = 2; + int j = (i == 2) ? 0 : (i + 1); + int m = (j == 2) ? 0 : (j + 1); + + T s = std::sqrt((mat.k[i][i] - (mat.k[j][j] + mat.k[m][m])) + T(1.0)); + k[i] = s * T(0.5); + s = T(0.5) / s; + k[3] = (mat.k[m][j] - mat.k[j][m]) * s; + k[j] = (mat.k[j][i] + mat.k[i][j]) * s; + k[m] = (mat.k[m][i] + mat.k[i][m]) * s; + } + } + + void Create(T x, T y, T z, T w) { + k[0] = x; + k[1] = y; + k[2] = z; + k[3] = w; + } + + bool operator==(const Quaternion& q) const { + return ((k[0] == q.k[0]) && (k[1] == q.k[1]) && (k[2] == q.k[2]) && + (k[3] == q.k[3])); + } + + bool operator!=(const Quaternion& q) const { + return !((k[0] == q.k[0]) && (k[1] == q.k[1]) && (k[2] == q.k[2]) && + (k[3] == q.k[3])); + } + + void Unit() { + k[0] = T(0.0); + k[1] = T(0.0); + k[2] = T(0.0); + k[3] = T(1.0); + } + + void Normalize() { + T k0 = k[0]; + T k1 = k[1]; + T k2 = k[2]; + T k3 = k[3]; + T len_sqr = Sqr(k0) + Sqr(k1) + Sqr(k2) + Sqr(k3); + if (len_sqr != T(0)) { + T len = std::sqrt(len_sqr); + k[0] = k0 / len; + k[1] = k1 / len; + k[2] = k2 / len; + k[3] = k3 / len; + } + } + + void Inverse() { + k[0] = -k[0]; + k[1] = -k[1]; + k[2] = -k[2]; + // k[3] = k[3]; + } + + T DotProd(const Quaternion& q) const { + T k0 = k[0]; + T k1 = k[1]; + T k2 = k[2]; + T k3 = k[3]; + T qk0 = q.k[0]; + T qk1 = q.k[1]; + T qk2 = q.k[2]; + T qk3 = q.k[3]; + return k0 * qk0 + k1 * qk1 + k2 * qk2 + k3 * qk3; + } + + void Lerp(const Quaternion& other, T t, Quaternion& dst) const { + T a0 = k[0]; + T a1 = k[1]; + T a2 = k[2]; + T a3 = k[3]; + + T dot = + (a0 * other.k[0] + a1 * other.k[1] + a2 * other.k[2] + a3 * other.k[3]); + T u = Sel(dot, T(1.0) - t, t - T(1.0)); + + T d0 = a0 * u + other.k[0] * t; + T d1 = a1 * u + other.k[1] * t; + T d2 = a2 * u + other.k[2] * t; + T d3 = a3 * u + other.k[3] * t; + T len_sqr = Sqr(d0) + Sqr(d1) + Sqr(d2) + Sqr(d3); + if (len_sqr != T(0)) { + T len = std::sqrt(len_sqr); + dst.k[0] = d0 / len; + dst.k[1] = d1 / len; + dst.k[2] = d2 / len; + dst.k[3] = d3 / len; + } + } + + void Multiply(const Quaternion& other, Quaternion& dst) const { + T a0 = k[0]; + T a1 = k[1]; + T a2 = k[2]; + T a3 = k[3]; + T b0 = other.k[0]; + T b1 = other.k[1]; + T b2 = other.k[2]; + T b3 = other.k[3]; + dst.k[0] = a3 * b0 + a0 * b3 + a1 * b2 - a2 * b1; + dst.k[1] = a3 * b1 + a1 * b3 + a2 * b0 - a0 * b2; + dst.k[2] = a3 * b2 + a2 * b3 + a0 * b1 - a1 * b0; + dst.k[3] = a3 * b3 - a0 * b0 - a1 * b1 - a2 * b2; + } + + void Multiply(const Quaternion& other) { + T a0 = k[0]; + T a1 = k[1]; + T a2 = k[2]; + T a3 = k[3]; + T b0 = other.k[0]; + T b1 = other.k[1]; + T b2 = other.k[2]; + T b3 = other.k[3]; + k[0] = a3 * b0 + a0 * b3 + a1 * b2 - a2 * b1; + k[1] = a3 * b1 + a1 * b3 + a2 * b0 - a0 * b2; + k[2] = a3 * b2 + a2 * b3 + a0 * b1 - a1 * b0; + k[3] = a3 * b3 - a0 * b0 - a1 * b1 - a2 * b2; + } + + void operator*=(const Quaternion& other) { Multiply(other); } + + Quaternion operator*(const Quaternion& other) const { + Quaternion q; + Multiply(other, q); + return q; + } + + T CreateAxisAngle(Vector3& v) const { + DCHECK(((k[3] >= -T(1.0)) || (k[3] <= T(1.0))) + << "Quaternion needs normalizing."); + + T LenSqr = Sqr(k[0]) + Sqr(k[1]) + Sqr(k[2]); + if (LenSqr > T(0.000001)) { + T len = std::sqrt(LenSqr); + v[0] = k[0] / len; + v[1] = k[1] / len; + v[2] = k[2] / len; + return T(2.0) * std::acos(k[3]) / T(PI2d); // Angle + } else { + // angle is 0 (mod 2*pi), so any axis will do + v[0] = T(1.0); + v[1] = T(0.0); + v[2] = T(0.0); + return 0; // Angle + } + } + + void CreateMatrix3x3(Matrix4& mat) const { + T xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz; + T s = T(2.0); + + xs = k[0] * s; + ys = k[1] * s; + zs = k[2] * s; + wx = k[3] * xs; + wy = k[3] * ys; + wz = k[3] * zs; + xx = k[0] * xs; + xy = k[0] * ys; + xz = k[0] * zs; + yy = k[1] * ys; + yz = k[1] * zs; + zz = k[2] * zs; + + mat.k[0][0] = (T(1.0) - (yy + zz)); + mat.k[0][1] = (xy - wz); + mat.k[0][2] = (xz + wy); + mat.k[1][0] = (xy + wz); + mat.k[1][1] = (T(1.0) - (xx + zz)); + mat.k[1][2] = (yz - wx); + mat.k[2][0] = (xz - wy); + mat.k[2][1] = (yz + wx); + mat.k[2][2] = (T(1.0) - (xx + yy)); + } + + void CreateMatrix(Matrix4& mat) const { + CreateMatrix3x3(mat); + mat.UnitNot3x3(); + } + + std::string ToString() { + using namespace std::string_literals; + return "("s + std::to_string(k[0]) + ", "s + std::to_string(k[1]) + + std::to_string(k[2]) + ", "s + std::to_string(k[3]) + ")"s; + } +}; + +using Vector2f = Vector2; +using Vector3f = Vector3; +using Vector4f = Vector4; +using Matrix4f = Matrix4; +using Quatf = Quaternion; } // namespace base diff --git a/src/demo/credits.cc b/src/demo/credits.cc index 5c5e55c..04774ba 100644 --- a/src/demo/credits.cc +++ b/src/demo/credits.cc @@ -18,7 +18,7 @@ constexpr char kCreditsLines[Credits::kNumLines][15] = { constexpr float kLineSpaces[Credits::kNumLines - 1] = {1.5f, 0.5f, 1.5f, 0.5f}; -const Vector4 kTextColor = {0.80f, 0.87f, 0.93f, 1}; +const Vector4f kTextColor = {0.80f, 0.87f, 0.93f, 1}; constexpr float kFadeSpeed = 0.2f; } // namespace @@ -64,12 +64,12 @@ void Credits::Show() { text_[i].Create("credits", {1, kNumLines}); text_[i].SetZOrder(50); text_[i].SetPosition({0, 0}); - text_[i].SetColor(kTextColor * Vector4(1, 1, 1, 0)); + text_[i].SetColor(kTextColor * Vector4f(1, 1, 1, 0)); text_[i].SetFrame(i); if (i > 0) { text_[i].PlaceToBottomOf(text_[i - 1]); - text_[i].Translate(text_[i - 1].GetPosition() * Vector2(0, 1)); + text_[i].Translate(text_[i - 1].GetPosition() * Vector2f(0, 1)); text_[i].Translate({0, text_[i - 1].GetSize().y * -kLineSpaces[i - 1]}); } } @@ -94,7 +94,7 @@ void Credits::Hide() { text_animator_.SetEndCallback(Animator::kBlending, nullptr); text_animator_.SetVisible(false); }); - text_animator_.SetBlending(kTextColor * Vector4(1, 1, 1, 0), kFadeSpeed); + text_animator_.SetBlending(kTextColor * Vector4f(1, 1, 1, 0), kFadeSpeed); text_animator_.Play(Animator::kBlending, false); } diff --git a/src/demo/demo.cc b/src/demo/demo.cc index cf69eca..781826e 100644 --- a/src/demo/demo.cc +++ b/src/demo/demo.cc @@ -193,9 +193,9 @@ void Demo::UpdateGameState(float delta_time) { float weights[3] = {0, 0, 0}; weights[dominant_channel] = 1; - Vector4 c = {Lerp(0.75f, 0.95f, rnd.GetFloat()) * weights[0], - Lerp(0.75f, 0.95f, rnd.GetFloat()) * weights[1], - Lerp(0.75f, 0.95f, rnd.GetFloat()) * weights[2], 1}; + Vector4f c = {Lerp(0.75f, 0.95f, rnd.GetFloat()) * weights[0], + Lerp(0.75f, 0.95f, rnd.GetFloat()) * weights[1], + Lerp(0.75f, 0.95f, rnd.GetFloat()) * weights[2], 1}; c += {Lerp(0.1f, 0.5f, rnd.GetFloat()) * (1 - weights[0]), Lerp(0.1f, 0.5f, rnd.GetFloat()) * (1 - weights[1]), Lerp(0.1f, 0.5f, rnd.GetFloat()) * (1 - weights[2]), 1}; diff --git a/src/demo/enemy.cc b/src/demo/enemy.cc index 9706020..a8d90cb 100644 --- a/src/demo/enemy.cc +++ b/src/demo/enemy.cc @@ -96,19 +96,19 @@ bool Enemy::HasTarget(DamageType damage_type) { return GetTarget(damage_type) ? true : false; } -Vector2 Enemy::GetTargetPos(DamageType damage_type) { +Vector2f Enemy::GetTargetPos(DamageType damage_type) { DCHECK(damage_type > kDamageType_Invalid && damage_type < kDamageType_Any); EnemyUnit* target = GetTarget(damage_type); if (target) return target->sprite.GetPosition() - - Vector2(0, target->sprite.GetSize().y / 2.5f); + Vector2f(0, target->sprite.GetSize().y / 2.5f); return {0, 0}; } void Enemy::SelectTarget(DamageType damage_type, - const Vector2& origin, - const Vector2& dir, + const Vector2f& origin, + const Vector2f& dir, float snap_factor) { DCHECK(damage_type > kDamageType_Invalid && damage_type < kDamageType_Any); @@ -132,8 +132,8 @@ void Enemy::SelectTarget(DamageType damage_type, e.sprite.GetSize() * snap_factor, origin, dir)) continue; - Vector2 weapon_enemy_dir = e.sprite.GetPosition() - origin; - float enemy_weapon_dist = weapon_enemy_dir.Magnitude(); + Vector2f weapon_enemy_dir = e.sprite.GetPosition() - origin; + float enemy_weapon_dist = weapon_enemy_dir.Length(); if (closest_dist > enemy_weapon_dist) { closest_dist = enemy_weapon_dist; best_enemy = &e; @@ -238,7 +238,7 @@ void Enemy::TakeDamage(EnemyUnit* target, int damage) { } else { target->targetted_by_weapon_ = kDamageType_Invalid; - Vector2 s = target->sprite.GetSize() * Vector2(0.6f, 0.01f); + Vector2f s = target->sprite.GetSize() * Vector2f(0.6f, 0.01f); s.x *= (float)target->hit_points / (float)target->total_health; float t = (s.x - target->health_bar.GetSize().x) / 2; target->health_bar.SetSize(s); @@ -279,14 +279,14 @@ void Enemy::SpawnNextEnemy() { ? kDamageType_Any : (DamageType)(rnd.Roll(2) - 1); - Vector2 s = engine.GetScreenSize(); + Vector2f s = engine.GetScreenSize(); int col; col = rnd.Roll(4) - 1; if (col == last_spawn_col_) col = (col + 1) % 4; last_spawn_col_ = col; float x = (s.x / 4) / 2 + (s.x / 4) * col - s.x / 2; - Vector2 pos = {x, s.y / 2}; + Vector2f pos = {x, s.y / 2}; float speed = enemy_type == kEnemyType_Tank ? 36.0f : (rnd.Roll(4) == 4 ? 6.0f : 10.0f); @@ -295,7 +295,7 @@ void Enemy::SpawnNextEnemy() { void Enemy::Spawn(EnemyType enemy_type, DamageType damage_type, - const Vector2& pos, + const Vector2f& pos, float speed) { DCHECK(enemy_type > kEnemyType_Invalid && enemy_type < kEnemyType_Max); DCHECK(damage_type > kDamageType_Invalid && damage_type < kDamageType_Max); @@ -318,7 +318,7 @@ void Enemy::Spawn(EnemyType enemy_type, } e.sprite.SetZOrder(11); e.sprite.SetVisible(true); - Vector2 spawn_pos = pos + Vector2(0, e.sprite.GetSize().y / 2); + Vector2f spawn_pos = pos + Vector2f(0, e.sprite.GetSize().y / 2); e.sprite.SetPosition(spawn_pos); e.sprite.SetFrame(enemy_frame_start[enemy_type][damage_type]); @@ -337,13 +337,13 @@ void Enemy::Spawn(EnemyType enemy_type, e.blast.SetPosition(spawn_pos); e.health_base.SetZOrder(11); - e.health_base.SetSize(e.sprite.GetSize() * Vector2(0.6f, 0.01f)); + e.health_base.SetSize(e.sprite.GetSize() * Vector2f(0.6f, 0.01f)); e.health_base.SetPosition(spawn_pos); e.health_base.PlaceToBottomOf(e.sprite); e.health_base.SetColor({0.5f, 0.5f, 0.5f, 1}); e.health_bar.SetZOrder(11); - e.health_bar.SetSize(e.sprite.GetSize() * Vector2(0.6f, 0.01f)); + e.health_bar.SetSize(e.sprite.GetSize() * Vector2f(0.6f, 0.01f)); e.health_bar.SetPosition(spawn_pos); e.health_bar.PlaceToBottomOf(e.sprite); e.health_bar.SetColor({0.161f, 0.89f, 0.322f, 1}); diff --git a/src/demo/enemy.h b/src/demo/enemy.h index 96d0122..50295ba 100644 --- a/src/demo/enemy.h +++ b/src/demo/enemy.h @@ -29,11 +29,11 @@ class Enemy { void Pause(bool pause); bool HasTarget(DamageType damage_type); - base::Vector2 GetTargetPos(DamageType damage_type); + base::Vector2f GetTargetPos(DamageType damage_type); void SelectTarget(DamageType damage_type, - const base::Vector2& origin, - const base::Vector2& dir, + const base::Vector2f& origin, + const base::Vector2f& dir, float snap_factor); void DeselectTarget(DamageType damage_type); @@ -97,7 +97,7 @@ class Enemy { void Spawn(EnemyType enemy_type, DamageType damage_type, - const base::Vector2& pos, + const base::Vector2f& pos, float speed); EnemyUnit* GetTarget(DamageType damage_type); diff --git a/src/demo/hud.cc b/src/demo/hud.cc index 8b41e9a..e5f1da9 100644 --- a/src/demo/hud.cc +++ b/src/demo/hud.cc @@ -18,9 +18,9 @@ namespace { constexpr float kHorizontalMargin = 0.07f; constexpr float kVerticalMargin = 0.025f; -const Vector4 kPprogressBarColor[2] = {{0.256f, 0.434f, 0.72f, 1}, - {0.905f, 0.493f, 0.194f, 1}}; -const Vector4 kTextColor = {0.895f, 0.692f, 0.24f, 1}; +const Vector4f kPprogressBarColor[2] = {{0.256f, 0.434f, 0.72f, 1}, + {0.905f, 0.493f, 0.194f, 1}}; +const Vector4f kTextColor = {0.895f, 0.692f, 0.24f, 1}; } // namespace @@ -42,22 +42,23 @@ bool Hud::Initialize() { for (int i = 0; i < 2; ++i) { text_[i].Create("text"s + std::to_string(i)); text_[i].SetZOrder(30); - text_[i].SetColor(kTextColor * Vector4(1, 1, 1, 0)); + text_[i].SetColor(kTextColor * Vector4f(1, 1, 1, 0)); - Vector2 pos = (engine.GetScreenSize() / 2 - text_[i].GetSize() / 2); - pos -= engine.GetScreenSize() * Vector2(kHorizontalMargin, kVerticalMargin); + Vector2f pos = (engine.GetScreenSize() / 2 - text_[i].GetSize() / 2); + pos -= + engine.GetScreenSize() * Vector2f(kHorizontalMargin, kVerticalMargin); - Vector2 scale = engine.GetScreenSize() * Vector2(1, 0); - scale -= engine.GetScreenSize() * Vector2(kHorizontalMargin * 4, 0); - scale += text_[0].GetSize() * Vector2(0, 0.3f); + Vector2f scale = engine.GetScreenSize() * Vector2f(1, 0); + scale -= engine.GetScreenSize() * Vector2f(kHorizontalMargin * 4, 0); + scale += text_[0].GetSize() * Vector2f(0, 0.3f); progress_bar_[i].SetZOrder(30); progress_bar_[i].SetSize(scale); - progress_bar_[i].Translate(pos * Vector2(0, 1)); - progress_bar_[i].SetColor(kPprogressBarColor[i] * Vector4(1, 1, 1, 0)); + progress_bar_[i].Translate(pos * Vector2f(0, 1)); + progress_bar_[i].SetColor(kPprogressBarColor[i] * Vector4f(1, 1, 1, 0)); - pos -= progress_bar_[i].GetSize() * Vector2(0, 4); - text_[i].Translate(pos * Vector2(i ? 1 : -1, 1)); + pos -= progress_bar_[i].GetSize() * Vector2f(0, 4); + text_[i].Translate(pos * Vector2f(i ? 1 : -1, 1)); progress_bar_animator_[i].Attach(&progress_bar_[i]); @@ -111,7 +112,7 @@ void Hud::SetWave(int wave, bool flash) { void Hud::SetProgress(float progress) { progress = std::min(std::max(0.0f, progress), 1.0f); last_progress_ = progress; - Vector2 s = progress_bar_[0].GetSize() * Vector2(progress, 1); + Vector2f s = progress_bar_[0].GetSize() * Vector2f(progress, 1); float t = (s.x - progress_bar_[1].GetSize().x) / 2; progress_bar_[1].SetSize(s); progress_bar_[1].Translate({t, 0}); diff --git a/src/demo/menu.cc b/src/demo/menu.cc index e4a8b7b..28aede8 100644 --- a/src/demo/menu.cc +++ b/src/demo/menu.cc @@ -22,11 +22,11 @@ constexpr char kMenuOption[Menu::kOption_Max][10] = {"continue", "start", constexpr float kMenuOptionSpace = 1.5f; -const Vector4 kColorNormal = {1, 1, 1, 1}; -const Vector4 kColorHighlight = {5, 5, 5, 1}; +const Vector4f kColorNormal = {1, 1, 1, 1}; +const Vector4f kColorHighlight = {5, 5, 5, 1}; constexpr float kBlendingSpeed = 0.12f; -const Vector4 kColorFadeOut = {1, 1, 1, 0}; +const Vector4f kColorFadeOut = {1, 1, 1, 0}; constexpr float kFadeSpeed = 0.2f; } // namespace @@ -76,10 +76,12 @@ bool Menu::Initialize() { } void Menu::OnInputEvent(std::unique_ptr event) { - if (event->GetType() == InputEvent::kDragStart) - tap_pos_[0] = tap_pos_[1] = event->GetVector(); - else if (event->GetType() == InputEvent::kDrag) + if (event->GetType() == InputEvent::kDragStart) { + tap_pos_[0] = event->GetVector(); tap_pos_[1] = event->GetVector(); + } else if (event->GetType() == InputEvent::kDrag) { + tap_pos_[1] = event->GetVector(); + } if (event->GetType() != InputEvent::kDragEnd || IsAnimating()) return; @@ -88,10 +90,12 @@ void Menu::OnInputEvent(std::unique_ptr event) { if (items_[i].hide) continue; if (!Intersection(items_[i].text.GetPosition(), - items_[i].text.GetSize() * Vector2(1.2f, 2), tap_pos_[0])) + items_[i].text.GetSize() * Vector2f(1.2f, 2), + tap_pos_[0])) continue; if (!Intersection(items_[i].text.GetPosition(), - items_[i].text.GetSize() * Vector2(1.2f, 2), tap_pos_[1])) + items_[i].text.GetSize() * Vector2f(1.2f, 2), + tap_pos_[1])) continue; items_[i].text_animator.SetEndCallback(Animator::kBlending, @@ -111,7 +115,7 @@ void Menu::SetOptionEnabled(Option o, bool enable) { if (last >= 0) { items_[i].text.PlaceToBottomOf(items_[last].text); items_[i].text.Translate(items_[last].text.GetPosition() * - Vector2(0, 1)); + Vector2f(0, 1)); items_[i].text.Translate( {0, items_[last].text.GetSize().y * -kMenuOptionSpace}); } diff --git a/src/demo/menu.h b/src/demo/menu.h index c7324d0..66dbbd0 100644 --- a/src/demo/menu.h +++ b/src/demo/menu.h @@ -53,7 +53,7 @@ class Menu { Option selected_option_ = kOption_Invalid; - base::Vector2 tap_pos_[2] = {{0, 0}, {0, 0}}; + base::Vector2f tap_pos_[2] = {{0, 0}, {0, 0}}; bool CreateRenderResources(); diff --git a/src/demo/player.cc b/src/demo/player.cc index d601f70..674bea8 100644 --- a/src/demo/player.cc +++ b/src/demo/player.cc @@ -57,21 +57,21 @@ void Player::OnInputEvent(std::unique_ptr event) { DragCancel(); } -Vector2 Player::GetWeaponPos(DamageType type) const { +Vector2f Player::GetWeaponPos(DamageType type) const { return Engine::Get().GetScreenSize() / - Vector2(type == kDamageType_Green ? 3.5f : -3.5f, -2) + - Vector2(0, weapon_[type].GetSize().y * 0.7f); + Vector2f(type == kDamageType_Green ? 3.5f : -3.5f, -2) + + Vector2f(0, weapon_[type].GetSize().y * 0.7f); } -Vector2 Player::GetWeaponScale() const { +Vector2f Player::GetWeaponScale() const { return weapon_[0].GetSize(); } -DamageType Player::GetWeaponType(const Vector2& pos) { +DamageType Player::GetWeaponType(const Vector2f& pos) { DamageType closest_weapon = kDamageType_Invalid; float closest_dist = std::numeric_limits::max(); for (int i = 0; i < 2; ++i) { - float dist = (pos - weapon_[i].GetPosition()).Magnitude(); + float dist = (pos - weapon_[i].GetPosition()).Length(); if (dist < closest_dist) { closest_dist = dist; closest_weapon = (DamageType)i; @@ -94,7 +94,7 @@ void Player::CooldownWeapon(DamageType type) { cooldown_animator_[type].Play(Animator::kFrames, false); } -void Player::Fire(DamageType type, Vector2 dir) { +void Player::Fire(DamageType type, Vector2f dir) { Engine& engine = Engine::Get(); Enemy& enemy = static_cast(engine.GetGame())->GetEnemy(); @@ -103,12 +103,12 @@ void Player::Fire(DamageType type, Vector2 dir) { else dir *= engine.GetScreenSize().y * 1.3f; - float len = dir.Magnitude(); + float len = dir.Length(); beam_[type].SetSize({len, beam_[type].GetSize().y}); beam_[type].SetPosition(weapon_[type].GetPosition()); dir.Normalize(); - float cos_theta = dir.DotProduct(Vector2(1, 0)); + float cos_theta = dir.DotProduct(Vector2f(1, 0)); float theta = acos(cos_theta) + M_PI; beam_[type].SetTheta(theta); auto offset = beam_[type].GetRotation() * (len / 2); @@ -120,7 +120,7 @@ void Player::Fire(DamageType type, Vector2 dir) { spark_animator_[type].Stop(Animator::kMovement); float length = beam_[type].GetSize().x * 0.9f; - Vector2 movement = dir * -length; + Vector2f movement = dir * -length; // Convert from units per second to duration. float speed = 1.0f / (18.0f / length); spark_animator_[type].SetMovement(movement, speed); @@ -139,7 +139,7 @@ void Player::SetupWeapons() { drag_sign_[i].SetZOrder(21); drag_sign_[i].SetFrame(i * 8); - Vector2 pos = GetWeaponPos((DamageType)i); + Vector2f pos = GetWeaponPos((DamageType)i); // Setup weapon. weapon_[i].Create("weapon_tex", {8, 2}); @@ -153,7 +153,7 @@ void Player::SetupWeapons() { beam_[i].SetZOrder(22); beam_[i].SetFrame(i); beam_[i].SetPosition(pos); - beam_[i].Translate(beam_[i].GetSize() * Vector2(-0.5f, -0.5f)); + beam_[i].Translate(beam_[i].GetSize() * Vector2f(-0.5f, -0.5f)); // Setup beam spark. beam_spark_[i].Create("weapon_tex", {8, 2}); @@ -200,7 +200,7 @@ void Player::UpdateTarget() { Demo* game = static_cast(engine.GetGame()); if (drag_valid_) { - Vector2 dir = (drag_end_ - drag_start_).Normalize(); + Vector2f dir = (drag_end_ - drag_start_).Normalize(); game->GetEnemy().SelectTarget(active_weapon_, drag_start_, dir, 1.2f); if (!game->GetEnemy().HasTarget(active_weapon_)) game->GetEnemy().SelectTarget(active_weapon_, drag_start_, dir, 2); @@ -209,18 +209,19 @@ void Player::UpdateTarget() { } } -void Player::DragStart(const Vector2& pos) { +void Player::DragStart(const Vector2f& pos) { active_weapon_ = GetWeaponType(pos); if (active_weapon_ == kDamageType_Invalid) return; - drag_start_ = drag_end_ = pos; + drag_start_ = pos; + drag_end_ = pos; drag_sign_[active_weapon_].SetPosition(drag_start_); drag_sign_[active_weapon_].SetVisible(true); } -void Player::Drag(const Vector2& pos) { +void Player::Drag(const Vector2f& pos) { if (active_weapon_ == kDamageType_Invalid) return; @@ -248,7 +249,7 @@ void Player::DragEnd() { active_weapon_ = kDamageType_Invalid; drag_sign_[type].SetVisible(false); - Vector2 fire_dir = (drag_start_ - drag_end_).Normalize(); + Vector2f fire_dir = (drag_start_ - drag_end_).Normalize(); if (drag_valid_ && !IsFiring(type)) { if (warmup_animator_[type].IsPlaying(Animator::kFrames)) { @@ -265,7 +266,8 @@ void Player::DragEnd() { } drag_valid_ = false; - drag_start_ = drag_end_ = {0, 0}; + drag_start_ = {0, 0}; + drag_end_ = {0, 0}; } void Player::DragCancel() { @@ -289,16 +291,17 @@ void Player::DragCancel() { } drag_valid_ = false; - drag_start_ = drag_end_ = {0, 0}; + drag_start_ = {0, 0}; + drag_end_ = {0, 0}; } bool Player::ValidateDrag() { - Vector2 dir = drag_end_ - drag_start_; - float len = dir.Magnitude(); + Vector2f dir = drag_end_ - drag_start_; + float len = dir.Length(); dir.Normalize(); if (len < weapon_[active_weapon_].GetSize().y / 4) return false; - if (dir.DotProduct(Vector2(0, 1)) < 0) + if (dir.DotProduct(Vector2f(0, 1)) < 0) return false; return true; } diff --git a/src/demo/player.h b/src/demo/player.h index e883bb9..af1f5c5 100644 --- a/src/demo/player.h +++ b/src/demo/player.h @@ -25,8 +25,8 @@ class Player { void OnInputEvent(std::unique_ptr event); - base::Vector2 GetWeaponPos(DamageType type) const; - base::Vector2 GetWeaponScale() const; + base::Vector2f GetWeaponPos(DamageType type) const; + base::Vector2f GetWeaponScale() const; private: eng::ImageQuad drag_sign_[2]; @@ -41,24 +41,24 @@ class Player { DamageType active_weapon_ = kDamageType_Invalid; - base::Vector2 drag_start_ = {0, 0}; - base::Vector2 drag_end_ = {0, 0}; + base::Vector2f drag_start_ = {0, 0}; + base::Vector2f drag_end_ = {0, 0}; bool drag_valid_ = false; - DamageType GetWeaponType(const base::Vector2& pos); + DamageType GetWeaponType(const base::Vector2f& pos); void WarmupWeapon(DamageType type); void CooldownWeapon(DamageType type); - void Fire(DamageType type, base::Vector2 dir); + void Fire(DamageType type, base::Vector2f dir); bool IsFiring(DamageType type); void SetupWeapons(); void UpdateTarget(); - void DragStart(const base::Vector2& pos); - void Drag(const base::Vector2& pos); + void DragStart(const base::Vector2f& pos); + void Drag(const base::Vector2f& pos); void DragEnd(); void DragCancel(); bool ValidateDrag(); diff --git a/src/demo/sky_quad.cc b/src/demo/sky_quad.cc index cc4b0b1..ed18bb3 100644 --- a/src/demo/sky_quad.cc +++ b/src/demo/sky_quad.cc @@ -44,7 +44,7 @@ void SkyQuad::Update(float delta_time) { } void SkyQuad::Draw(float frame_frac) { - Vector2 sky_offset = Lerp(last_sky_offset_, sky_offset_, frame_frac); + Vector2f sky_offset = Lerp(last_sky_offset_, sky_offset_, frame_frac); shader_->Activate(); shader_->SetUniform("scale", scale_); @@ -61,7 +61,7 @@ void SkyQuad::ContextLost() { Create(); } -void SkyQuad::SwitchColor(const Vector4& color) { +void SkyQuad::SwitchColor(const Vector4f& color) { color_animator_.SetBlending(color, 5, std::bind(SmoothStep, std::placeholders::_1)); color_animator_.Play(Animator::kBlending, false); diff --git a/src/demo/sky_quad.h b/src/demo/sky_quad.h index db1c9f4..72d3e23 100644 --- a/src/demo/sky_quad.h +++ b/src/demo/sky_quad.h @@ -30,25 +30,25 @@ class SkyQuad : public eng::Animatable { void SetFrame(size_t frame) override {} size_t GetFrame() const override { return 0; } size_t GetNumFrames() const override { return 0; } - void SetColor(const base::Vector4& color) override { nebula_color_ = color; } - base::Vector4 GetColor() const override { return nebula_color_; } + void SetColor(const base::Vector4f& color) override { nebula_color_ = color; } + base::Vector4f GetColor() const override { return nebula_color_; } // Drawable interface. void Draw(float frame_frac) override; void ContextLost(); - void SwitchColor(const base::Vector4& color); + void SwitchColor(const base::Vector4f& color); void SetSpeed(float speed); private: std::unique_ptr shader_; - base::Vector2 sky_offset_ = {0, 0}; - base::Vector2 last_sky_offset_ = {0, 0}; - base::Vector4 nebula_color_ = {0, 0, 0, 1}; - base::Vector2 scale_ = {1, 1}; + base::Vector2f sky_offset_ = {0, 0}; + base::Vector2f last_sky_offset_ = {0, 0}; + base::Vector4f nebula_color_ = {0, 0, 0, 1}; + base::Vector2f scale_ = {1, 1}; eng::Animator color_animator_; diff --git a/src/engine/animatable.cc b/src/engine/animatable.cc index 90cd50a..c2f5018 100644 --- a/src/engine/animatable.cc +++ b/src/engine/animatable.cc @@ -6,11 +6,11 @@ using namespace base; namespace eng { -void Animatable::Translate(const Vector2& pos) { +void Animatable::Translate(const Vector2f& pos) { position_ += pos; } -void Animatable::Scale(const Vector2& scale) { +void Animatable::Scale(const Vector2f& scale) { scale_ = scale; } diff --git a/src/engine/animatable.h b/src/engine/animatable.h index b9d2858..429941d 100644 --- a/src/engine/animatable.h +++ b/src/engine/animatable.h @@ -11,27 +11,27 @@ class Animatable : public Drawable { Animatable() = default; ~Animatable() override = default; - void Translate(const base::Vector2& pos); - void Scale(const base::Vector2& scale); + void Translate(const base::Vector2f& pos); + void Scale(const base::Vector2f& scale); void Scale(float scale); void Rotate(float angle); - void SetPosition(const base::Vector2& pos) { position_ = pos; } - void SetSize(const base::Vector2& size) { size_ = size; } + void SetPosition(const base::Vector2f& pos) { position_ = pos; } + void SetSize(const base::Vector2f& size) { size_ = size; } void SetTheta(float theta); - base::Vector2 GetPosition() const { return position_; } - base::Vector2 GetSize() const { return size_ * scale_; } + base::Vector2f GetPosition() const { return position_; } + base::Vector2f GetSize() const { return size_ * scale_; } float GetTheta() const { return theta_; } - base::Vector2 GetRotation() const { return rotation_; } + base::Vector2f GetRotation() const { return rotation_; } // Pure virtuals for frame animation support. virtual void SetFrame(size_t frame) = 0; virtual size_t GetFrame() const = 0; virtual size_t GetNumFrames() const = 0; - virtual void SetColor(const base::Vector4& color) = 0; - virtual base::Vector4 GetColor() const = 0; + virtual void SetColor(const base::Vector4f& color) = 0; + virtual base::Vector4f GetColor() const = 0; void PlaceToLeftOf(const Animatable& s) { Translate({s.GetSize().x / -2.0f + GetSize().x / -2.0f, 0}); @@ -50,10 +50,10 @@ class Animatable : public Drawable { } protected: - base::Vector2 position_ = {0, 0}; - base::Vector2 size_ = {1, 1}; - base::Vector2 scale_ = {1, 1}; - base::Vector2 rotation_ = {0, 1}; + base::Vector2f position_ = {0, 0}; + base::Vector2f size_ = {1, 1}; + base::Vector2f scale_ = {1, 1}; + base::Vector2f rotation_ = {0, 1}; float theta_ = 0; }; diff --git a/src/engine/animator.cc b/src/engine/animator.cc index 121a9e3..b23e649 100644 --- a/src/engine/animator.cc +++ b/src/engine/animator.cc @@ -116,7 +116,7 @@ void Animator::SetEndCallback(int animation, base::Closure cb) { timer_cb_ = std::move(cb); } -void Animator::SetMovement(Vector2 direction, +void Animator::SetMovement(Vector2f direction, float duration, Interpolator interpolator) { movement_direction_ = direction; @@ -138,7 +138,7 @@ void Animator::SetRotation(float trget, a.rotation_last_theta = 0; } -void Animator::SetBlending(Vector4 target, +void Animator::SetBlending(Vector4f target, float duration, Interpolator interpolator) { blending_target_ = target; @@ -186,7 +186,7 @@ void Animator::EvalAnim(float frame_time) { float time = movement_time_ + movement_speed_ * frame_time; float interpolated_time = movement_interpolator_ ? movement_interpolator_(time) : time; - Vector2 pos = base::Lerp({0, 0}, movement_direction_, interpolated_time); + Vector2f pos = base::Lerp({0, 0}, movement_direction_, interpolated_time); a.animatable->Translate(pos - a.movement_last_pos); a.movement_last_pos = pos; } @@ -204,7 +204,7 @@ void Animator::EvalAnim(float frame_time) { float time = blending_time_ + blending_speed_ * frame_time; float interpolated_time = blending_interpolator_ ? blending_interpolator_(time) : time; - Vector4 r = + Vector4f r = base::Lerp(a.blending_start, blending_target_, interpolated_time); a.animatable->SetColor(r); } diff --git a/src/engine/animator.h b/src/engine/animator.h index cef3772..4f90aa8 100644 --- a/src/engine/animator.h +++ b/src/engine/animator.h @@ -44,7 +44,7 @@ class Animator { void SetEndCallback(int animation, base::Closure cb); // Distance is the magnitude of direction vector. Duration is in seconds. - void SetMovement(base::Vector2 direction, + void SetMovement(base::Vector2f direction, float duration, Interpolator interpolator = nullptr); @@ -53,7 +53,7 @@ class Animator { float duration, Interpolator interpolator = nullptr); - void SetBlending(base::Vector4 target, + void SetBlending(base::Vector4f target, float duration, Interpolator interpolator = nullptr); @@ -76,9 +76,9 @@ class Animator { private: struct Element { Animatable* animatable; - base::Vector2 movement_last_pos = {0, 0}; + base::Vector2f movement_last_pos = {0, 0}; float rotation_last_theta = 0; - base::Vector4 blending_start = {0, 0, 0, 0}; + base::Vector4f blending_start = {0, 0, 0, 0}; int frame_start_ = 0; }; @@ -87,7 +87,7 @@ class Animator { unsigned int resume_flags_ = 0; std::vector elements_; - base::Vector2 movement_direction_ = {0, 0}; + base::Vector2f movement_direction_ = {0, 0}; float movement_speed_ = 0; float movement_time_ = 0; Interpolator movement_interpolator_; @@ -99,7 +99,7 @@ class Animator { Interpolator rotation_interpolator_; base::Closure rotation_cb_; - base::Vector4 blending_target_ = {0, 0, 0, 0}; + base::Vector4f blending_target_ = {0, 0, 0, 0}; float blending_speed_ = 0; float blending_time_ = 0; Interpolator blending_interpolator_; diff --git a/src/engine/engine.cc b/src/engine/engine.cc index dbadeed..a6688da 100644 --- a/src/engine/engine.cc +++ b/src/engine/engine.cc @@ -53,18 +53,17 @@ Engine& Engine::Get() { } bool Engine::Initialize() { - // The orthogonal viewport is (-1.0 .. 1.0) for the short edge of the screen. - // For the long endge, it's calculated from aspect ratio. + // Normalize viewport. if (GetScreenWidth() > GetScreenHeight()) { float aspect_ratio = (float)GetScreenWidth() / (float)GetScreenHeight(); LOG << "aspect ratio: " << aspect_ratio; screen_size_ = {aspect_ratio * 2.0f, 2.0f}; - projection_ = base::Ortho(-aspect_ratio, aspect_ratio, -1.0f, 1.0f); + projection_.CreateOrthoProjection(-aspect_ratio, aspect_ratio, -1.0f, 1.0f); } else { float aspect_ratio = (float)GetScreenHeight() / (float)GetScreenWidth(); LOG << "aspect_ratio: " << aspect_ratio; screen_size_ = {2.0f, aspect_ratio * 2.0f}; - projection_ = base::Ortho(-1.0, 1.0, -aspect_ratio, aspect_ratio); + projection_.CreateOrthoProjection(-1.0, 1.0, -aspect_ratio, aspect_ratio); } LOG << "image scale factor: " << GetImageScaleFactor(); @@ -202,12 +201,12 @@ void Engine::Exit() { platform_->Exit(); } -Vector2 Engine::ToScale(const Vector2& vec) { +Vector2f Engine::ToScale(const Vector2f& vec) { return GetScreenSize() * vec / - Vector2((float)GetScreenWidth(), (float)GetScreenHeight()); + Vector2f((float)GetScreenWidth(), (float)GetScreenHeight()); } -Vector2 Engine::ToPosition(const Vector2& vec) { +Vector2f Engine::ToPosition(const Vector2f& vec) { return ToScale(vec) - GetScreenSize() / 2.0f; } @@ -285,7 +284,7 @@ void Engine::AddInputEvent(std::unique_ptr event) { switch (event->GetType()) { case InputEvent::kDragEnd: - if (((GetScreenSize() / 2) * 0.9f - event->GetVector()).Magnitude() <= + if (((GetScreenSize() / 2) * 0.9f - event->GetVector()).Length() <= 0.25f) { SetSatsVisible(!stats_->IsVisible()); // TODO: Enqueue DragCancel so we can consume this event. @@ -300,7 +299,7 @@ void Engine::AddInputEvent(std::unique_ptr event) { break; case InputEvent::kDrag: if (stats_->IsVisible()) { - if ((stats_->GetPosition() - event->GetVector()).Magnitude() <= + if ((stats_->GetPosition() - event->GetVector()).Length() <= stats_->GetSize().y) stats_->SetPosition(event->GetVector()); // TODO: Enqueue DragCancel so we can consume this event. @@ -323,7 +322,7 @@ std::unique_ptr Engine::GetNextInputEvent() { event = std::make_unique( (InputEvent::Type)data["input_type"].asInt(), (size_t)data["pointer_id"].asUInt(), - Vector2(data["pos_x"].asFloat(), data["pos_y"].asFloat())); + Vector2f(data["pos_x"].asFloat(), data["pos_y"].asFloat())); ++replay_index_; } return event; diff --git a/src/engine/engine.h b/src/engine/engine.h index 63803cd..0b4fa69 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -59,10 +59,10 @@ class Engine { void Exit(); // Convert size from pixels to viewport scale. - base::Vector2 ToScale(const base::Vector2& vec); + base::Vector2f ToScale(const base::Vector2f& vec); // Convert position form pixels to viewport coordinates. - base::Vector2 ToPosition(const base::Vector2& vec); + base::Vector2f ToPosition(const base::Vector2f& vec); template std::unique_ptr CreateRenderResource() { @@ -126,9 +126,9 @@ class Engine { int GetScreenHeight() const; // Return screen size in viewport scale. - base::Vector2 GetScreenSize() const { return screen_size_; } + base::Vector2f GetScreenSize() const { return screen_size_; } - const base::Matrix4x4& GetProjectionMatrix() const { return projection_; } + const base::Matrix4f& GetProjectionMatrix() const { return projection_; } int GetDeviceDpi() const; @@ -175,8 +175,8 @@ class Engine { std::unique_ptr pass_through_shader_; std::unique_ptr solid_shader_; - base::Vector2 screen_size_ = {0, 0}; - base::Matrix4x4 projection_; + base::Vector2f screen_size_ = {0, 0}; + base::Matrix4f projection_; std::unique_ptr system_font_; diff --git a/src/engine/image.cc b/src/engine/image.cc index d50d289..7912057 100644 --- a/src/engine/image.cc +++ b/src/engine/image.cc @@ -312,7 +312,7 @@ uint8_t* Image::GetBuffer() { return buffer_.get(); } -void Image::Clear(Vector4 rgba) { +void Image::Clear(Vector4f rgba) { // Quantize the color to target resolution. uint8_t r = (uint8_t)(rgba.x * 255.0f), g = (uint8_t)(rgba.y * 255.0f), b = (uint8_t)(rgba.z * 255.0f), a = (uint8_t)(rgba.w * 255.0f); @@ -345,10 +345,10 @@ void Image::GradientH() { memcpy(buffer_.get() + h * width_ * 4, buffer_.get(), width_ * 4); } -void Image::GradientV(const Vector4& c1, const Vector4& c2, int height) { +void Image::GradientV(const Vector4f& c1, const Vector4f& c2, int height) { // Fill each section with gradient. for (int h = 0; h < height_; ++h) { - Vector4 c = Lerp(c1, c2, fmod(h, height) / (float)height); + Vector4f c = Lerp(c1, c2, fmod(h, height) / (float)height); for (int x = 0; x < width_; ++x) { buffer_.get()[h * width_ * 4 + x * 4 + 0] = c.x * 255; buffer_.get()[h * width_ * 4 + x * 4 + 1] = c.y * 255; diff --git a/src/engine/image.h b/src/engine/image.h index aa387c4..3eb7f0d 100644 --- a/src/engine/image.h +++ b/src/engine/image.h @@ -41,9 +41,11 @@ class Image { bool IsValid() const { return !!buffer_; } - void Clear(base::Vector4 rgba); + void Clear(base::Vector4f rgba); void GradientH(); - void GradientV(const base::Vector4& c1, const base::Vector4& c2, int height); + void GradientV(const base::Vector4f& c1, + const base::Vector4f& c2, + int height); private: base::AlignedMemPtr buffer_; diff --git a/src/engine/image_quad.cc b/src/engine/image_quad.cc index 17c04a3..760f2b7 100644 --- a/src/engine/image_quad.cc +++ b/src/engine/image_quad.cc @@ -32,8 +32,8 @@ void ImageQuad::Destory() { void ImageQuad::AutoScale() { auto& engine = Engine::Get(); - Vector2 dimensions = {GetFrameWidth(), GetFrameHeight()}; - Vector2 size = engine.ToScale(dimensions); + Vector2f dimensions = {GetFrameWidth(), GetFrameHeight()}; + Vector2f size = engine.ToScale(dimensions); float s = static_cast(engine.image_dpi()) * engine.GetImageScaleFactor(); size *= static_cast(engine.GetDeviceDpi()) / s; @@ -63,8 +63,8 @@ void ImageQuad::Draw(float frame_frac) { texture_->Activate(); - Vector2 tex_scale = {GetFrameWidth() / texture_->GetWidth(), - GetFrameHeight() / texture_->GetHeight()}; + Vector2f tex_scale = {GetFrameWidth() / texture_->GetWidth(), + GetFrameHeight() / texture_->GetHeight()}; Shader* shader = custom_shader_ ? custom_shader_.get() : Engine::Get().GetPassThroughShader(); @@ -100,7 +100,7 @@ float ImageQuad::GetFrameHeight() const { } // Return the uv offset for the given frame. -Vector2 ImageQuad::GetUVOffset(int frame) const { +Vector2f ImageQuad::GetUVOffset(int frame) const { DCHECK(frame < GetNumFrames()) << "asset: " << asset_name_ << " frame: " << frame; return {(float)(frame % num_frames_[0]), (float)(frame / num_frames_[0])}; diff --git a/src/engine/image_quad.h b/src/engine/image_quad.h index ca5f1e3..bc4a879 100644 --- a/src/engine/image_quad.h +++ b/src/engine/image_quad.h @@ -40,17 +40,17 @@ class ImageQuad : public Animatable { void SetFrame(size_t frame) override; size_t GetFrame() const override { return current_frame_; } size_t GetNumFrames() const override; - void SetColor(const base::Vector4& color) override { color_ = color; } - base::Vector4 GetColor() const override { return color_; } + void SetColor(const base::Vector4f& color) override { color_ = color; } + base::Vector4f GetColor() const override { return color_; } // Drawable interface. void Draw(float frame_frac) override; private: - using UniformValue = std::variant; @@ -64,14 +64,14 @@ class ImageQuad : public Animatable { int frame_width_ = 0; int frame_height_ = 0; - base::Vector4 color_ = {1, 1, 1, 1}; + base::Vector4f color_ = {1, 1, 1, 1}; std::string asset_name_; float GetFrameWidth() const; float GetFrameHeight() const; - base::Vector2 GetUVOffset(int frame) const; + base::Vector2f GetUVOffset(int frame) const; }; } // namespace eng diff --git a/src/engine/input_event.h b/src/engine/input_event.h index 8bd267c..0a76caa 100644 --- a/src/engine/input_event.h +++ b/src/engine/input_event.h @@ -21,7 +21,7 @@ class InputEvent { InputEvent(Type type, size_t pointer_id) : type_(type), pointer_id_(pointer_id) {} - InputEvent(Type type, size_t pointer_id, const base::Vector2& vec) + InputEvent(Type type, size_t pointer_id, const base::Vector2f& vec) : type_(type), pointer_id_(pointer_id), vec_(vec) {} InputEvent(Type type) : type_(type) {} InputEvent(Type type, char key) : type_(type), key_(key) {} @@ -31,14 +31,14 @@ class InputEvent { size_t GetPointerId() const { return pointer_id_; } - base::Vector2 GetVector() const { return vec_; } + base::Vector2f GetVector() const { return vec_; } char GetKeyPress() const { return key_; } private: Type type_ = kInvalid; size_t pointer_id_ = 0; - base::Vector2 vec_ = {0, 0}; + base::Vector2f vec_ = {0, 0}; char key_ = 0; }; diff --git a/src/engine/platform/platform_android.cc b/src/engine/platform/platform_android.cc index 50ec498..909d3fe 100644 --- a/src/engine/platform/platform_android.cc +++ b/src/engine/platform/platform_android.cc @@ -232,7 +232,7 @@ int32_t PlatformAndroid::HandleInput(android_app* app, AInputEvent* event) { uint32_t flags = action & AMOTION_EVENT_ACTION_MASK; int32_t count = AMotionEvent_getPointerCount(event); int32_t pointer_id = AMotionEvent_getPointerId(event, index); - Vector2 pos[2] = {platform->pointer_pos_[0], platform->pointer_pos_[1]}; + Vector2f pos[2] = {platform->pointer_pos_[0], platform->pointer_pos_[1]}; for (auto i = 0; i < count; ++i) { int32_t id = AMotionEvent_getPointerId(event, i); pos[id] = {AMotionEvent_getX(event, i), AMotionEvent_getY(event, i)}; @@ -252,7 +252,7 @@ int32_t PlatformAndroid::HandleInput(android_app* app, AInputEvent* event) { platform->pointer_down_[pointer_id] = true; input_event = std::make_unique(InputEvent::kDragStart, pointer_id, - pos[pointer_id] * Vector2(1, -1)); + pos[pointer_id] * Vector2f(1, -1)); break; case AMOTION_EVENT_ACTION_UP: @@ -260,20 +260,21 @@ int32_t PlatformAndroid::HandleInput(android_app* app, AInputEvent* event) { // DLOG << "AMOTION_EVENT_ACTION_UP - pointer_id: " << pointer_id; platform->pointer_pos_[pointer_id] = pos[pointer_id]; platform->pointer_down_[pointer_id] = false; - input_event = std::make_unique( - InputEvent::kDragEnd, pointer_id, pos[pointer_id] * Vector2(1, -1)); + input_event = + std::make_unique(InputEvent::kDragEnd, pointer_id, + pos[pointer_id] * Vector2f(1, -1)); break; case AMOTION_EVENT_ACTION_MOVE: if (platform->pointer_down_[0] && pos[0] != platform->pointer_pos_[0]) { platform->pointer_pos_[0] = pos[0]; input_event = std::make_unique(InputEvent::kDrag, 0, - pos[0] * Vector2(1, -1)); + pos[0] * Vector2f(1, -1)); } if (platform->pointer_down_[1] && pos[1] != platform->pointer_pos_[1]) { platform->pointer_pos_[1] = pos[1]; input_event = std::make_unique(InputEvent::kDrag, 1, - pos[1] * Vector2(1, -1)); + pos[1] * Vector2f(1, -1)); } break; diff --git a/src/engine/platform/platform_android.h b/src/engine/platform/platform_android.h index 2cee0c7..73810ec 100644 --- a/src/engine/platform/platform_android.h +++ b/src/engine/platform/platform_android.h @@ -31,7 +31,7 @@ class PlatformAndroid : public PlatformBase { private: android_app* app_ = nullptr; - base::Vector2 pointer_pos_[2] = {{0, 0}, {0, 0}}; + base::Vector2f pointer_pos_[2] = {{0, 0}, {0, 0}}; bool pointer_down_[2] = {false, false}; static int32_t HandleInput(android_app* app, AInputEvent* event); diff --git a/src/engine/platform/platform_linux.cc b/src/engine/platform/platform_linux.cc index 64e88bf..e24d4a5 100644 --- a/src/engine/platform/platform_linux.cc +++ b/src/engine/platform/platform_linux.cc @@ -66,32 +66,32 @@ void PlatformLinux::Update() { break; } case MotionNotify: { - Vector2 v(e.xmotion.x, e.xmotion.y); + Vector2f v(e.xmotion.x, e.xmotion.y); v = engine_->ToPosition(v); // DLOG << "drag: " << v; auto input_event = std::make_unique(InputEvent::kDrag, 0, - v * Vector2(1, -1)); + v * Vector2f(1, -1)); engine_->AddInputEvent(std::move(input_event)); break; } case ButtonPress: { if (e.xbutton.button == 1) { - Vector2 v(e.xbutton.x, e.xbutton.y); + Vector2f v(e.xbutton.x, e.xbutton.y); v = engine_->ToPosition(v); // DLOG << "drag-start: " << v; auto input_event = std::make_unique( - InputEvent::kDragStart, 0, v * Vector2(1, -1)); + InputEvent::kDragStart, 0, v * Vector2f(1, -1)); engine_->AddInputEvent(std::move(input_event)); } break; } case ButtonRelease: { if (e.xbutton.button == 1) { - Vector2 v(e.xbutton.x, e.xbutton.y); + Vector2f v(e.xbutton.x, e.xbutton.y); v = engine_->ToPosition(v); // DLOG << "drag-end!"; auto input_event = std::make_unique( - InputEvent::kDragEnd, 0, v * Vector2(1, -1)); + InputEvent::kDragEnd, 0, v * Vector2f(1, -1)); engine_->AddInputEvent(std::move(input_event)); } break; diff --git a/src/engine/renderer/opengl/render_command.h b/src/engine/renderer/opengl/render_command.h index 51289be..8ce4941 100644 --- a/src/engine/renderer/opengl/render_command.h +++ b/src/engine/renderer/opengl/render_command.h @@ -92,25 +92,25 @@ RENDER_COMMAND_END RENDER_COMMAND_BEGIN(CmdSetUniformVec2) std::string name; - base::Vector2 v; + base::Vector2f v; std::shared_ptr impl_data; RENDER_COMMAND_END RENDER_COMMAND_BEGIN(CmdSetUniformVec3) std::string name; - base::Vector3 v; + base::Vector3f v; std::shared_ptr impl_data; RENDER_COMMAND_END RENDER_COMMAND_BEGIN(CmdSetUniformVec4) std::string name; - base::Vector4 v; + base::Vector4f v; std::shared_ptr impl_data; RENDER_COMMAND_END RENDER_COMMAND_BEGIN(CmdSetUniformMat4) std::string name; - base::Matrix4x4 m; + base::Matrix4f m; std::shared_ptr impl_data; RENDER_COMMAND_END diff --git a/src/engine/renderer/opengl/renderer_opengl.cc b/src/engine/renderer/opengl/renderer_opengl.cc index 8564092..3f5b447 100644 --- a/src/engine/renderer/opengl/renderer_opengl.cc +++ b/src/engine/renderer/opengl/renderer_opengl.cc @@ -110,7 +110,7 @@ void RendererOpenGL::ActivateShader(std::shared_ptr impl_data) { void RendererOpenGL::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector2& val) { + const base::Vector2f& val) { auto cmd = std::make_unique(); cmd->name = name; cmd->v = val; @@ -120,7 +120,7 @@ void RendererOpenGL::SetUniform(std::shared_ptr impl_data, void RendererOpenGL::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector3& val) { + const base::Vector3f& val) { auto cmd = std::make_unique(); cmd->name = name; cmd->v = val; @@ -130,7 +130,7 @@ void RendererOpenGL::SetUniform(std::shared_ptr impl_data, void RendererOpenGL::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector4& val) { + const base::Vector4f& val) { auto cmd = std::make_unique(); cmd->name = name; cmd->v = val; @@ -140,7 +140,7 @@ void RendererOpenGL::SetUniform(std::shared_ptr impl_data, void RendererOpenGL::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Matrix4x4& val) { + const base::Matrix4f& val) { auto cmd = std::make_unique(); cmd->name = name; cmd->m = val; diff --git a/src/engine/renderer/opengl/renderer_opengl.h b/src/engine/renderer/opengl/renderer_opengl.h index 0394199..178da4a 100644 --- a/src/engine/renderer/opengl/renderer_opengl.h +++ b/src/engine/renderer/opengl/renderer_opengl.h @@ -69,16 +69,16 @@ class RendererOpenGL : public Renderer { void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector2& val) override; + const base::Vector2f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector3& val) override; + const base::Vector3f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector4& val) override; + const base::Vector4f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Matrix4x4& val) override; + const base::Matrix4f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, float val) override; diff --git a/src/engine/renderer/renderer.h b/src/engine/renderer/renderer.h index 877fe63..890bec8 100644 --- a/src/engine/renderer/renderer.h +++ b/src/engine/renderer/renderer.h @@ -59,16 +59,16 @@ class Renderer { virtual void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector2& val) = 0; + const base::Vector2f& val) = 0; virtual void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector3& val) = 0; + const base::Vector3f& val) = 0; virtual void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector4& val) = 0; + const base::Vector4f& val) = 0; virtual void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Matrix4x4& val) = 0; + const base::Matrix4f& val) = 0; virtual void SetUniform(std::shared_ptr impl_data, const std::string& name, float val) = 0; diff --git a/src/engine/renderer/shader.cc b/src/engine/renderer/shader.cc index 7c8980d..04c4308 100644 --- a/src/engine/renderer/shader.cc +++ b/src/engine/renderer/shader.cc @@ -36,22 +36,22 @@ void Shader::Activate() { renderer_->ActivateShader(impl_data_); } -void Shader::SetUniform(const std::string& name, const Vector2& v) { +void Shader::SetUniform(const std::string& name, const Vector2f& v) { if (valid_) renderer_->SetUniform(impl_data_, name, v); } -void Shader::SetUniform(const std::string& name, const Vector3& v) { +void Shader::SetUniform(const std::string& name, const Vector3f& v) { if (valid_) renderer_->SetUniform(impl_data_, name, v); } -void Shader::SetUniform(const std::string& name, const Vector4& v) { +void Shader::SetUniform(const std::string& name, const Vector4f& v) { if (valid_) renderer_->SetUniform(impl_data_, name, v); } -void Shader::SetUniform(const std::string& name, const Matrix4x4& m) { +void Shader::SetUniform(const std::string& name, const Matrix4f& m) { if (valid_) renderer_->SetUniform(impl_data_, name, m); } diff --git a/src/engine/renderer/shader.h b/src/engine/renderer/shader.h index f4c6fe3..6429b53 100644 --- a/src/engine/renderer/shader.h +++ b/src/engine/renderer/shader.h @@ -28,10 +28,10 @@ class Shader : public RenderResource { void Activate(); - void SetUniform(const std::string& name, const base::Vector2& v); - void SetUniform(const std::string& name, const base::Vector3& v); - void SetUniform(const std::string& name, const base::Vector4& v); - void SetUniform(const std::string& name, const base::Matrix4x4& m); + void SetUniform(const std::string& name, const base::Vector2f& v); + void SetUniform(const std::string& name, const base::Vector3f& v); + void SetUniform(const std::string& name, const base::Vector4f& v); + void SetUniform(const std::string& name, const base::Matrix4f& m); void SetUniform(const std::string& name, float f); void SetUniform(const std::string& name, int i); diff --git a/src/engine/renderer/vulkan/renderer_vulkan.cc b/src/engine/renderer/vulkan/renderer_vulkan.cc index ecdce95..87997e4 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.cc +++ b/src/engine/renderer/vulkan/renderer_vulkan.cc @@ -597,28 +597,28 @@ void RendererVulkan::ActivateShader(std::shared_ptr impl_data) { void RendererVulkan::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector2& val) { + const base::Vector2f& val) { auto shader = reinterpret_cast(impl_data.get()); SetUniformInternal(shader, name, val); } void RendererVulkan::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector3& val) { + const base::Vector3f& val) { auto shader = reinterpret_cast(impl_data.get()); SetUniformInternal(shader, name, val); } void RendererVulkan::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector4& val) { + const base::Vector4f& val) { auto shader = reinterpret_cast(impl_data.get()); SetUniformInternal(shader, name, val); } void RendererVulkan::SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Matrix4x4& val) { + const base::Matrix4f& val) { auto shader = reinterpret_cast(impl_data.get()); SetUniformInternal(shader, name, val); } diff --git a/src/engine/renderer/vulkan/renderer_vulkan.h b/src/engine/renderer/vulkan/renderer_vulkan.h index 1fa4ad1..5b6c684 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.h +++ b/src/engine/renderer/vulkan/renderer_vulkan.h @@ -52,16 +52,16 @@ class RendererVulkan : public Renderer { void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector2& val) override; + const base::Vector2f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector3& val) override; + const base::Vector3f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Vector4& val) override; + const base::Vector4f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, - const base::Matrix4x4& val) override; + const base::Matrix4f& val) override; void SetUniform(std::shared_ptr impl_data, const std::string& name, float val) override; diff --git a/src/engine/solid_quad.h b/src/engine/solid_quad.h index f489abf..76235bc 100644 --- a/src/engine/solid_quad.h +++ b/src/engine/solid_quad.h @@ -14,14 +14,14 @@ class SolidQuad : public Animatable { void SetFrame(size_t frame) override {} size_t GetFrame() const override { return 0; } size_t GetNumFrames() const override { return 0; } - void SetColor(const base::Vector4& color) override { color_ = color; } - base::Vector4 GetColor() const override { return color_; } + void SetColor(const base::Vector4f& color) override { color_ = color; } + base::Vector4f GetColor() const override { return color_; } // Drawable interface. void Draw(float frame_frac) override; private: - base::Vector4 color_ = {1, 1, 1, 1}; + base::Vector4f color_ = {1, 1, 1, 1}; }; } // namespace eng