📄 matrix.h
字号:
/// determine if matrix is invertible.
/// note: only checks 3x3 sub matrix determinant.
bool invertible() const
{
return !Float::equal(determinant(),0);
}
/// calculate inverse of matrix.
Matrix inverse() const
{
Matrix matrix;
inverse(matrix);
return matrix;
}
/// calculate inverse of matrix and write result to parameter matrix.
void inverse(Matrix &inverse) const
{
const float determinant = this->determinant();
assert(!Float::equal(determinant,0));
float k = 1.0f / determinant;
inverse.m11 = (m22*m33 - m32*m23) * k;
inverse.m12 = (m32*m13 - m12*m33) * k;
inverse.m13 = (m12*m23 - m22*m13) * k;
inverse.m21 = (m23*m31 - m33*m21) * k;
inverse.m22 = (m33*m11 - m13*m31) * k;
inverse.m23 = (m13*m21 - m23*m11) * k;
inverse.m31 = (m21*m32 - m31*m22) * k;
inverse.m32 = (m31*m12 - m11*m32) * k;
inverse.m33 = (m11*m22 - m21*m12) * k;
inverse.m14 = -(inverse.m11*m14 + inverse.m12*m24 + inverse.m13*m34);
inverse.m24 = -(inverse.m21*m14 + inverse.m22*m24 + inverse.m23*m34);
inverse.m34 = -(inverse.m31*m14 + inverse.m32*m24 + inverse.m33*m34);
inverse.m41 = m41;
inverse.m42 = m42;
inverse.m43 = m43;
inverse.m44 = m44;
}
/// calculate transpose of matrix.
Matrix transpose() const
{
Matrix matrix;
transpose(matrix);
return matrix;
}
/// calculate transpose of matrix and write to parameter matrix.
void transpose(Matrix &transpose) const
{
transpose.m11 = m11;
transpose.m12 = m21;
transpose.m13 = m31;
transpose.m14 = m41;
transpose.m21 = m12;
transpose.m22 = m22;
transpose.m23 = m32;
transpose.m24 = m42;
transpose.m31 = m13;
transpose.m32 = m23;
transpose.m33 = m33;
transpose.m34 = m43;
transpose.m41 = m14;
transpose.m42 = m24;
transpose.m43 = m34;
transpose.m44 = m44;
}
/// transform a vector by this matrix.
/// the convention used is post-multiplication by a column vector: x=Ab.
void transform(Vector &vector) const
{
float x = vector.x * m11 + vector.y * m12 + vector.z * m13 + m14;
float y = vector.x * m21 + vector.y * m22 + vector.z * m23 + m24;
float z = vector.x * m31 + vector.y * m32 + vector.z * m33 + m34;
vector.x = x;
vector.y = y;
vector.z = z;
}
/// transform a vector by this matrix, store result in parameter.
/// the convention used is post-multiplication by a column vector: x=Ab.
void transform(const Vector &vector, Vector &result) const
{
result.x = vector.x * m11 + vector.y * m12 + vector.z * m13 + m14;
result.y = vector.x * m21 + vector.y * m22 + vector.z * m23 + m24;
result.z = vector.x * m31 + vector.y * m32 + vector.z * m33 + m34;
}
/// add another matrix to this matrix.
void add(const Matrix &matrix)
{
m11 += matrix.m11;
m12 += matrix.m12;
m13 += matrix.m13;
m14 += matrix.m14;
m21 += matrix.m21;
m22 += matrix.m22;
m23 += matrix.m23;
m24 += matrix.m24;
m31 += matrix.m31;
m32 += matrix.m32;
m33 += matrix.m33;
m34 += matrix.m34;
m41 += matrix.m41;
m42 += matrix.m42;
m43 += matrix.m43;
m44 += matrix.m44;
}
/// subtract a matrix from this matrix.
void subtract(const Matrix &matrix)
{
m11 -= matrix.m11;
m12 -= matrix.m12;
m13 -= matrix.m13;
m14 -= matrix.m14;
m21 -= matrix.m21;
m22 -= matrix.m22;
m23 -= matrix.m23;
m24 -= matrix.m24;
m31 -= matrix.m31;
m32 -= matrix.m32;
m33 -= matrix.m33;
m34 -= matrix.m34;
m41 -= matrix.m41;
m42 -= matrix.m42;
m43 -= matrix.m43;
m44 -= matrix.m44;
}
/// multiply this matrix by a scalar.
void multiply(float scalar)
{
m11 *= scalar;
m12 *= scalar;
m13 *= scalar;
m14 *= scalar;
m21 *= scalar;
m22 *= scalar;
m23 *= scalar;
m24 *= scalar;
m31 *= scalar;
m32 *= scalar;
m33 *= scalar;
m34 *= scalar;
m41 *= scalar;
m42 *= scalar;
m43 *= scalar;
m44 *= scalar;
}
/// multiply two matrices.
/// note: this is a full 4x4 matrix multiplication.
void multiply(const Matrix &matrix, Matrix &result)
{
result.m11 = m11*matrix.m11 + m12*matrix.m21 + m13*matrix.m31 + m14*matrix.m41;
result.m12 = m11*matrix.m12 + m12*matrix.m22 + m13*matrix.m32 + m14*matrix.m42;
result.m13 = m11*matrix.m13 + m12*matrix.m23 + m13*matrix.m33 + m14*matrix.m43;
result.m14 = m11*matrix.m14 + m12*matrix.m24 + m13*matrix.m34 + m14*matrix.m44;
result.m21 = m21*matrix.m11 + m22*matrix.m21 + m23*matrix.m31 + m24*matrix.m41;
result.m22 = m21*matrix.m12 + m22*matrix.m22 + m23*matrix.m32 + m24*matrix.m42;
result.m23 = m21*matrix.m13 + m22*matrix.m23 + m23*matrix.m33 + m24*matrix.m43;
result.m24 = m21*matrix.m14 + m22*matrix.m24 + m23*matrix.m34 + m24*matrix.m44;
result.m31 = m31*matrix.m11 + m32*matrix.m21 + m33*matrix.m31 + m34*matrix.m41;
result.m32 = m31*matrix.m12 + m32*matrix.m22 + m33*matrix.m32 + m34*matrix.m42;
result.m33 = m31*matrix.m13 + m32*matrix.m23 + m33*matrix.m33 + m34*matrix.m43;
result.m34 = m31*matrix.m14 + m32*matrix.m24 + m33*matrix.m34 + m34*matrix.m44;
result.m41 = m41*matrix.m11 + m42*matrix.m21 + m43*matrix.m31 + m44*matrix.m41;
result.m42 = m41*matrix.m12 + m42*matrix.m22 + m43*matrix.m32 + m44*matrix.m42;
result.m43 = m41*matrix.m13 + m42*matrix.m23 + m43*matrix.m33 + m44*matrix.m43;
result.m44 = m41*matrix.m14 + m42*matrix.m24 + m43*matrix.m34 + m44*matrix.m44;
}
/// equals operator
bool operator ==(const Matrix &other) const
{
if (Float::equal(m11,other.m11) &&
Float::equal(m12,other.m12) &&
Float::equal(m13,other.m13) &&
Float::equal(m14,other.m14) &&
Float::equal(m21,other.m21) &&
Float::equal(m22,other.m22) &&
Float::equal(m23,other.m23) &&
Float::equal(m24,other.m24) &&
Float::equal(m31,other.m31) &&
Float::equal(m32,other.m32) &&
Float::equal(m33,other.m33) &&
Float::equal(m34,other.m34) &&
Float::equal(m41,other.m41) &&
Float::equal(m42,other.m42) &&
Float::equal(m43,other.m43) &&
Float::equal(m44,other.m44)) return true;
else return false;
}
/// not equals operator
bool operator !=(const Matrix &other) const
{
return !(*this==other);
}
/// cute access to matrix elements via overloaded () operator.
/// use it like this: Matrix matrix; float element = matrix(row, column);
float operator()(int i, int j) const
{
assert(i>=1);
assert(i<=4);
assert(j>=1);
assert(j<=4);
const float *data = &m11;
return data[(i<<2) + j];
}
/// cute access to basis vectors of 3x3 submatrix
const Vector& i() const
{
return *((Vector*)&m11);
}
const Vector& j() const
{
return *((Vector*)&m21);
}
const Vector& k() const
{
return *((Vector*)&m31);
}
/// print a basic representation of the matrix data to stdout.
void print() const
{
printf("Matrix[(%f, %f, %f, %f) | (%f, %f, %f, %f) | (%f, %f, %f, %f) | (%f, %f, %f, %f)]", m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44);
}
friend inline Matrix operator-(const Matrix &a);
friend inline Matrix operator+(const Matrix &a, const Matrix &b);
friend inline Matrix operator-(const Matrix &a, const Matrix &b);
friend inline Matrix operator*(const Matrix &a, const Matrix &b);
friend inline Matrix& operator+=(Matrix &a, const Matrix &b);
friend inline Matrix& operator-=(Matrix &a, const Matrix &b);
friend inline Matrix& operator*=(Matrix &a, const Matrix &b);
friend inline Vector operator*(const Matrix &matrix, const Vector &vector);
friend inline Vector operator*(const Vector &vector, const Matrix &matrix);
friend inline Vector& operator*=(Vector &vector, const Matrix &matrix);
friend inline Matrix operator*(const Matrix &a, float s);
friend inline Matrix operator/(const Matrix &a, float s);
friend inline Matrix& operator*=(Matrix &a, float s);
friend inline Matrix& operator/=(Matrix &a, float s);
friend inline Matrix operator*(float s, const Matrix &a);
friend inline Matrix& operator*=(float s, Matrix &a);
float m11,m12,m13,m14; // 4x4 matrix, index m[row][column], convention: pre-multiply column vector, Ax = b
float m21,m22,m23,m24; // hence: (m11,m21,m31) make up the x axis of the 3x3 sub matrix,
float m31,m32,m33,m34; // and (m14,m24,m34) is the translation vector.
float m41,m42,m43,m44;
};
inline Matrix operator-(const Matrix &a)
{
return Matrix(-a.m11, -a.m12, -a.m13, -a.m14,
-a.m21, -a.m22, -a.m23, -a.m24,
-a.m31, -a.m32, -a.m33, -a.m34,
-a.m41, -a.m42, -a.m43, -a.m44);
}
inline Matrix operator+(const Matrix &a, const Matrix &b)
{
return Matrix(a.m11+b.m11, a.m12+b.m12, a.m13+b.m13, a.m14+b.m14,
a.m21+b.m21, a.m22+b.m22, a.m23+b.m23, a.m24+b.m24,
a.m31+b.m31, a.m32+b.m32, a.m33+b.m33, a.m34+b.m34,
a.m41+b.m41, a.m42+b.m42, a.m43+b.m43, a.m44+b.m44);
}
inline Matrix operator-(const Matrix &a, const Matrix &b)
{
return Matrix(a.m11-b.m11, a.m12-b.m12, a.m13-b.m13, a.m14-b.m14,
a.m21-b.m21, a.m22-b.m22, a.m23-b.m23, a.m24-b.m24,
a.m31-b.m31, a.m32-b.m32, a.m33-b.m33, a.m34-b.m34,
a.m41-b.m41, a.m42-b.m42, a.m43-b.m43, a.m44-b.m44);
}
inline Matrix operator*(const Matrix &a, const Matrix &b)
{
return Matrix(a.m11*b.m11 + a.m12*b.m21 + a.m13*b.m31 + a.m14*b.m41,
a.m11*b.m12 + a.m12*b.m22 + a.m13*b.m32 + a.m14*b.m42,
a.m11*b.m13 + a.m12*b.m23 + a.m13*b.m33 + a.m14*b.m43,
a.m11*b.m14 + a.m12*b.m24 + a.m13*b.m34 + a.m14*b.m44,
a.m21*b.m11 + a.m22*b.m21 + a.m23*b.m31 + a.m24*b.m41,
a.m21*b.m12 + a.m22*b.m22 + a.m23*b.m32 + a.m24*b.m42,
a.m21*b.m13 + a.m22*b.m23 + a.m23*b.m33 + a.m24*b.m43,
a.m21*b.m14 + a.m22*b.m24 + a.m23*b.m34 + a.m24*b.m44,
a.m31*b.m11 + a.m32*b.m21 + a.m33*b.m31 + a.m34*b.m41,
a.m31*b.m12 + a.m32*b.m22 + a.m33*b.m32 + a.m34*b.m42,
a.m31*b.m13 + a.m32*b.m23 + a.m33*b.m33 + a.m34*b.m43,
a.m31*b.m14 + a.m32*b.m24 + a.m33*b.m34 + a.m34*b.m44,
a.m41*b.m11 + a.m42*b.m21 + a.m43*b.m31 + a.m44*b.m41,
a.m41*b.m12 + a.m42*b.m22 + a.m43*b.m32 + a.m44*b.m42,
a.m41*b.m13 + a.m42*b.m23 + a.m43*b.m33 + a.m44*b.m43,
a.m41*b.m14 + a.m42*b.m24 + a.m43*b.m34 + a.m44*b.m44);
}
inline Matrix& operator+=(Matrix &a, const Matrix &b)
{
a.add(b);
return a;
}
inline Matrix& operator-=(Matrix &a, const Matrix &b)
{
a.subtract(b);
return a;
}
inline Matrix& operator*=(Matrix &a, const Matrix &b)
{
a = Matrix(a.m11*b.m11 + a.m12*b.m21 + a.m13*b.m31 + a.m14*b.m41,
a.m11*b.m12 + a.m12*b.m22 + a.m13*b.m32 + a.m14*b.m42,
a.m11*b.m13 + a.m12*b.m23 + a.m13*b.m33 + a.m14*b.m43,
a.m11*b.m14 + a.m12*b.m24 + a.m13*b.m34 + a.m14*b.m44,
a.m21*b.m11 + a.m22*b.m21 + a.m23*b.m31 + a.m24*b.m41,
a.m21*b.m12 + a.m22*b.m22 + a.m23*b.m32 + a.m24*b.m42,
a.m21*b.m13 + a.m22*b.m23 + a.m23*b.m33 + a.m24*b.m43,
a.m21*b.m14 + a.m22*b.m24 + a.m23*b.m34 + a.m24*b.m44,
a.m31*b.m11 + a.m32*b.m21 + a.m33*b.m31 + a.m34*b.m41,
a.m31*b.m12 + a.m32*b.m22 + a.m33*b.m32 + a.m34*b.m42,
a.m31*b.m13 + a.m32*b.m23 + a.m33*b.m33 + a.m34*b.m43,
a.m31*b.m14 + a.m32*b.m24 + a.m33*b.m34 + a.m34*b.m44,
a.m41*b.m11 + a.m42*b.m21 + a.m43*b.m31 + a.m44*b.m41,
a.m41*b.m12 + a.m42*b.m22 + a.m43*b.m32 + a.m44*b.m42,
a.m41*b.m13 + a.m42*b.m23 + a.m43*b.m33 + a.m44*b.m43,
a.m41*b.m14 + a.m42*b.m24 + a.m43*b.m34 + a.m44*b.m44);
return a;
}
inline Vector operator*(const Matrix &matrix, const Vector &vector)
{
return Vector(vector.x * matrix.m11 + vector.y * matrix.m12 + vector.z * matrix.m13 + matrix.m14,
vector.x * matrix.m21 + vector.y * matrix.m22 + vector.z * matrix.m23 + matrix.m24,
vector.x * matrix.m31 + vector.y * matrix.m32 + vector.z * matrix.m33 + matrix.m34);
}
inline Vector operator*(const Vector &vector, const Matrix &matrix)
{
// when we premultiply x*A we assume the vector is a row vector
return Vector(vector.x * matrix.m11 + vector.y * matrix.m21 + vector.z * matrix.m31 + matrix.m41,
vector.x * matrix.m12 + vector.y * matrix.m22 + vector.z * matrix.m32 + matrix.m42,
vector.x * matrix.m13 + vector.y * matrix.m23 + vector.z * matrix.m33 + matrix.m43);
}
inline Vector& operator*=(Vector &vector, const Matrix &matrix)
{
// equivalent to: vector = matrix * vector (not vector*matrix!)
const float rx = vector.x * matrix.m11 + vector.y * matrix.m12 + vector.z * matrix.m13 + matrix.m14;
const float ry = vector.x * matrix.m21 + vector.y * matrix.m22 + vector.z * matrix.m23 + matrix.m24;
const float rz = vector.x * matrix.m31 + vector.y * matrix.m32 + vector.z * matrix.m33 + matrix.m34;
vector.x = rx;
vector.y = ry;
vector.z = rz;
return vector;
}
inline Matrix operator*(const Matrix &a, float s)
{
return Matrix(s*a.m11, s*a.m12, s*a.m13, s*a.m14,
s*a.m21, s*a.m22, s*a.m23, s*a.m24,
s*a.m31, s*a.m32, s*a.m33, s*a.m34,
s*a.m41, s*a.m42, s*a.m43, s*a.m44);
}
inline Matrix operator/(const Matrix &a, float s)
{
assert(s!=0);
const float inv = 1.0f / s;
return Matrix(inv*a.m11, inv*a.m12, inv*a.m13, inv*a.m14,
inv*a.m21, inv*a.m22, inv*a.m23, inv*a.m24,
inv*a.m31, inv*a.m32, inv*a.m33, inv*a.m34,
inv*a.m41, inv*a.m42, inv*a.m43, inv*a.m44);
}
inline Matrix& operator*=(Matrix &a, float s)
{
a.multiply(s);
return a;
}
inline Matrix& operator/=(Matrix &a, float s)
{
assert(s!=0);
a.multiply(1.0f/s);
return a;
}
inline Matrix operator*(float s, const Matrix &a)
{
return Matrix(s*a.m11, s*a.m12, s*a.m13, s*a.m14,
s*a.m21, s*a.m22, s*a.m23, s*a.m24,
s*a.m31, s*a.m32, s*a.m33, s*a.m34,
s*a.m41, s*a.m42, s*a.m43, s*a.m44);
}
inline Matrix& operator*=(float s, Matrix &a)
{
a.multiply(s);
return a;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -