Newer
Older
// Constructor
Mat4::Mat4(std::array<float, 16> arr) : arr(arr){};
Mat4::Mat4() : arr(identity().arr){};
// Operator
float Mat4::operator[](std::array<int, 2> i) const {
return arr[4 * i[0] + i[1]];
float& Mat4::operator[](std::array<int, 2> i) {
return arr[4 * i[0] + i[1]];
Mat4 Mat4::operator*(const Mat4& rhs) const {
Mat4 n;
for (int c = 0; c != 4; c++) {
for (int r = 0; r != 4; r++) {
float v = 0;
for (int k = 0; k != 4; k++) v += arr[4 * k + r] * rhs[{c, k}];
n[{c, r}] = v;
}
}
return n;
bool Mat4::operator==(const Mat4& rhs) const {
return arr == rhs.arr;
bool Mat4::operator!=(const Mat4& rhs) const {
return !(*this == rhs);
// Methods
Mat4 Mat4::transpose() const {
Mat4 x;
for (int c = 0; c != 4; c++) {
for (int r = 0; r != 4; r++) {
x[{c, r}] = arr[4 * r + c];
}
}
return x;
Vec3 Mat4::transformDir(Vec3 v) const {
Mat4 mat(*this);
const float x =
mat[{0, 0}] * v[0] + mat[{0, 1}] * v[1] + mat[{0, 2}] * v[2];
const float y =
mat[{1, 0}] * v[0] + mat[{1, 1}] * v[1] + mat[{1, 2}] * v[2];
const float z =
mat[{2, 0}] * v[0] + mat[{2, 1}] * v[1] + mat[{2, 2}] * v[2];
return Vec3(x, y, z);
Vec3 Mat4::transformPoint(Vec3 v) const {
Mat4 mat(*this);
float x = mat[{0, 0}] * v[0] + mat[{0, 1}] * v[1] + mat[{0, 2}] * v[2] +
mat[{0, 3}];
float y = mat[{1, 0}] * v[0] + mat[{1, 1}] * v[1] + mat[{1, 2}] * v[2] +
mat[{1, 3}];
float z = mat[{2, 0}] * v[0] + mat[{2, 1}] * v[1] + mat[{2, 2}] * v[2] +
mat[{2, 3}];
return Vec3(x, y, z);
Vec3 Mat4::position() const {
Mat4 mat(*this);
return Vec3(mat[{0, 3}], mat[{1, 3}], mat[{2, 3}]);
Mat4 Mat4::invertFull() const {
Mat4 ret;
std::array<float, 16> mat(arr);
std::array<float, 16> dst(ret.arr);
std::array<float, 12> tmp;
/* determinant */
/*
* transpose matrix
*/
for (int i = 0; i < 4; i++) {
src[i] = mat[i * 4];
src[i + 4] = mat[i * 4 + 1];
src[i + 8] = mat[i * 4 + 2];
src[i + 12] = mat[i * 4 + 3];
}
/* calculate pairs for first 8 elements (cofactors) */
tmp[0] = src[10] * src[15];
tmp[1] = src[11] * src[14];
tmp[2] = src[9] * src[15];
tmp[3] = src[11] * src[13];
tmp[4] = src[9] * src[14];
tmp[5] = src[10] * src[13];
tmp[6] = src[8] * src[15];
tmp[7] = src[11] * src[12];
tmp[8] = src[8] * src[14];
tmp[9] = src[10] * src[12];
tmp[10] = src[8] * src[13];
tmp[11] = src[9] * src[12];
/* calculate first 8 elements (cofactors) */
dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7];
dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7];
dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7];
dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7];
dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7];
dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7];
dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6];
dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6];
dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3];
dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3];
dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3];
dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3];
dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3];
dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3];
dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2];
dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2];
/* calculate pairs for second 8 elements (cofactors) */
tmp[0] = src[2] * src[7];
tmp[1] = src[3] * src[6];
tmp[2] = src[1] * src[7];
tmp[3] = src[3] * src[5];
tmp[4] = src[1] * src[6];
tmp[5] = src[2] * src[5];
tmp[6] = src[0] * src[7];
tmp[7] = src[3] * src[4];
tmp[8] = src[0] * src[6];
tmp[9] = src[2] * src[4];
tmp[10] = src[0] * src[5];
tmp[11] = src[1] * src[4];
/* calculate second 8 elements (cofactors) */
dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15];
dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15];
dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15];
dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15];
dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15];
dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15];
dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14];
dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14];
dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9];
dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10];
dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10];
dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8];
dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8];
dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9];
dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9];
dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8];
/* calculate determinant */
det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3];
// Static
Mat4 translate(Vec3 xyz) {
Mat4 matrix;
matrix[{0, 3}] = xyz[0];
matrix[{1, 3}] = xyz[1];
matrix[{2, 3}] = xyz[2];
return matrix;
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
Mat4 rotate(Vec3 axis, float angle) {
Mat4 matrix;
float rad = (angle / 180) * M_PI;
float cosa = cos(rad);
float sina = sin(rad);
float l = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
float rx = axis[0] / l;
float ry = axis[1] / l;
float rz = axis[2] / l;
float icosa = 1 - cosa;
{
matrix[{0, 0}] = (icosa * rx * rx + cosa);
matrix[{1, 0}] = (icosa * rx * ry + rz * sina);
matrix[{2, 0}] = (icosa * rx * rz - ry * sina);
}
{
matrix[{0, 1}] = (icosa * rx * ry - rz * sina);
matrix[{1, 1}] = (icosa * ry * ry + cosa);
matrix[{2, 1}] = (icosa * ry * rz + rx * sina);
}
{
matrix[{0, 2}] = (icosa * rx * rz + ry * sina);
matrix[{1, 2}] = (icosa * ry * rz - rx * sina);
matrix[{2, 2}] = (icosa * rz * rz + cosa);
}
return matrix;
Mat4 scale(Vec3 xyz) {
Mat4 matrix;
matrix[{0, 0}] = xyz[0];
matrix[{1, 1}] = xyz[1];
matrix[{2, 2}] = xyz[2];
return matrix;
Mat4 identity() {
return Mat4({1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1});
// Out
std::ostream& operator<<(std::ostream& os, const Mat4& rhs) {
for (int c = 0; c < 4; c++) {
os << "(";
for (int r = 0; r < 4; r++) {
os << rhs[{c, r}];
if (r != 3) {
os << ",";
}
}
os << ")" << std::endl;
}
return os;