📄 matrix.h
字号:
extern CQuaternion Slerp(const CQuaternion &q1, const CQuaternion &q2, const float t);
/*******************************************************************************
* Class: CMatrix
********************************************************************************
* This class implements a 4x4 matrix. Several functions and operators are
* defined to make working with matrices easier. The values are kept in column-
* major order to make it easier to use with OpenGL. For performance reasons,
* most of the functions assume that all matrices are orthogonal, which means the
* bottom row is [ 0 0 0 1 ]. Since I plan to use the GL_PROJECTION matrix to
* handle the projection matrix, I should never need to use any other kind of
* matrix, and I get a decent performance boost by ignoring the bottom row.
*
* Note: This class is not templatized because integral data types don't make sense
* and there's no need for double-precision.
*******************************************************************************/
class CMatrix
{
public:
// This class uses column-major order, as used by OpenGL
// Here are the ways in which the matrix values can be accessed:
// | f11 f21 f31 f41 | | f1[0] f1[4] f1[8] f1[12] | | f2[0][0] f2[1][0] f2[2][0] f2[3][0] |
// | f12 f22 f32 f42 | | f1[1] f1[5] f1[9] f1[13] | | f2[0][1] f2[1][1] f2[2][1] f2[3][1] |
// | f13 f23 f33 f43 | = | f1[2] f1[6] f1[10] f1[14] | = | f2[0][2] f2[1][2] f2[2][2] f2[3][2] |
// | f14 f24 f34 f44 | | f1[3] f1[7] f1[11] f1[15] | | f2[0][3] f2[1][3] f2[2][3] f2[3][3] |
union
{
struct { float f11, f12, f13, f14, f21, f22, f23, f24, f31, f32, f33, f34, f41, f42, f43, f44; };
float f1[16];
float f2[4][4];
};
CMatrix() {}
CMatrix(const float f) { *this = f; }
CMatrix(const float *pf) { *this = pf; }
CMatrix(const CQuaternion &q) { *this = q; }
// Init functions
void ZeroMatrix()
{
f11 = f12 = f13 = f14 = f21 = f22 = f23 = f24 = f31 = f32 = f33 = f34 = f41 = f42 = f43 = f44 = 0;
}
void IdentityMatrix()
{
f12 = f13 = f14 = f21 = f23 = f24 = f31 = f32 = f34 = f41 = f42 = f43 = 0;
f11 = f22 = f33 = f44 = 1;
}
operator float*() { return f1; }
float &operator[](const int n) { return f1[n]; }
float &operator()(const int i, const int j) { return f2[i][j]; }
operator const float*() const { return f1; }
float operator[](const int n) const { return f1[n]; }
float operator()(const int i, const int j) const{ return f2[i][j]; }
void operator=(const float f) { for(register int i=0; i<16; i++) f1[i] = f; }
void operator=(const float *pf) { for(register int i=0; i<16; i++) f1[i] = pf[i]; }
void operator=(const CQuaternion &q);
CMatrix operator*(const CMatrix &m) const;
void operator*=(const CMatrix &m) { *this = *this * m; }
CVector operator*(const CVector &v) const { return TransformVector(v); }
CVector TransformVector(const CVector &v) const
{
// 9 muls, 9 adds
// | f11 f21 f31 f41 | | v.x | | f11*v.x+f21*v.y+f31*v.z+f41 |
// | f12 f22 f32 f42 | | v.y | | f12*v.x+f22*v.y+f32*v.z+f42 |
// | f13 f23 f33 f43 | * | v.z | = | f13*v.x+f23*v.y+f33*v.z+f43 |
// | 0 0 0 1 | | 1 | | 1 |
return CVector((f11*v.x+f21*v.y+f31*v.z+f41),
(f12*v.x+f22*v.y+f32*v.z+f42),
(f13*v.x+f23*v.y+f33*v.z+f43));
}
CVector TransformNormal(const CVector &v) const
{
// 9 muls, 6 adds
// (Transpose rotation vectors, ignore position)
// | f11 f12 f13 0 | | v.x | | f11*v.x+f12*v.y+f13*v.z |
// | f21 f22 f23 0 | | v.y | | f21*v.x+f22*v.y+f23*v.z |
// | f31 f32 f33 0 | * | v.z | = | f31*v.x+f32*v.y+f33*v.z |
// | 0 0 0 1 | | 1 | | 1 |
return CVector((f11*v.x+f12*v.y+f13*v.z),
(f21*v.x+f22*v.y+f23*v.z),
(f31*v.x+f32*v.y+f33*v.z));
}
// Translate functions
void TranslateMatrix(const float x, const float y, const float z)
{
// | 1 0 0 x |
// | 0 1 0 y |
// | 0 0 1 z |
// | 0 0 0 1 |
f12 = f13 = f14 = f21 = f23 = f24 = f31 = f32 = f34 = 0;
f11 = f22 = f33 = f44 = 1;
f41 = x; f42 = y; f43 = z;
}
void TranslateMatrix(const float *pf) { TranslateMatrix(pf[0], pf[1], pf[2]); }
void Translate(const float x, const float y, const float z)
{
// 9 muls, 9 adds
// | f11 f21 f31 f41 | | 1 0 0 x | | f11 f21 f31 f11*x+f21*y+f31*z+f41 |
// | f12 f22 f32 f42 | | 0 1 0 y | | f12 f22 f32 f12*x+f22*y+f32*z+f42 |
// | f13 f23 f33 f43 | * | 0 0 1 z | = | f13 f23 f33 f13*x+f23*y+f33*z+f43 |
// | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 |
f41 = f11*x+f21*y+f31*z+f41;
f42 = f12*x+f22*y+f32*z+f42;
f43 = f13*x+f23*y+f33*z+f43;
}
void Translate(const float *pf) { Translate(pf[0], pf[1], pf[2]); }
// Scale functions
void ScaleMatrix(const float x, const float y, const float z)
{
// | x 0 0 0 |
// | 0 y 0 0 |
// | 0 0 z 0 |
// | 0 0 0 1 |
f12 = f13 = f14 = f21 = f23 = f24 = f31 = f32 = f34 = f41 = f42 = f43 = 0;
f11 = x; f22 = y; f33 = z; f44 = 1;
}
void ScaleMatrix(const float *pf) { ScaleMatrix(pf[0], pf[1], pf[2]); }
void Scale(const float x, const float y, const float z)
{
// 9 muls
// | f11 f21 f31 f41 | | x 0 0 0 | | f11*x f21*y f31*z f41 |
// | f12 f22 f32 f42 | | 0 y 0 0 | | f12*x f22*y f32*z f42 |
// | f13 f23 f33 f43 | * | 0 0 z 0 | = | f13*x f23*y f33*z f43 |
// | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 |
f11 *= x; f21 *= y; f31 *= z;
f12 *= x; f22 *= y; f32 *= z;
f13 *= x; f23 *= y; f33 *= z;
}
void Scale(const float *pf) { Scale(pf[0], pf[1], pf[2]); }
// Rotate functions
void RotateXMatrix(const float fRadians)
{
// | 1 0 0 0 |
// | 0 fCos -fSin 0 |
// | 0 fSin fCos 0 |
// | 0 0 0 1 |
f12 = f13 = f14 = f21 = f24 = f31 = f34 = f41 = f42 = f43 = 0;
f11 = f44 = 1;
float fCos = cosf(fRadians);
float fSin = sinf(fRadians);
f22 = f33 = fCos;
f23 = fSin;
f32 = -fSin;
}
void RotateX(const float fRadians)
{
// 12 muls, 6 adds, 2 trig function calls
// | f11 f21 f31 f41 | | 1 0 0 0 | | f11 f21*fCos+f31*fSin f31*fCos-f21*fSin f41 |
// | f12 f22 f32 f42 | | 0 fCos -fSin 0 | | f12 f22*fCos+f32*fSin f32*fCos-f22*fSin f42 |
// | f13 f23 f33 f43 | * | 0 fSin fCos 0 | = | f13 f23*fCos+f33*fSin f33*fCos-f23*fSin f43 |
// | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 |
float fTemp, fCos, fSin;
fCos = cosf(fRadians);
fSin = sinf(fRadians);
fTemp = f21*fCos+f31*fSin;
f31 = f31*fCos-f21*fSin;
f21 = fTemp;
fTemp = f22*fCos+f32*fSin;
f32 = f32*fCos-f22*fSin;
f22 = fTemp;
fTemp = f23*fCos+f33*fSin;
f33 = f33*fCos-f23*fSin;
f23 = fTemp;
}
void RotateYMatrix(const float fRadians)
{
// | fCos 0 fSin 0 |
// | 0 1 0 0 |
// | -fSin 0 fCos 0 |
// | 0 0 0 1 |
f12 = f14 = f21 = f23 = f24 = f32 = f34 = f41 = f42 = f43 = 0;
f22 = f44 = 1;
float fCos = cosf(fRadians);
float fSin = sinf(fRadians);
f11 = f33 = fCos;
f13 = -fSin;
f31 = fSin;
}
void RotateY(const float fRadians)
{
// 12 muls, 6 adds, 2 trig function calls
// | f11 f21 f31 f41 | | fCos 0 fSin 0 | | f11*fCos-f31*fSin f21 f11*fSin+f31*fCos f41 |
// | f12 f22 f32 f42 | | 0 1 0 0 | | f12*fCos-f32*fSin f22 f12*fSin+f32*fCos f42 |
// | f13 f23 f33 f43 | * | -fSin 0 fCos 0 | = | f13*fCos-f33*fSin f23 f13*fSin+f33*fCos f43 |
// | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 |
float fTemp, fCos, fSin;
fCos = cosf(fRadians);
fSin = sinf(fRadians);
fTemp = f11*fCos-f31*fSin;
f31 = f11*fSin+f31*fCos;
f11 = fTemp;
fTemp = f12*fCos-f32*fSin;
f32 = f12*fSin+f32*fCos;
f12 = fTemp;
fTemp = f13*fCos-f33*fSin;
f33 = f13*fSin+f33*fCos;
f13 = fTemp;
}
void RotateZMatrix(const float fRadians)
{
// | fCos -fSin 0 0 |
// | fSin fCos 0 0 |
// | 0 0 1 0 |
// | 0 0 0 1 |
f13 = f14 = f23 = f24 = f31 = f32 = f34 = f41 = f42 = f43 = 0;
f33 = f44 = 1;
float fCos = cosf(fRadians);
float fSin = sinf(fRadians);
f11 = f22 = fCos;
f12 = fSin;
f21 = -fSin;
}
void RotateZ(const float fRadians)
{
// 12 muls, 6 adds, 2 trig function calls
// | f11 f21 f31 f41 | | fCos -fSin 0 0 | | f11*fCos+f21*fSin f21*fCos-f11*fSin f31 f41 |
// | f12 f22 f32 f42 | | fSin fCos 0 0 | | f12*fCos+f22*fSin f22*fCos-f12*fSin f32 f42 |
// | f13 f23 f33 f43 | * | 0 0 1 0 | = | f13*fCos+f23*fSin f23*fCos-f13*fSin f33 f43 |
// | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 |
float fTemp, fCos, fSin;
fCos = cosf(fRadians);
fSin = sinf(fRadians);
fTemp = f11*fCos+f21*fSin;
f21 = f21*fCos-f11*fSin;
f11 = fTemp;
fTemp = f12*fCos+f22*fSin;
f22 = f22*fCos-f12*fSin;
f12 = fTemp;
fTemp = f13*fCos+f23*fSin;
f23 = f23*fCos-f13*fSin;
f13 = fTemp;
}
void RotateMatrix(const CVector &v, const float f)
{
// 15 muls, 10 adds, 2 trig function calls
float fCos = cosf(f);
CVector vCos = v * (1 - fCos);
CVector vSin = v * sinf(f);
f14 = f24 = f34 = f41 = f42 = f43 = 0;
f44 = 1;
f11 = (v.x * vCos.x) + fCos;
f21 = (v.x * vCos.y) - (vSin.z);
f31 = (v.x * vCos.z) + (vSin.y);
f12 = (v.y * vCos.x) + (vSin.z);
f22 = (v.y * vCos.y) + fCos;
f32 = (v.y * vCos.z) - (vSin.x);
f13 = (v.z * vCos.x) - (vSin.y);
f32 = (v.z * vCos.y) + (vSin.x);
f33 = (v.z * vCos.z) + fCos;
}
void Rotate(const CVector &v, const float f)
{
// 51 muls, 37 adds, 2 trig function calls
CMatrix mat;
mat.RotateMatrix(v, f);
*this *= mat;
}
void ModelMatrix(const CQuaternion &q, const CVector &vFrom)
{
*this = q;
f41 = vFrom.x;
f42 = vFrom.y;
f43 = vFrom.z;
}
void ModelMatrix(const CVector &vFrom, const CVector &vView, const CVector &vUp, const CVector &vRight)
{
f11 = vRight.x; f21 = vUp.x; f31 = -vView.x; f41 = vFrom.x;
f12 = vRight.y; f22 = vUp.y; f32 = -vView.y; f42 = vFrom.y;
f13 = vRight.z; f23 = vUp.z; f33 = -vView.z; f43 = vFrom.z;
f14 = 0; f24 = 0; f34 = 0; f44 = 1;
}
void ModelMatrix(const CVector &vFrom, const CVector &vAt, const CVector &vUp)
{
CVector vView = vAt - vFrom;
vView.Normalize();
CVector vRight = vView ^ vUp;
vRight.Normalize();
CVector vTrueUp = vRight ^ vView;
vTrueUp.Normalize();
ModelMatrix(vFrom, vView, vTrueUp, vRight);
}
void ViewMatrix(const CQuaternion &q, const CVector &vFrom)
{
*this = q;
Transpose();
f41 = -(vFrom.x*f11 + vFrom.y*f21 + vFrom.z*f31);
f42 = -(vFrom.x*f12 + vFrom.y*f22 + vFrom.z*f32);
f43 = -(vFrom.x*f13 + vFrom.y*f23 + vFrom.z*f33);
}
void ViewMatrix(const CVector &vFrom, const CVector &vView, const CVector &vUp, const CVector &vRight)
{
// 9 muls, 9 adds
f11 = vRight.x; f21 = vRight.y; f31 = vRight.z; f41 = -(vFrom | vRight);
f12 = vUp.x; f22 = vUp.y; f32 = vUp.z; f42 = -(vFrom | vUp);
f13 = -vView.x; f23 = -vView.y; f33 = -vView.z; f43 = -(vFrom | -vView);
f14 = 0; f24 = 0; f34 = 0; f44 = 1;
}
void ViewMatrix(const CVector &vFrom, const CVector &vAt, const CVector &vUp)
{
CVector vView = vAt - vFrom;
vView.Normalize();
CVector vRight = vView ^ vUp;
vRight.Normalize();
CVector vTrueUp = vRight ^ vView;
vTrueUp.Normalize();
ViewMatrix(vFrom, vView, vTrueUp, vRight);
}
void ProjectionMatrix(const float fNear, const float fFar, const float fFOV, const float fAspect)
{
// 2 muls, 3 divs, 2 adds, 1 trig function call
float h = 1.0f / tanf(DEGTORAD(fFOV * 0.5f));
float Q = fFar / (fFar - fNear);
f12 = f13 = f14 = f21 = f23 = f24 = f31 = f32 = f41 = f42 = f44 = 0;
f11 = h / fAspect;
f22 = h;
f33 = Q;
f34 = 1;
f43 = -Q*fNear;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -