LIVE / matrix.h
Xu Ma
update
1c3c0d9
raw
history blame
16 kB
#pragma once
#include "diffvg.h"
#include "vector.h"
#include <iostream>
template <typename T>
struct TMatrix3x3 {
DEVICE
TMatrix3x3() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
data[i][j] = T(0);
}
}
}
template <typename T2>
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<T> identity() {
TMatrix3x3<T> m(1, 0, 0,
0, 1, 0,
0, 0, 1);
return m;
}
T data[3][3];
};
using Matrix3x3 = TMatrix3x3<Real>;
using Matrix3x3f = TMatrix3x3<float>;
template <typename T>
struct TMatrix4x4 {
DEVICE TMatrix4x4() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
data[i][j] = T(0);
}
}
}
template <typename T2>
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 <typename T2>
DEVICE TMatrix4x4(const TMatrix4x4<T2> &m) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
data[i][j] = T(m.data[i][j]);
}
}
}
template <typename T2>
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<T> identity() {
TMatrix4x4<T> 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<Real>;
using Matrix4x4f = TMatrix4x4<float>;
template <typename T0, typename T1>
DEVICE
inline auto operator+(const TMatrix3x3<T0> &m0, const TMatrix3x3<T1> &m1) -> TMatrix3x3<decltype(m0(0, 0) + m1(0, 0))> {
TMatrix3x3<decltype(m0(0, 0) + m1(0, 0))> 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 <typename T0, typename T1>
DEVICE
inline auto operator-(const TMatrix3x3<T0> &m0, const TMatrix3x3<T1> &m1) -> TMatrix3x3<decltype(m0(0, 0) - m1(0, 0))> {
TMatrix3x3<decltype(m0(0, 0) - m1(0, 0))> 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 <typename T>
DEVICE
inline auto operator*(const TMatrix3x3<T> &m0, const TMatrix3x3<T> &m1) -> TMatrix3x3<T> {
TMatrix3x3<T> 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 <typename T>
DEVICE
inline auto operator*(const TVector3<T> &v, const TMatrix3x3<T> &m) -> TVector3<T> {
TVector3<T> 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 <typename T>
DEVICE
inline auto operator*(const TMatrix3x3<T> &m, const TVector3<T> &v) -> TVector3<T> {
TVector3<T> 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 <typename T>
DEVICE
inline auto inverse(const TMatrix3x3<T> &m) -> TMatrix3x3<T> {
// 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<T>{};
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 <typename T0, typename T1>
DEVICE
inline auto operator+(const TMatrix4x4<T0> &m0, const TMatrix4x4<T1> &m1) -> TMatrix4x4<decltype(m0(0, 0) + m1(0, 0))> {
TMatrix4x4<decltype(m0(0, 0) + m1(0, 0))> 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 <typename T>
DEVICE
TMatrix3x3<T> transpose(const TMatrix3x3<T> &m) {
return TMatrix3x3<T>(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 <typename T>
DEVICE
TMatrix4x4<T> transpose(const TMatrix4x4<T> &m) {
return TMatrix4x4<T>(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 <typename T>
DEVICE
inline TMatrix3x3<T> operator-(const TMatrix3x3<T> &m0) {
TMatrix3x3<T> m;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
m(i, j) = -m0(i, j);
}
}
return m;
}
template <typename T>
DEVICE
inline TMatrix4x4<T> operator-(const TMatrix4x4<T> &m0) {
TMatrix4x4<T> m;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
m(i, j) = -m0(i, j);
}
}
return m;
}
template <typename T>
DEVICE
inline TMatrix4x4<T> operator-(const TMatrix4x4<T> &m0, const TMatrix4x4<T> &m1) {
TMatrix4x4<T> 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 <typename T>
DEVICE
inline TMatrix3x3<T>& operator+=(TMatrix3x3<T> &m0, const TMatrix3x3<T> &m1) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
m0(i, j) += m1(i, j);
}
}
return m0;
}
template <typename T>
DEVICE
inline TMatrix4x4<T>& operator+=(TMatrix4x4<T> &m0, const TMatrix4x4<T> &m1) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
m0(i, j) += m1(i, j);
}
}
return m0;
}
template <typename T>
DEVICE
inline TMatrix4x4<T>& operator-=(TMatrix4x4<T> &m0, const TMatrix4x4<T> &m1) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
m0(i, j) -= m1(i, j);
}
}
return m0;
}
template <typename T>
DEVICE
inline TMatrix4x4<T> operator*(const TMatrix4x4<T> &m0, const TMatrix4x4<T> &m1) {
TMatrix4x4<T> 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 <typename T>
DEVICE
TMatrix4x4<T> inverse(const TMatrix4x4<T> &m) {
// https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
TMatrix4x4<T> 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<T>{};
}
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 <typename T>
inline std::ostream& operator<<(std::ostream &os, const TMatrix3x3<T> &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 <typename T>
inline std::ostream& operator<<(std::ostream &os, const TMatrix4x4<T> &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 <typename T>
DEVICE
TVector2<T> xform_pt(const TMatrix3x3<T> &m, const TVector2<T> &pt) {
TVector3<T> 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>{t[0] / t[2], t[1] / t[2]};
}
template <typename T>
DEVICE
void d_xform_pt(const TMatrix3x3<T> &m, const TVector2<T> &pt,
const TVector2<T> &d_out,
TMatrix3x3<T> &d_m,
TVector2<T> &d_pt) {
TVector3<T> 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>{t[0] / t[2], t[1] / t[2]};
TVector3<T> 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 <typename T>
DEVICE
TVector2<T> xform_normal(const TMatrix3x3<T> &m_inv, const TVector2<T> &n) {
return normalize(TVector2<T>{m_inv(0, 0) * n[0] + m_inv(1, 0) * n[1],
m_inv(0, 1) * n[0] + m_inv(1, 1) * n[1]});
}