#pragma once #include "diffvg.h" #include "vector.h" #include template struct TMatrix3x3 { DEVICE TMatrix3x3() { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { data[i][j] = T(0); } } } template DEVICE TMatrix3x3(T2 *arr) { data[0][0] = arr[0]; data[0][1] = arr[1]; data[0][2] = arr[2]; data[1][0] = arr[3]; data[1][1] = arr[4]; data[1][2] = arr[5]; data[2][0] = arr[6]; data[2][1] = arr[7]; data[2][2] = arr[8]; } DEVICE TMatrix3x3(T v00, T v01, T v02, T v10, T v11, T v12, T v20, T v21, T v22) { data[0][0] = v00; data[0][1] = v01; data[0][2] = v02; data[1][0] = v10; data[1][1] = v11; data[1][2] = v12; data[2][0] = v20; data[2][1] = v21; data[2][2] = v22; } DEVICE const T& operator()(int i, int j) const { return data[i][j]; } DEVICE T& operator()(int i, int j) { return data[i][j]; } DEVICE static TMatrix3x3 identity() { TMatrix3x3 m(1, 0, 0, 0, 1, 0, 0, 0, 1); return m; } T data[3][3]; }; using Matrix3x3 = TMatrix3x3; using Matrix3x3f = TMatrix3x3; template struct TMatrix4x4 { DEVICE TMatrix4x4() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { data[i][j] = T(0); } } } template DEVICE TMatrix4x4(const T2 *arr) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { data[i][j] = (T)arr[i * 4 + j]; } } } template DEVICE TMatrix4x4(const TMatrix4x4 &m) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { data[i][j] = T(m.data[i][j]); } } } template DEVICE TMatrix4x4(T2 v00, T2 v01, T2 v02, T2 v03, T2 v10, T2 v11, T2 v12, T2 v13, T2 v20, T2 v21, T2 v22, T2 v23, T2 v30, T2 v31, T2 v32, T2 v33) { data[0][0] = (T)v00; data[0][1] = (T)v01; data[0][2] = (T)v02; data[0][3] = (T)v03; data[1][0] = (T)v10; data[1][1] = (T)v11; data[1][2] = (T)v12; data[1][3] = (T)v13; data[2][0] = (T)v20; data[2][1] = (T)v21; data[2][2] = (T)v22; data[2][3] = (T)v23; data[3][0] = (T)v30; data[3][1] = (T)v31; data[3][2] = (T)v32; data[3][3] = (T)v33; } DEVICE const T& operator()(int i, int j) const { return data[i][j]; } DEVICE T& operator()(int i, int j) { return data[i][j]; } DEVICE static TMatrix4x4 identity() { TMatrix4x4 m(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); return m; } T data[4][4]; }; using Matrix4x4 = TMatrix4x4; using Matrix4x4f = TMatrix4x4; template DEVICE inline auto operator+(const TMatrix3x3 &m0, const TMatrix3x3 &m1) -> TMatrix3x3 { TMatrix3x3 m; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { m(i, j) = m0(i, j) + m1(i, j); } } return m; } template DEVICE inline auto operator-(const TMatrix3x3 &m0, const TMatrix3x3 &m1) -> TMatrix3x3 { TMatrix3x3 m; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { m(i, j) = m0(i, j) - m1(i, j); } } return m; } template DEVICE inline auto operator*(const TMatrix3x3 &m0, const TMatrix3x3 &m1) -> TMatrix3x3 { TMatrix3x3 ret; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { ret(i, j) = T(0); for (int k = 0; k < 3; k++) { ret(i, j) += m0(i, k) * m1(k, j); } } } return ret; } template DEVICE inline auto operator*(const TVector3 &v, const TMatrix3x3 &m) -> TVector3 { TVector3 ret; for (int i = 0; i < 3; i++) { ret[i] = T(0); for (int j = 0; j < 3; j++) { ret[i] += v[j] * m(j, i); } } return ret; } template DEVICE inline auto operator*(const TMatrix3x3 &m, const TVector3 &v) -> TVector3 { TVector3 ret; for (int i = 0; i < 3; i++) { ret[i] = 0.f; for (int j = 0; j < 3; j++) { ret[i] += m(i, j) * v[j]; } } return ret; } template DEVICE inline auto inverse(const TMatrix3x3 &m) -> TMatrix3x3 { // computes the inverse of a matrix m auto det = m(0, 0) * (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) - m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) + m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)); auto invdet = 1 / det; auto m_inv = TMatrix3x3{}; m_inv(0, 0) = (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) * invdet; m_inv(0, 1) = (m(0, 2) * m(2, 1) - m(0, 1) * m(2, 2)) * invdet; m_inv(0, 2) = (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * invdet; m_inv(1, 0) = (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) * invdet; m_inv(1, 1) = (m(0, 0) * m(2, 2) - m(0, 2) * m(2, 0)) * invdet; m_inv(1, 2) = (m(1, 0) * m(0, 2) - m(0, 0) * m(1, 2)) * invdet; m_inv(2, 0) = (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1)) * invdet; m_inv(2, 1) = (m(2, 0) * m(0, 1) - m(0, 0) * m(2, 1)) * invdet; m_inv(2, 2) = (m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1)) * invdet; return m_inv; } template DEVICE inline auto operator+(const TMatrix4x4 &m0, const TMatrix4x4 &m1) -> TMatrix4x4 { TMatrix4x4 m; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m(i, j) = m0(i, j) + m1(i, j); } } return m; } template DEVICE TMatrix3x3 transpose(const TMatrix3x3 &m) { return TMatrix3x3(m(0, 0), m(1, 0), m(2, 0), m(0, 1), m(1, 1), m(2, 1), m(0, 2), m(1, 2), m(2, 2)); } template DEVICE TMatrix4x4 transpose(const TMatrix4x4 &m) { return TMatrix4x4(m(0, 0), m(1, 0), m(2, 0), m(3, 0), m(0, 1), m(1, 1), m(2, 1), m(3, 1), m(0, 2), m(1, 2), m(2, 2), m(3, 2), m(0, 3), m(1, 3), m(2, 3), m(3, 3)); } template DEVICE inline TMatrix3x3 operator-(const TMatrix3x3 &m0) { TMatrix3x3 m; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { m(i, j) = -m0(i, j); } } return m; } template DEVICE inline TMatrix4x4 operator-(const TMatrix4x4 &m0) { TMatrix4x4 m; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m(i, j) = -m0(i, j); } } return m; } template DEVICE inline TMatrix4x4 operator-(const TMatrix4x4 &m0, const TMatrix4x4 &m1) { TMatrix4x4 m; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m(i, j) = m0(i, j) - m1(i, j); } } return m; } template DEVICE inline TMatrix3x3& operator+=(TMatrix3x3 &m0, const TMatrix3x3 &m1) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { m0(i, j) += m1(i, j); } } return m0; } template DEVICE inline TMatrix4x4& operator+=(TMatrix4x4 &m0, const TMatrix4x4 &m1) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m0(i, j) += m1(i, j); } } return m0; } template DEVICE inline TMatrix4x4& operator-=(TMatrix4x4 &m0, const TMatrix4x4 &m1) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m0(i, j) -= m1(i, j); } } return m0; } template DEVICE inline TMatrix4x4 operator*(const TMatrix4x4 &m0, const TMatrix4x4 &m1) { TMatrix4x4 m; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { m(i, j) += m0(i, k) * m1(k, j); } } } return m; } template DEVICE TMatrix4x4 inverse(const TMatrix4x4 &m) { // https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix TMatrix4x4 inv; inv(0, 0) = m(1, 1) * m(2, 2) * m(3, 3) - m(1, 1) * m(2, 3) * m(3, 2) - m(2, 1) * m(1, 2) * m(3, 3) + m(2, 1) * m(1, 3) * m(3, 2) + m(3, 1) * m(1, 2) * m(2, 3) - m(3, 1) * m(1, 3) * m(2, 2); inv(1, 0) = -m(1, 0) * m(2, 2) * m(3, 3) + m(1, 0) * m(2, 3) * m(3, 2) + m(2, 0) * m(1, 2) * m(3, 3) - m(2, 0) * m(1, 3) * m(3, 2) - m(3, 0) * m(1, 2) * m(2, 3) + m(3, 0) * m(1, 3) * m(2, 2); inv(2, 0) = m(1, 0) * m(2, 1) * m(3, 3) - m(1, 0) * m(2, 3) * m(3, 1) - m(2, 0) * m(1, 1) * m(3, 3) + m(2, 0) * m(1, 3) * m(3, 1) + m(3, 0) * m(1, 1) * m(2, 3) - m(3, 0) * m(1, 3) * m(2, 1); inv(3, 0) = -m(1, 0) * m(2, 1) * m(3, 2) + m(1, 0) * m(2, 2) * m(3, 1) + m(2, 0) * m(1, 1) * m(3, 2) - m(2, 0) * m(1, 2) * m(3, 1) - m(3, 0) * m(1, 1) * m(2, 2) + m(3, 0) * m(1, 2) * m(2, 1); inv(0, 1) = -m(0, 1) * m(2, 2) * m(3, 3) + m(0, 1) * m(2, 3) * m(3, 2) + m(2, 1) * m(0, 2) * m(3, 3) - m(2, 1) * m(0, 3) * m(3, 2) - m(3, 1) * m(0, 2) * m(2, 3) + m(3, 1) * m(0, 3) * m(2, 2); inv(1, 1) = m(0, 0) * m(2, 2) * m(3, 3) - m(0, 0) * m(2, 3) * m(3, 2) - m(2, 0) * m(0, 2) * m(3, 3) + m(2, 0) * m(0, 3) * m(3, 2) + m(3, 0) * m(0, 2) * m(2, 3) - m(3, 0) * m(0, 3) * m(2, 2); inv(2, 1) = -m(0, 0) * m(2, 1) * m(3, 3) + m(0, 0) * m(2, 3) * m(3, 1) + m(2, 0) * m(0, 1) * m(3, 3) - m(2, 0) * m(0, 3) * m(3, 1) - m(3, 0) * m(0, 1) * m(2, 3) + m(3, 0) * m(0, 3) * m(2, 1); inv(3, 1) = m(0, 0) * m(2, 1) * m(3, 2) - m(0, 0) * m(2, 2) * m(3, 1) - m(2, 0) * m(0, 1) * m(3, 2) + m(2, 0) * m(0, 2) * m(3, 1) + m(3, 0) * m(0, 1) * m(2, 2) - m(3, 0) * m(0, 2) * m(2, 1); inv(0, 2) = m(0, 1) * m(1, 2) * m(3, 3) - m(0, 1) * m(1, 3) * m(3, 2) - m(1, 1) * m(0, 2) * m(3, 3) + m(1, 1) * m(0, 3) * m(3, 2) + m(3, 1) * m(0, 2) * m(1, 3) - m(3, 1) * m(0, 3) * m(1, 2); inv(1, 2) = -m(0, 0) * m(1, 2) * m(3, 3) + m(0, 0) * m(1, 3) * m(3, 2) + m(1, 0) * m(0, 2) * m(3, 3) - m(1, 0) * m(0, 3) * m(3, 2) - m(3, 0) * m(0, 2) * m(1, 3) + m(3, 0) * m(0, 3) * m(1, 2); inv(2, 2) = m(0, 0) * m(1, 1) * m(3, 3) - m(0, 0) * m(1, 3) * m(3, 1) - m(1, 0) * m(0, 1) * m(3, 3) + m(1, 0) * m(0, 3) * m(3, 1) + m(3, 0) * m(0, 1) * m(1, 3) - m(3, 0) * m(0, 3) * m(1, 1); inv(3, 2) = -m(0, 0) * m(1, 1) * m(3, 2) + m(0, 0) * m(1, 2) * m(3, 1) + m(1, 0) * m(0, 1) * m(3, 2) - m(1, 0) * m(0, 2) * m(3, 1) - m(3, 0) * m(0, 1) * m(1, 2) + m(3, 0) * m(0, 2) * m(1, 1); inv(0, 3) = -m(0, 1) * m(1, 2) * m(2, 3) + m(0, 1) * m(1, 3) * m(2, 2) + m(1, 1) * m(0, 2) * m(2, 3) - m(1, 1) * m(0, 3) * m(2, 2) - m(2, 1) * m(0, 2) * m(1, 3) + m(2, 1) * m(0, 3) * m(1, 2); inv(1, 3) = m(0, 0) * m(1, 2) * m(2, 3) - m(0, 0) * m(1, 3) * m(2, 2) - m(1, 0) * m(0, 2) * m(2, 3) + m(1, 0) * m(0, 3) * m(2, 2) + m(2, 0) * m(0, 2) * m(1, 3) - m(2, 0) * m(0, 3) * m(1, 2); inv(2, 3) = -m(0, 0) * m(1, 1) * m(2, 3) + m(0, 0) * m(1, 3) * m(2, 1) + m(1, 0) * m(0, 1) * m(2, 3) - m(1, 0) * m(0, 3) * m(2, 1) - m(2, 0) * m(0, 1) * m(1, 3) + m(2, 0) * m(0, 3) * m(1, 1); inv(3, 3) = m(0, 0) * m(1, 1) * m(2, 2) - m(0, 0) * m(1, 2) * m(2, 1) - m(1, 0) * m(0, 1) * m(2, 2) + m(1, 0) * m(0, 2) * m(2, 1) + m(2, 0) * m(0, 1) * m(1, 2) - m(2, 0) * m(0, 2) * m(1, 1); auto det = m(0, 0) * inv(0, 0) + m(0, 1) * inv(1, 0) + m(0, 2) * inv(2, 0) + m(0, 3) * inv(3, 0); if (det == 0) { return TMatrix4x4{}; } auto inv_det = 1.0 / det; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { inv(i, j) *= inv_det; } } return inv; } template inline std::ostream& operator<<(std::ostream &os, const TMatrix3x3 &m) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { os << m(i, j) << " "; } os << std::endl; } return os; } template inline std::ostream& operator<<(std::ostream &os, const TMatrix4x4 &m) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { os << m(i, j) << " "; } os << std::endl; } return os; } template DEVICE TVector2 xform_pt(const TMatrix3x3 &m, const TVector2 &pt) { TVector3 t{m(0, 0) * pt[0] + m(0, 1) * pt[1] + m(0, 2), m(1, 0) * pt[0] + m(1, 1) * pt[1] + m(1, 2), m(2, 0) * pt[0] + m(2, 1) * pt[1] + m(2, 2)}; return TVector2{t[0] / t[2], t[1] / t[2]}; } template DEVICE void d_xform_pt(const TMatrix3x3 &m, const TVector2 &pt, const TVector2 &d_out, TMatrix3x3 &d_m, TVector2 &d_pt) { TVector3 t{m(0, 0) * pt[0] + m(0, 1) * pt[1] + m(0, 2), m(1, 0) * pt[0] + m(1, 1) * pt[1] + m(1, 2), m(2, 0) * pt[0] + m(2, 1) * pt[1] + m(2, 2)}; auto out = TVector2{t[0] / t[2], t[1] / t[2]}; TVector3 d_t{d_out[0] / t[2], d_out[1] / t[2], -(d_out[0] * out[0] + d_out[1] * out[1]) / t[2]}; d_m(0, 0) += d_t[0] * pt[0]; d_m(0, 1) += d_t[0] * pt[1]; d_m(0, 2) += d_t[0]; d_m(1, 0) += d_t[1] * pt[0]; d_m(1, 1) += d_t[1] * pt[1]; d_m(1, 2) += d_t[1]; d_m(2, 0) += d_t[2] * pt[0]; d_m(2, 1) += d_t[2] * pt[1]; d_m(2, 2) += d_t[2]; d_pt[0] += d_t[0] * m(0, 0) + d_t[1] * m(1, 0) + d_t[2] * m(2, 0); d_pt[1] += d_t[0] * m(0, 1) + d_t[1] * m(1, 1) + d_t[2] * m(2, 1); } template DEVICE TVector2 xform_normal(const TMatrix3x3 &m_inv, const TVector2 &n) { return normalize(TVector2{m_inv(0, 0) * n[0] + m_inv(1, 0) * n[1], m_inv(0, 1) * n[0] + m_inv(1, 1) * n[1]}); }