📄 matrix.h
字号:
// Matrix class
#pragma once
#include "Vector.h"
namespace Mathematics
{
/// 4x4 matrix class.
/// The convention here is post-multiplication by a column vector.
/// ie. x = Ab, where x and b are column vectors.
/// Please note that in cases where a matrix is pre-multiplied by a
/// vector, we then assume that the vector is a row vector.
/// This operation is then equivalent to post multiplying the vector
/// treated as a column vector by the transpose of the actual matrix.
/// If you wish to think of this matrix in terms of basis vectors,
/// then by convention, the rows of this matrix form the set of
/// basis vectors.
/// When composing matrix transforms A * B * C * D, note that the
/// actual order of operations as visible in the resultant matrix
/// is D, C, B, A. Alternatively, you can view transforms as changing
/// coordinate system, then the coordinate systems are changed
/// in order A, B, C, D.
class Matrix
{
public:
/// default constructor.
/// does nothing for speed.
Matrix() {};
/// construct a matrix from three basis vectors.
/// the x,y,z values from each of these basis vectors map to rows in the 3x3 sub matrix.
/// note: the rest of the matrix (row 4 and column 4 are set to identity)
Matrix(const Vector &a, const Vector &b, const Vector &c)
{
// ax ay az 0
// bx by bz 0
// cx cy cz 0
// 0 0 0 1
m11 = a.x;
m12 = a.y;
m13 = a.z;
m14 = 0;
m21 = b.x;
m22 = b.y;
m23 = b.z;
m24 = 0;
m31 = c.x;
m32 = c.y;
m33 = c.z;
m34 = 0;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// construct a matrix from explicit values for the 3x3 sub matrix.
/// note: the rest of the matrix (row 4 and column 4 are set to identity)
Matrix(float m11, float m12, float m13,
float m21, float m22, float m23,
float m31, float m32, float m33)
{
this->m11 = m11;
this->m12 = m12;
this->m13 = m13;
this->m14 = 0;
this->m21 = m21;
this->m22 = m22;
this->m23 = m23;
this->m24 = 0;
this->m31 = m31;
this->m32 = m32;
this->m33 = m33;
this->m34 = 0;
this->m41 = 0;
this->m42 = 0;
this->m43 = 0;
this->m44 = 1;
}
/// construct a matrix from explicit entry values for the whole 4x4 matrix.
Matrix(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)
{
this->m11 = m11;
this->m12 = m12;
this->m13 = m13;
this->m14 = m14;
this->m21 = m21;
this->m22 = m22;
this->m23 = m23;
this->m24 = m24;
this->m31 = m31;
this->m32 = m32;
this->m33 = m33;
this->m34 = m34;
this->m41 = m41;
this->m42 = m42;
this->m43 = m43;
this->m44 = m44;
}
/// load matrix from raw float array.
/// data is assumed to be stored linearly in memory in row order, from left to right, top to bottom.
Matrix(const float data[])
{
this->m11 = data[0];
this->m12 = data[1];
this->m13 = data[2];
this->m14 = data[3];
this->m21 = data[4];
this->m22 = data[5];
this->m23 = data[6];
this->m24 = data[7];
this->m31 = data[8];
this->m32 = data[9];
this->m33 = data[10];
this->m34 = data[11];
this->m41 = data[12];
this->m42 = data[13];
this->m43 = data[14];
this->m44 = data[15];
}
/// set all entries in matrix to identity.
void zero()
{
m11 = 0;
m12 = 0;
m13 = 0;
m14 = 0;
m21 = 0;
m22 = 0;
m23 = 0;
m24 = 0;
m31 = 0;
m32 = 0;
m33 = 0;
m34 = 0;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 0;
}
/// set matrix to identity.
void identity()
{
m11 = 1;
m12 = 0;
m13 = 0;
m14 = 0;
m21 = 0;
m22 = 1;
m23 = 0;
m24 = 0;
m31 = 0;
m32 = 0;
m33 = 1;
m34 = 0;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// set to a translation matrix.
void translate(float x, float y, float z)
{
m11 = 1; // 1 0 0 x
m12 = 0; // 0 1 0 y
m13 = 0; // 0 0 1 z
m14 = x; // 0 0 0 1
m21 = 0;
m22 = 1;
m23 = 0;
m24 = y;
m31 = 0;
m32 = 0;
m33 = 1;
m34 = z;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// set to a translation matrix.
void translate(const Vector &vector)
{
m11 = 1; // 1 0 0 x
m12 = 0; // 0 1 0 y
m13 = 0; // 0 0 1 z
m14 = vector.x; // 0 0 0 1
m21 = 0;
m22 = 1;
m23 = 0;
m24 = vector.y;
m31 = 0;
m32 = 0;
m33 = 1;
m34 = vector.z;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// set to a scale matrix.
void scale(float s)
{
m11 = s;
m12 = 0;
m13 = 0;
m14 = 0;
m21 = 0;
m22 = s;
m23 = 0;
m24 = 0;
m31 = 0;
m32 = 0;
m33 = s;
m34 = 0;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// set to a diagonal matrix.
void diagonal(float a, float b, float c, float d = 1)
{
m11 = a;
m12 = 0;
m13 = 0;
m14 = 0;
m21 = 0;
m22 = b;
m23 = 0;
m24 = 0;
m31 = 0;
m32 = 0;
m33 = c;
m34 = 0;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = d;
}
/// set matrix to a rotation around the specified axis.
void rotate(float angle, const Vector &axis)
{
assert(axis.normalized());
float sine = Float::sin(angle);
float cosine = Float::cos(angle);
float oneMinusCosine = 1.0f - cosine;
float xx = axis.x*axis.x;
float yy = axis.y*axis.y;
float zz = axis.z*axis.z;
float xym = axis.x*axis.y*oneMinusCosine;
float xzm = axis.x*axis.z*oneMinusCosine;
float yzm = axis.y*axis.z*oneMinusCosine;
float xSine = axis.x*sine;
float ySine = axis.y*sine;
float zSine = axis.z*sine;
m11 = xx*oneMinusCosine + cosine;
m12 = xym - zSine;
m13 = xzm + ySine;
m14 = 0;
m21 = xym + zSine;
m22 = yy*oneMinusCosine + cosine;
m23 = yzm - xSine;
m24 = 0;
m31 = xzm - ySine;
m32 = yzm + xSine;
m33 = zz*oneMinusCosine + cosine;
m34 = 0;
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// set to a look at matrix.
/// left handed.
void lookat(Vector eye, Vector at, Vector up)
{
Vector z_axis = at - eye;
Vector x_axis = up.cross(z_axis);
Vector y_axis = z_axis.cross(x_axis);
x_axis.normalize();
y_axis.normalize();
z_axis.normalize();
m11 = x_axis.x;
m12 = x_axis.y;
m13 = x_axis.z;
m14 = - x_axis.dot(eye);
m21 = y_axis.x;
m22 = y_axis.y;
m23 = y_axis.z;
m24 = - y_axis.dot(eye);
m31 = z_axis.x;
m32 = z_axis.y;
m33 = z_axis.z;
m34 = - z_axis.dot(eye);
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// set to an orthographic projection matrix.
/// Left handed Direct3D style.
void orthographic(float l, float r, float b, float t, float n, float f)
{
// | 2/(r-l) 0 0 0 |
// | 0 2/(t-b) 0 0 |
// | 0 0 1/(zf-zn) 0 |
// | (l+r)/(l-r) (t+b)/(b-t) zn/(zn-zf) 1 |
m11 = 2 / (r-l);
m12 = 0;
m13 = 0;
m14 = (l+r) / (l-r);
m21 = 0;
m22 = 2 / (t-b);
m23 = 0;
m24 = (t+b) / (b-t);
m31 = 0;
m32 = 0;
m33 = 1 / (f-n);
m34 = n / (n-f);
m41 = 0;
m42 = 0;
m43 = 0;
m44 = 1;
}
/// set to an orthographic projection matrix.
/// Direct3D style.
void orthographic(float width, float height, float n, float f)
{
orthographic(0, width, 0, height, n, f);
}
/// set to a perspective projection matrix.
/// Left handed Direct3D style.
void perspective(float l, float r, float b, float t, float n, float f)
{
// | 2*zn/(r-l) 0 0 0 |
// | 0 2*zn/(t-b) 0 0 |
// | (l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1 |
// | 0 0 zn*zf/(zn-zf) 0 |
m11 = 2*n / (r-l);
m12 = 0;
m13 = (l+r)/(l-r);
m14 = 0;
m21 = 0;
m22 = 2*n / (t-b);
m23 = (t+b)/(b-t);
m24 = 0;
m31 = 0;
m32 = 0;
m33 = f / (f-n);
m34 = n*f / (n-f);
m41 = 0;
m42 = 0;
m43 = 1;
m44 = 0;
}
/// set to a perspective projection matrix specified in terms of field of view and aspect ratio.
/// Sortof OpenGL gluPerspective style, but mapping through a Direct3D style projection matrix underneath.
void perspective(float fov, float aspect, float n, float f)
{
const float t = Float::tan(fov*0.5f) * n;
const float b = -t;
const float l = aspect * b;
const float r = aspect * t;
perspective(l,r,b,t,n,f);
}
/// calculate determinant of 3x3 sub matrix.
float determinant() const
{
return -m13*m22*m31 + m12*m23*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -