Matrix4::Matrix4()
{
}
Matrix4::Matrix4(const Matrix4 &M)
{
for(UINT Row = 0; Row < 4; Row++)
{
for(UINT Col = 0; Col < 4; Col++)
{
_Entries[Row][Col] = M[Row][Col];
}
}
}
Matrix4::Matrix4(const Vec3f &V0, const Vec3f &V1, const Vec3f &V2)
{
_Entries[0][0] = V0.x;
_Entries[0][1] = V0.y;
_Entries[0][2] = V0.z;
_Entries[0][3] = 0.0f;
_Entries[1][0] = V1.x;
_Entries[1][1] = V1.y;
_Entries[1][2] = V1.z;
_Entries[1][3] = 0.0f;
_Entries[2][0] = V2.x;
_Entries[2][1] = V2.y;
_Entries[2][2] = V2.z;
_Entries[2][3] = 0.0f;
_Entries[3][0] = 0.0f;
_Entries[3][1] = 0.0f;
_Entries[3][2] = 0.0f;
_Entries[3][3] = 1.0f;
}
#ifdef USE_D3D
Matrix4::Matrix4(const D3DXMATRIX &M)
{
for(UINT Row = 0; Row < 4; Row++)
{
for(UINT Col = 0; Col < 4; Col++)
{
_Entries[Row][Col] = M(Row, Col);
}
}
}
#endif
Matrix4& Matrix4::operator = (const Matrix4 &M)
{
for(UINT Row = 0; Row < 4; Row++)
{
for(UINT Col = 0; Col < 4; Col++)
{
_Entries[Row][Col] = M[Row][Col];
}
}
return (*this);
}
String Matrix4::CommaSeparatedString() const
{
String Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result += String(_Entries[i][i2]);
if(i2 != 3)
{
Result += ", ";
}
}
if(i != 3)
{
Result += "\n";
}
}
return Result;
}
String Matrix4::CommaSeparatedStringSingleLine() const
{
String Result;
for(UINT i = 0; i < 4; i++)
{
Result += "(";
for(UINT i2 = 0; i2 < 4; i2++)
{
Result += String(_Entries[i][i2]);
if(i2 != 3)
{
Result += ", ";
}
}
Result += ")";
}
return Result;
}
String Matrix4::SpaceSeperatedStringSingleLine() const
{
String Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result += String(_Entries[i][i2]);
if(i2 != 3)
{
Result += " ";
}
}
}
return Result;
}
String Matrix4::TabSeperatedString() const
{
String Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result += String(_Entries[i][i2]);
if(i2 != 3)
{
Result += ", ";
}
}
if(i != 3)
{
Result += "\n";
}
}
return Result;
}
Matrix4 Matrix4::Inverse() const
{
double Result[4][4];
double tmp[12];
double src[16];
double det;
for (UINT i = 0; i < 4; i++)
{
src[i + 0 ] = (*this)[i][0];
src[i + 4 ] = (*this)[i][1];
src[i + 8 ] = (*this)[i][2];
src[i + 12] = (*this)[i][3];
}
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];
Result[0][0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
Result[0][0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
Result[0][1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
Result[0][1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
Result[0][2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
Result[0][2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
Result[0][3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
Result[0][3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
Result[1][0] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
Result[1][0] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
Result[1][1] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
Result[1][1] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
Result[1][2] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
Result[1][2] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
Result[1][3] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
Result[1][3] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
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];
Result[2][0] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
Result[2][0] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
Result[2][1] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
Result[2][1] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
Result[2][2] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
Result[2][2] -= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
Result[2][3] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
Result[2][3] -= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
Result[3][0] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
Result[3][0] -= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
Result[3][1] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
Result[3][1] -= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
Result[3][2] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
Result[3][2] -= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
Result[3][3] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
Result[3][3] -= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
det=src[0]*Result[0][0]+src[1]*Result[0][1]+src[2]*Result[0][2]+src[3]*Result[0][3];
det = 1.0f / det;
Matrix4 FloatResult;
for (UINT i = 0; i < 4; i++)
{
for (UINT j = 0; j < 4; j++)
{
FloatResult[i][j] = float(Result[i][j] * det);
}
}
return FloatResult;
}
Matrix4 Matrix4::Transpose() const
{
Matrix4 Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result[i2][i] = _Entries[i][i2];
}
}
return Result;
}
Matrix4 Matrix4::Identity()
{
Matrix4 Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
if(i == i2)
{
Result[i][i2] = 1.0f;
}
else
{
Result[i][i2] = 0.0f;
}
}
}
return Result;
}
Matrix4 Matrix4::Rotation(const Vec3f &_Basis1, const Vec3f &_Basis2, const Vec3f &_Basis3)
{
Vec3f Basis1 = Vec3f::Normalize(_Basis1);
Vec3f Basis2 = Vec3f::Normalize(_Basis2);
Vec3f Basis3 = Vec3f::Normalize(_Basis3);
Matrix4 Result;
Result[0][0] = Basis1.x;
Result[1][0] = Basis1.y;
Result[2][0] = Basis1.z;
Result[3][0] = 0.0f;
Result[0][1] = Basis2.x;
Result[1][1] = Basis2.y;
Result[2][1] = Basis2.z;
Result[3][1] = 0.0f;
Result[0][2] = Basis3.x;
Result[1][2] = Basis3.y;
Result[2][2] = Basis3.z;
Result[3][2] = 0.0f;
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = 0.0f;
Result[3][3] = 1.0f;
return Result;
}
Matrix4 Matrix4::Camera(const Vec3f &Eye, const Vec3f &_Look, const Vec3f &_Up, const Vec3f &_Right)
{
Vec3f Look = Vec3f::Normalize(_Look);
Vec3f Up = Vec3f::Normalize(_Up);
Vec3f Right = Vec3f::Normalize(_Right);
Matrix4 Result;
Result[0][0] = Right.x;
Result[1][0] = Right.y;
Result[2][0] = Right.z;
Result[3][0] = -Vec3f::Dot(Right, Eye);
Result[0][1] = Up.x;
Result[1][1] = Up.y;
Result[2][1] = Up.z;
Result[3][1] = -Vec3f::Dot(Up, Eye);
Result[0][2] = Look.x;
Result[1][2] = Look.y;
Result[2][2] = Look.z;
Result[3][2] = -Vec3f::Dot(Look, Eye);
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = 0.0f;
Result[3][3] = 1.0f;
return Result;
}
Matrix4 Matrix4::LookAt(const Vec3f &Eye, const Vec3f &At, const Vec3f &Up)
{
Vec3f XAxis, YAxis, ZAxis;
ZAxis = Vec3f::Normalize(Eye - At);
XAxis = Vec3f::Normalize(Vec3f::Cross(Up, ZAxis));
YAxis = Vec3f::Normalize(Vec3f::Cross(ZAxis, XAxis));
Matrix4 Result;
Result[0][0] = XAxis.x;
Result[1][0] = XAxis.y;
Result[2][0] = XAxis.z;
Result[3][0] = -Vec3f::Dot(XAxis,Eye);
Result[0][1] = YAxis.x;
Result[1][1] = YAxis.y;
Result[2][1] = YAxis.z;
Result[3][1] = -Vec3f::Dot(YAxis,Eye);
Result[0][2] = ZAxis.x;
Result[1][2] = ZAxis.y;
Result[2][2] = ZAxis.z;
Result[3][2] = -Vec3f::Dot(ZAxis,Eye);
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = 0.0f;
Result[3][3] = 1.0f;
return Result;
}
Matrix4 Matrix4::Orthogonal(float Width, float Height, float ZNear, float ZFar)
{
Matrix4 Result;
Result[0][0] = 2.0f / Width;
Result[1][0] = 0.0f;
Result[2][0] = 0.0f;
Result[3][0] = 0.0f;
Result[0][1] = 0.0f;
Result[1][1] = 2.0f / Height;
Result[2][1] = 0.0f;
Result[3][1] = 0.0f;
Result[0][2] = 0.0f;
Result[1][2] = 0.0f;
Result[2][2] = 1.0f / (ZNear - ZFar);
Result[3][2] = ZNear / (ZNear - ZFar);
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = 0.0f;
Result[3][3] = 1.0f;
return Result;
}
Matrix4 Matrix4::Perspective(float Width, float Height, float ZNear, float ZFar)
{
Matrix4 Result;
Result[0][0] = 2.0f * ZNear / Width;
Result[1][0] = 0.0f;
Result[2][0] = 0.0f;
Result[3][0] = 0.0f;
Result[0][1] = 0.0f;
Result[1][1] = 2.0f * ZNear / Height;
Result[2][1] = 0.0f;
Result[3][1] = 0.0f;
Result[0][2] = 0.0f;
Result[1][2] = 0.0f;
Result[2][2] = ZFar / (ZNear - ZFar);
Result[3][2] = ZFar * ZNear / (ZNear - ZFar);
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = -1.0f;
Result[3][3] = 0.0f;
return Result;
}
Matrix4 Matrix4::PerspectiveFov(float FOV, float Aspect, float ZNear, float ZFar)
{
float Width = 1.0f / tanf(FOV/2.0f), Height = Aspect / tanf(FOV/2.0f);
Matrix4 Result;
Result[0][0] = Width;
Result[1][0] = 0.0f;
Result[2][0] = 0.0f;
Result[3][0] = 0.0f;
Result[0][1] = 0.0f;
Result[1][1] = Height;
Result[2][1] = 0.0f;
Result[3][1] = 0.0f;
Result[0][2] = 0.0f;
Result[1][2] = 0.0f;
Result[2][2] = ZFar / (ZNear - ZFar);
Result[3][2] = ZFar * ZNear / (ZNear - ZFar);
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = -1.0f;
Result[3][3] = 0.0f;
return Result;
}
Matrix4 Matrix4::PerspectiveMultiFov(float FovX, float FovY, float ZNear, float ZFar)
{
float Width = 1.0f / tanf(FovX / 2.0f), Height = 1.0f / tanf(FovY / 2.0f);
Matrix4 Result;
Result[0][0] = Width;
Result[1][0] = 0.0f;
Result[2][0] = 0.0f;
Result[3][0] = 0.0f;
Result[0][1] = 0.0f;
Result[1][1] = Height;
Result[2][1] = 0.0f;
Result[3][1] = 0.0f;
Result[0][2] = 0.0f;
Result[1][2] = 0.0f;
Result[2][2] = ZFar / (ZNear - ZFar);
Result[3][2] = ZFar * ZNear / (ZNear - ZFar);
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = -1.0f;
Result[3][3] = 0.0f;
return Result;
}
Matrix4 Matrix4::Rotation(const Vec3f &Axis, float Angle)
{
float c = cosf(Angle);
float s = sinf(Angle);
float t = 1.0f - c;
Vec3f NormalizedAxis = Vec3f::Normalize(Axis);
float x = NormalizedAxis.x;
float y = NormalizedAxis.y;
float z = NormalizedAxis.z;
Matrix4 Result;
Result[0][0] = 1 + t*(x*x-1);
Result[0][1] = z*s+t*x*y;
Result[0][2] = -y*s+t*x*z;
Result[0][3] = 0.0f;
Result[1][0] = -z*s+t*x*y;
Result[1][1] = 1+t*(y*y-1);
Result[1][2] = x*s+t*y*z;
Result[1][3] = 0.0f;
Result[2][0] = y*s+t*x*z;
Result[2][1] = -x*s+t*y*z;
Result[2][2] = 1+t*(z*z-1);
Result[2][3] = 0.0f;
Result[3][0] = 0.0f;
Result[3][1] = 0.0f;
Result[3][2] = 0.0f;
Result[3][3] = 1.0f;
return Result;
}
Matrix4 Matrix4::Rotation(float Yaw, float Pitch, float Roll)
{
return RotationY(Yaw) * RotationX(Pitch) * RotationZ(Roll);
}
Matrix4 Matrix4::Rotation(const Vec3f &Axis, float Angle, const Vec3f &Center)
{
return Translation(-Center) * Rotation(Axis, Angle) * Translation(Center);
}
Matrix4 Matrix4::RotationX(float Theta)
{
float CosT = cosf(Theta);
float SinT = sinf(Theta);
Matrix4 Result = Identity();
Result[1][1] = CosT;
Result[1][2] = SinT;
Result[2][1] = -SinT;
Result[2][2] = CosT;
return Result;
}
Matrix4 Matrix4::RotationY(float Theta)
{
float CosT = cosf(Theta);
float SinT = sinf(Theta);
Matrix4 Result = Identity();
Result[0][0] = CosT;
Result[0][2] = SinT;
Result[2][0] = -SinT;
Result[2][2] = CosT;
return Result;
}
Matrix4 Matrix4::RotationZ(float Theta)
{
float CosT = cosf(Theta);
float SinT = sinf(Theta);
Matrix4 Result = Identity();
Result[0][0] = CosT;
Result[0][1] = SinT;
Result[1][0] = -SinT;
Result[1][1] = CosT;
return Result;
}
Matrix4 Matrix4::Scaling(const Vec3f &ScaleFactors)
{
Matrix4 Result;
Result[0][0] = ScaleFactors.x;
Result[1][0] = 0.0f;
Result[2][0] = 0.0f;
Result[3][0] = 0.0f;
Result[0][1] = 0.0f;
Result[1][1] = ScaleFactors.y;
Result[2][1] = 0.0f;
Result[3][1] = 0.0f;
Result[0][2] = 0.0f;
Result[1][2] = 0.0f;
Result[2][2] = ScaleFactors.z;
Result[3][2] = 0.0f;
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = 0.0f;
Result[3][3] = 1.0f;
return Result;
}
Matrix4 Matrix4::Translation(const Vec3f &Pos)
{
Matrix4 Result;
Result[0][0] = 1.0f;
Result[1][0] = 0.0f;
Result[2][0] = 0.0f;
Result[3][0] = Pos.x;
Result[0][1] = 0.0f;
Result[1][1] = 1.0f;
Result[2][1] = 0.0f;
Result[3][1] = Pos.y;
Result[0][2] = 0.0f;
Result[1][2] = 0.0f;
Result[2][2] = 1.0f;
Result[3][2] = Pos.z;
Result[0][3] = 0.0f;
Result[1][3] = 0.0f;
Result[2][3] = 0.0f;
Result[3][3] = 1.0f;
return Result;
}
Matrix4 Matrix4::ChangeOfBasis(const Vec3f &Source0, const Vec3f &Source1, const Vec3f &Source2, const Vec3f &SourceOrigin,
const Vec3f &Target0, const Vec3f &Target1, const Vec3f &Target2, const Vec3f &TargetOrigin)
{
Matrix4 RotationComponent = Matrix4(Source0, Source1, Source2).Inverse() * Matrix4(Target0, Target1, Target2);
Matrix4 Result = Translation(-SourceOrigin) * RotationComponent * Translation(TargetOrigin);
return Result;
}
Matrix4 Matrix4::Face(const Vec3f &V0, const Vec3f &V1)
{
Vec3f Axis = Vec3f::Cross(V0, V1);
float Angle = Vec3f::AngleBetween(V0, V1);
if(Angle == 0.0f)
{
return Identity();
}
else if(Axis.Length() == 0.0f)
{
Vec3f basis0, basis1;
Vec3f::CompleteOrthonormalBasis(V0, basis0, basis1);
return Rotation(basis0, Angle);
}
else
{
return Rotation(Axis, Angle);
}
}
Matrix4 Matrix4::Viewport(float Width, float Height)
{
return Matrix4::Scaling(Vec3f(Width * 0.5f, -Height * 0.5f, 1.0f)) * Matrix4::Translation(Vec3f(Width * 0.5f, Height * 0.5f, 0.0f));
}
float Matrix4::CompareMatrices(const Matrix4 &Left, const Matrix4 &Right)
{
float Sum = 0.0f;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Sum += Math::Abs(Left[i][i2] - Right[i][i2]);
}
}
return Sum / 16.0f;
}
Plane Matrix4::TransformPlane(const Plane &P) const
{
Vec4f v = Vec4f(P.a, P.b, P.c, P.d) * (*this);
return Plane(v.x, v.y, v.z, v.w).Normalize();
}
#ifdef USE_D3D
Matrix4::operator D3DXMATRIX() const
{
D3DXMATRIX M;
int i,i2;
for(i=0;i<4;i++)
for(i2=0;i2<4;i2++)
{
M(i,i2) = _Entries[i][i2];
}
return M;
}
#endif
ostream& operator << (ostream &os, const Matrix4 &m)
{
os << setprecision(8) << setiosflags(ios::right | ios::showpoint);
for(UINT i=0;i<4;i++)
{
for(UINT i2=0;i2<4;i2++)
{
os << setw(12) << m[i][i2];
}
os << endl;
}
return os;
}
istream& operator >> (istream &is, Matrix4 &m)
{
for(UINT i=0;i<4;i++)
{
for(UINT i2=0;i2<4;i2++)
{
is >> m[i][i2];
}
}
return is;
}
Matrix4 operator * (const Matrix4 &Left, const Matrix4 &Right)
{
Matrix4 Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
float Total = 0.0f;
for(UINT i3 = 0; i3 < 4; i3++)
{
Total += Left[i][i3] * Right[i3][i2];
}
Result[i][i2] = Total;
}
}
return Result;
}
Matrix4 operator * (const Matrix4 &Left, float &Right)
{
Matrix4 Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result[i][i2] = Left[i][i2] * Right;
}
}
return Result;
}
Matrix4 operator * (float &Left, const Matrix4 &Right)
{
Matrix4 Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result[i][i2] = Right[i][i2] * Left;
}
}
return Result;
}
Matrix4 operator + (const Matrix4 &Left, const Matrix4 &Right)
{
Matrix4 Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result[i][i2] = Left[i][i2] + Right[i][i2];
}
}
return Result;
}
Matrix4 operator - (const Matrix4 &Left, const Matrix4 &Right)
{
Matrix4 Result;
for(UINT i = 0; i < 4; i++)
{
for(UINT i2 = 0; i2 < 4; i2++)
{
Result[i][i2] = Left[i][i2] - Right[i][i2];
}
}
return Result;
}