Add Matrix4 Inverse and Transpose

Transpose is easy, with a bool flag to determine whether to access elements in row-major or column-major format. Inverse is more difficult, so this change only does translation inverses.
This commit is contained in:
Eryn Wells 2014-08-10 16:57:34 -07:00
parent 5b25b402c7
commit 4d4dc91ff4
3 changed files with 99 additions and 4 deletions

View file

@ -65,7 +65,8 @@ Matrix4::Translation(Double x,
* charles::basics::Matrix4::Matrix4 --
*/
Matrix4::Matrix4()
: mData()
: mData(),
mTransposed(false)
{ }
@ -73,6 +74,7 @@ Matrix4::Matrix4()
* charles::basics::Matrix4::Matrix4 --
*/
Matrix4::Matrix4(const Double data[16])
: mTransposed(false)
{
memcpy(mData, data, sizeof(Double) * 16);
}
@ -83,7 +85,13 @@ Matrix4::Matrix4(const Double data[16])
*/
Matrix4::Matrix4(const Matrix4 &rhs)
: Matrix4(rhs.mData)
{ }
{
/*
* Needs to be in the body instead of the initializer list because
* (apparently) delegating constructors must be the only thing in the list.
*/
mTransposed = rhs.mTransposed;
}
/*
@ -93,6 +101,7 @@ Matrix4&
Matrix4::operator=(const Matrix4 &rhs)
{
memcpy(mData, rhs.mData, sizeof(Double) * 16);
mTransposed = rhs.mTransposed;
return *this;
}
@ -138,7 +147,12 @@ Matrix4::operator()(UInt i,
ss << "matrix index out of bounds: i = " << i << ", j = " << j;
throw std::out_of_range(ss.str());
}
return mData[i*4 + j];
if (!mTransposed) {
return mData[i*4 + j];
} else {
return mData[i + j*4];
}
}
@ -155,7 +169,11 @@ Matrix4::operator()(UInt i,
ss << "matrix index out of bounds: i = " << i << ", j = " << j;
throw std::out_of_range(ss.str());
}
return mData[i*4 + j];
if (!mTransposed) {
return mData[i*4 + j];
} else {
return mData[i + j*4];
}
}
@ -255,6 +273,28 @@ Matrix4::operator*(const Vector4 &rhs)
}
/*
* charles::basics::Matrix4::Transpose --
*/
Matrix4&
Matrix4::Transpose()
{
mTransposed = !mTransposed;
return *this;
}
Matrix4&
Matrix4::Inverse()
{
/* XXX: Only translation matrices are supported right now. */
operator()(0,3) = -operator()(0,3);
operator()(1,3) = -operator()(1,3);
operator()(2,3) = -operator()(2,3);
return *this;
}
/*
* charles::basics::operator* --
*/
@ -266,6 +306,27 @@ operator*(Double lhs,
return rhs * lhs;
}
/*
* charles::basics::Transposed --
*/
Matrix4
Transposed(Matrix4 m)
{
return m.Transpose();
}
/*
* charles::basics::Inverse --
*/
Matrix4
Inverse(Matrix4 m)
{
return m.Inverse();
}
} /* namespace mespace */
} /* namespace charles */

View file

@ -73,15 +73,31 @@ struct Matrix4
Vector4 operator*(const Vector4 &rhs) const;
/** @} */
Matrix4& Transpose();
Matrix4& Inverse();
protected:
/** The matrix data */
Double mData[16];
/**
* `true` if the matrix has been transposed (i.e. should be indexed in
* column-major format).
*/
bool mTransposed;
};
/** Scalar multiplication, scalar factor on the left. */
Matrix4 operator*(Double lhs, const Matrix4 &rhs);
/** Transpose the given matrix. */
Matrix4 Transposed(Matrix4 rhs);
/** Invert the given matrix. */
Matrix4 Inverse(Matrix4 rhs);
} /* namespace basics */
} /* namespace charles */

View file

@ -293,3 +293,21 @@ TEST_F(Matrix4Test, IdentityVectorMultiplication)
EXPECT_EQ(p1.Y(), v1.Y());
EXPECT_EQ(p1.Z(), v1.Z());
}
TEST_F(Matrix4Test, Transpose)
{
Matrix4 t1 = Transposed(m1);
for (UInt i = 0; i < 4; i++) {
for (UInt j = 0; j < 4; j++) {
EXPECT_EQ(m1(i,j), t1(j,i));
}
}
t1.Transpose();
for (UInt i = 0; i < 4; i++) {
for (UInt j = 0; j < 4; j++) {
EXPECT_EQ(m1(i,j), t1(i,j));
}
}
}