// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "Matrix.hpp"
#include "Point.hpp"
#include "System/Math.hpp"
namespace sw
{
Matrix Matrix::diag(float m11, float m22, float m33, float m44)
{
return Matrix(m11, 0, 0, 0,
0, m22, 0, 0,
0, 0, m33, 0,
0, 0, 0, m44);
}
Matrix::operator float*()
{
return &(*this)(1, 1);
}
Matrix Matrix::operator+() const
{
return *this;
}
Matrix Matrix::operator-() const
{
const Matrix &M = *this;
return Matrix(-M(1, 1), -M(1, 2), -M(1, 3), -M(1, 4),
-M(2, 1), -M(2, 2), -M(2, 3), -M(2, 4),
-M(3, 1), -M(3, 2), -M(3, 3), -M(3, 4),
-M(4, 1), -M(4, 2), -M(4, 3), -M(4, 4));
}
Matrix Matrix::operator!() const
{
const Matrix &M = *this;
Matrix I;
float M3344 = M(3, 3) * M(4, 4) - M(4, 3) * M(3, 4);
float M2344 = M(2, 3) * M(4, 4) - M(4, 3) * M(2, 4);
float M2334 = M(2, 3) * M(3, 4) - M(3, 3) * M(2, 4);
float M3244 = M(3, 2) * M(4, 4) - M(4, 2) * M(3, 4);
float M2244 = M(2, 2) * M(4, 4) - M(4, 2) * M(2, 4);
float M2234 = M(2, 2) * M(3, 4) - M(3, 2) * M(2, 4);
float M3243 = M(3, 2) * M(4, 3) - M(4, 2) * M(3, 3);
float M2243 = M(2, 2) * M(4, 3) - M(4, 2) * M(2, 3);
float M2233 = M(2, 2) * M(3, 3) - M(3, 2) * M(2, 3);
float M1344 = M(1, 3) * M(4, 4) - M(4, 3) * M(1, 4);
float M1334 = M(1, 3) * M(3, 4) - M(3, 3) * M(1, 4);
float M1244 = M(1, 2) * M(4, 4) - M(4, 2) * M(1, 4);
float M1234 = M(1, 2) * M(3, 4) - M(3, 2) * M(1, 4);
float M1243 = M(1, 2) * M(4, 3) - M(4, 2) * M(1, 3);
float M1233 = M(1, 2) * M(3, 3) - M(3, 2) * M(1, 3);
float M1324 = M(1, 3) * M(2, 4) - M(2, 3) * M(1, 4);
float M1224 = M(1, 2) * M(2, 4) - M(2, 2) * M(1, 4);
float M1223 = M(1, 2) * M(2, 3) - M(2, 2) * M(1, 3);
// Adjoint Matrix
I(1, 1) = M(2, 2) * M3344 - M(3, 2) * M2344 + M(4, 2) * M2334;
I(2, 1) = -M(2, 1) * M3344 + M(3, 1) * M2344 - M(4, 1) * M2334;
I(3, 1) = M(2, 1) * M3244 - M(3, 1) * M2244 + M(4, 1) * M2234;
I(4, 1) = -M(2, 1) * M3243 + M(3, 1) * M2243 - M(4, 1) * M2233;
I(1, 2) = -M(1, 2) * M3344 + M(3, 2) * M1344 - M(4, 2) * M1334;
I(2, 2) = M(1, 1) * M3344 - M(3, 1) * M1344 + M(4, 1) * M1334;
I(3, 2) = -M(1, 1) * M3244 + M(3, 1) * M1244 - M(4, 1) * M1234;
I(4, 2) = M(1, 1) * M3243 - M(3, 1) * M1243 + M(4, 1) * M1233;
I(1, 3) = M(1, 2) * M2344 - M(2, 2) * M1344 + M(4, 2) * M1324;
I(2, 3) = -M(1, 1) * M2344 + M(2, 1) * M1344 - M(4, 1) * M1324;
I(3, 3) = M(1, 1) * M2244 - M(2, 1) * M1244 + M(4, 1) * M1224;
I(4, 3) = -M(1, 1) * M2243 + M(2, 1) * M1243 - M(4, 1) * M1223;
I(1, 4) = -M(1, 2) * M2334 + M(2, 2) * M1334 - M(3, 2) * M1324;
I(2, 4) = M(1, 1) * M2334 - M(2, 1) * M1334 + M(3, 1) * M1324;
I(3, 4) = -M(1, 1) * M2234 + M(2, 1) * M1234 - M(3, 1) * M1224;
I(4, 4) = M(1, 1) * M2233 - M(2, 1) * M1233 + M(3, 1) * M1223;
// Division by determinant
I /= M(1, 1) * I(1, 1) +
M(2, 1) * I(1, 2) +
M(3, 1) * I(1, 3) +
M(4, 1) * I(1, 4);
return I;
}
Matrix Matrix::operator~() const
{
const Matrix &M = *this;
return Matrix(M(1, 1), M(2, 1), M(3, 1), M(4, 1),
M(1, 2), M(2, 2), M(3, 2), M(4, 2),
M(1, 3), M(2, 3), M(3, 3), M(4, 3),
M(1, 4), M(2, 4), M(3, 4), M(4, 4));
}
Matrix &Matrix::operator+=(const Matrix &N)
{
Matrix &M = *this;
M(1, 1) += N(1, 1); M(1, 2) += N(1, 2); M(1, 3) += N(1, 3); M(1, 4) += N(1, 4);
M(2, 1) += N(2, 1); M(2, 2) += N(2, 2); M(2, 3) += N(2, 3); M(2, 4) += N(2, 4);
M(3, 1) += N(3, 1); M(3, 2) += N(3, 2); M(3, 3) += N(3, 3); M(3, 4) += N(3, 4);
M(4, 1) += N(4, 1); M(4, 2) += N(4, 2); M(4, 3) += N(4, 3); M(4, 4) += N(4, 4);
return M;
}
Matrix &Matrix::operator-=(const Matrix &N)
{
Matrix &M = *this;
M(1, 1) -= N(1, 1); M(1, 2) -= N(1, 2); M(1, 3) -= N(1, 3); M(1, 4) -= N(1, 4);
M(2, 1) -= N(2, 1); M(2, 2) -= N(2, 2); M(2, 3) -= N(2, 3); M(2, 4) -= N(2, 4);
M(3, 1) -= N(3, 1); M(3, 2) -= N(3, 2); M(3, 3) -= N(3, 3); M(3, 4) -= N(3, 4);
M(4, 1) -= N(4, 1); M(4, 2) -= N(4, 2); M(4, 3) -= N(4, 3); M(4, 4) -= N(4, 4);
return M;
}
Matrix &Matrix::operator*=(float s)
{
Matrix &M = *this;
M(1, 1) *= s; M(1, 2) *= s; M(1, 3) *= s; M(1, 4) *= s;
M(2, 1) *= s; M(2, 2) *= s; M(2, 3) *= s; M(2, 4) *= s;
M(3, 1) *= s; M(3, 2) *= s; M(3, 3) *= s; M(3, 4) *= s;
M(4, 1) *= s; M(4, 2) *= s; M(4, 3) *= s; M(4, 4) *= s;
return M;
}
Matrix &Matrix::operator*=(const Matrix &M)
{
return *this = *this * M;
}
Matrix &Matrix::operator/=(float s)
{
float r = 1.0f / s;
return *this *= r;
}
bool operator==(const Matrix &M, const Matrix &N)
{
if(M(1, 1) == N(1, 1) && M(1, 2) == N(1, 2) && M(1, 3) == N(1, 3) && M(1, 4) == N(1, 4) &&
M(2, 1) == N(2, 1) && M(2, 2) == N(2, 2) && M(2, 3) == N(2, 3) && M(2, 4) == N(2, 4) &&
M(3, 1) == N(3, 1) && M(3, 2) == N(3, 2) && M(3, 3) == N(3, 3) && M(3, 4) == N(3, 4) &&
M(4, 1) == N(4, 1) && M(4, 2) == N(4, 2) && M(4, 3) == N(4, 3) && M(4, 4) == N(4, 4))
return true;
else
return false;
}
bool operator!=(const Matrix &M, const Matrix &N)
{
if(M(1, 1) != N(1, 1) || M(1, 2) != N(1, 2) || M(1, 3) != N(1, 3) || M(1, 4) != N(1, 4) ||
M(2, 1) != N(2, 1) || M(2, 2) != N(2, 2) || M(2, 3) != N(2, 3) || M(2, 4) != N(2, 4) ||
M(3, 1) != N(3, 1) || M(3, 2) != N(3, 2) || M(3, 3) != N(3, 3) || M(3, 4) != N(3, 4) ||
M(4, 1) != N(4, 1) || M(4, 2) != N(4, 2) || M(4, 3) != N(4, 3) || M(4, 4) != N(4, 4))
return true;
else
return false;
}
Matrix operator+(const Matrix &M, const Matrix &N)
{
return Matrix(M(1, 1) + N(1, 1), M(1, 2) + N(1, 2), M(1, 3) + N(1, 3), M(1, 4) + N(1, 4),
M(2, 1) + N(2, 1), M(2, 2) + N(2, 2), M(2, 3) + N(2, 3), M(2, 4) + N(2, 4),
M(3, 1) + N(3, 1), M(3, 2) + N(3, 2), M(3, 3) + N(3, 3), M(3, 4) + N(3, 4),
M(4, 1) + N(4, 1), M(4, 2) + N(4, 2), M(4, 3) + N(4, 3), M(4, 4) + N(4, 4));
}
Matrix operator-(const Matrix &M, const Matrix &N)
{
return Matrix(M(1, 1) - N(1, 1), M(1, 2) - N(1, 2), M(1, 3) - N(1, 3), M(1, 4) - N(1, 4),
M(2, 1) - N(2, 1), M(2, 2) - N(2, 2), M(2, 3) - N(2, 3), M(2, 4) - N(2, 4),
M(3, 1) - N(3, 1), M(3, 2) - N(3, 2), M(3, 3) - N(3, 3), M(3, 4) - N(3, 4),
M(4, 1) - N(4, 1), M(4, 2) - N(4, 2), M(4, 3) - N(4, 3), M(4, 4) - N(4, 4));
}
Matrix operator*(float s, const Matrix &M)
{
return Matrix(s * M(1, 1), s * M(1, 2), s * M(1, 3), s * M(1, 4),
s * M(2, 1), s * M(2, 2), s * M(2, 3), s * M(2, 4),
s * M(3, 1), s * M(3, 2), s * M(3, 3), s * M(3, 4),
s * M(4, 1), s * M(4, 2), s * M(4, 3), s * M(4, 4));
}
Matrix operator*(const Matrix &M, float s)
{
return Matrix(M(1, 1) * s, M(1, 2) * s, M(1, 3) * s, M(1, 4) * s,
M(2, 1) * s, M(2, 2) * s, M(2, 3) * s, M(2, 4) * s,
M(3, 1) * s, M(3, 2) * s, M(3, 3) * s, M(3, 4) * s,
M(4, 1) * s, M(4, 2) * s, M(4, 3) * s, M(4, 4) * s);
}
Matrix operator*(const Matrix &M, const Matrix &N)
{
return Matrix(M(1, 1) * N(1, 1) + M(1, 2) * N(2, 1) + M(1, 3) * N(3, 1) + M(1, 4) * N(4, 1), M(1, 1) * N(1, 2) + M(1, 2) * N(2, 2) + M(1, 3) * N(3, 2) + M(1, 4) * N(4, 2), M(1, 1) * N(1, 3) + M(1, 2) * N(2, 3) + M(1, 3) * N(3, 3) + M(1, 4) * N(4, 3), M(1, 1) * N(1, 4) + M(1, 2) * N(2, 4) + M(1, 3) * N(3, 4) + M(1, 4) * N(4, 4),
M(2, 1) * N(1, 1) + M(2, 2) * N(2, 1) + M(2, 3) * N(3, 1) + M(2, 4) * N(4, 1), M(2, 1) * N(1, 2) + M(2, 2) * N(2, 2) + M(2, 3) * N(3, 2) + M(2, 4) * N(4, 2), M(2, 1) * N(1, 3) + M(2, 2) * N(2, 3) + M(2, 3) * N(3, 3) + M(2, 4) * N(4, 3), M(2, 1) * N(1, 4) + M(2, 2) * N(2, 4) + M(2, 3) * N(3, 4) + M(2, 4) * N(4, 4),
M(3, 1) * N(1, 1) + M(3, 2) * N(2, 1) + M(3, 3) * N(3, 1) + M(3, 4) * N(4, 1), M(3, 1) * N(1, 2) + M(3, 2) * N(2, 2) + M(3, 3) * N(3, 2) + M(3, 4) * N(4, 2), M(3, 1) * N(1, 3) + M(3, 2) * N(2, 3) + M(3, 3) * N(3, 3) + M(3, 4) * N(4, 3), M(3, 1) * N(1, 4) + M(3, 2) * N(2, 4) + M(3, 3) * N(3, 4) + M(3, 4) * N(4, 4),
M(4, 1) * N(1, 1) + M(4, 2) * N(2, 1) + M(4, 3) * N(3, 1) + M(4, 4) * N(4, 1), M(4, 1) * N(1, 2) + M(4, 2) * N(2, 2) + M(4, 3) * N(3, 2) + M(4, 4) * N(4, 2), M(4, 1) * N(1, 3) + M(4, 2) * N(2, 3) + M(4, 3) * N(3, 3) + M(4, 4) * N(4, 3), M(4, 1) * N(1, 4) + M(4, 2) * N(2, 4) + M(4, 3) * N(3, 4) + M(4, 4) * N(4, 4));
}
Matrix operator/(const Matrix &M, float s)
{
float r = 1.0f / s;
return M * r;
}
float4 Matrix::operator*(const float4 &v) const
{
const Matrix &M = *this;
float Mx = M(1, 1) * v.x + M(1, 2) * v.y + M(1, 3) * v.z + M(1, 4) * v.w;
float My = M(2, 1) * v.x + M(2, 2) * v.y + M(2, 3) * v.z + M(2, 4) * v.w;
float Mz = M(3, 1) * v.x + M(3, 2) * v.y + M(3, 3) * v.z + M(3, 4) * v.w;
float Mw = M(4, 1) * v.x + M(4, 2) * v.y + M(4, 3) * v.z + M(4, 4) * v.w;
return {Mx, My, Mz, Mw};
}
float Matrix::det(const Matrix &M)
{
float M3344 = M(3, 3) * M(4, 4) - M(4, 3) * M(3, 4);
float M2344 = M(2, 3) * M(4, 4) - M(4, 3) * M(2, 4);
float M2334 = M(2, 3) * M(3, 4) - M(3, 3) * M(2, 4);
float M1344 = M(1, 3) * M(4, 4) - M(4, 3) * M(1, 4);
float M1334 = M(1, 3) * M(3, 4) - M(3, 3) * M(1, 4);
float M1324 = M(1, 3) * M(2, 4) - M(2, 3) * M(1, 4);
return M(1, 1) * (M(2, 2) * M3344 - M(3, 2) * M2344 + M(4, 2) * M2334) -
M(2, 1) * (M(1, 2) * M3344 - M(3, 2) * M1344 + M(4, 2) * M1334) +
M(3, 1) * (M(1, 2) * M2344 - M(2, 2) * M1344 + M(4, 2) * M1324) -
M(4, 1) * (M(1, 2) * M2334 - M(2, 2) * M1334 + M(3, 2) * M1324);
}
float Matrix::det(float m11)
{
return m11;
}
float Matrix::det(float m11, float m12,
float m21, float m22)
{
return m11 * m22 - m12 * m21;
}
float Matrix::det(float m11, float m12, float m13,
float m21, float m22, float m23,
float m31, float m32, float m33)
{
return m11 * (m22 * m33 - m32 * m23) -
m21 * (m12 * m33 - m32 * m13) +
m31 * (m12 * m23 - m22 * m13);
}
float Matrix::det(float m11, float m12, float m13, float m14,
float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34,
float m41, float m42, float m43, float m44)
{
float M3344 = m33 * m44 - m43 * m34;
float M2344 = m23 * m44 - m43 * m24;
float M2334 = m23 * m34 - m33 * m24;
float M1344 = m13 * m44 - m43 * m14;
float M1334 = m13 * m34 - m33 * m14;
float M1324 = m13 * m24 - m23 * m14;
return m11 * (m22 * M3344 - m32 * M2344 + m42 * M2334) -
m21 * (m12 * M3344 - m32 * M1344 + m42 * M1334) +
m31 * (m12 * M2344 - m22 * M1344 + m42 * M1324) -
m41 * (m12 * M2334 - m22 * M1334 + m32 * M1324);
}
float Matrix::det(const Vector &v1, const Vector &v2, const Vector &v3)
{
return v1 * (v2 % v3);
}
float Matrix::det3(const Matrix &M)
{
return M(1, 1) * (M(2, 2) * M(3, 3) - M(3, 2) * M(2, 3)) -
M(2, 1) * (M(1, 2) * M(3, 3) - M(3, 2) * M(1, 3)) +
M(3, 1) * (M(1, 2) * M(2, 3) - M(2, 2) * M(1, 3));
}
float Matrix::tr(const Matrix &M)
{
return M(1, 1) + M(2, 2) + M(3, 3) + M(4, 4);
}
Matrix &Matrix::orthogonalise()
{
// NOTE: Numnerically instable, won't return exact the same result when already orhtogonal
Matrix &M = *this;
Vector v1(M(1, 1), M(2, 1), M(3, 1));
Vector v2(M(1, 2), M(2, 2), M(3, 2));
Vector v3(M(1, 3), M(2, 3), M(3, 3));
v2 -= v1 * (v1 * v2) / (v1 * v1);
v3 -= v1 * (v1 * v3) / (v1 * v1);
v3 -= v2 * (v2 * v3) / (v2 * v2);
v1 /= Vector::N(v1);
v2 /= Vector::N(v2);
v3 /= Vector::N(v3);
M(1, 1) = v1.x; M(1, 2) = v2.x; M(1, 3) = v3.x;
M(2, 1) = v1.y; M(2, 2) = v2.y; M(2, 3) = v3.y;
M(3, 1) = v1.z; M(3, 2) = v2.z; M(3, 3) = v3.z;
return *this;
}
Matrix Matrix::eulerRotate(const Vector &v)
{
float cz = cos(v.z);
float sz = sin(v.z);
float cx = cos(v.x);
float sx = sin(v.x);
float cy = cos(v.y);
float sy = sin(v.y);
float sxsy = sx * sy;
float sxcy = sx * cy;
return Matrix(cy * cz - sxsy * sz, -cy * sz - sxsy * cz, -sy * cx,
cx * sz, cx * cz, -sx,
sy * cz + sxcy * sz, -sy * sz + sxcy * cz, cy * cx);
}
Matrix Matrix::eulerRotate(float x, float y, float z)
{
return eulerRotate(Vector(x, y, z));
}
Matrix Matrix::translate(const Vector &v)
{
return Matrix(1, 0, 0, v.x,
0, 1, 0, v.y,
0, 0, 1, v.z,
0, 0, 0, 1);
}
Matrix Matrix::translate(float x, float y, float z)
{
return translate(Vector(x, y, z));
}
Matrix Matrix::scale(const Vector &v)
{
return Matrix(v.x, 0, 0,
0, v.y, 0,
0, 0, v.z);
}
Matrix Matrix::scale(float x, float y, float z)
{
return scale(Vector(x, y, z));
}
Matrix Matrix::lookAt(const Vector &v)
{
Vector y = v;
y /= Vector::N(y);
Vector x = y % Vector(0, 0, 1);
x /= Vector::N(x);
Vector z = x % y;
z /= Vector::N(z);
return ~Matrix(x, y, z);
}
Matrix Matrix::lookAt(float x, float y, float z)
{
return translate(Vector(x, y, z));
}
}