Математическая библиотека


struct matrix4x4
{
	float Mat[4][4];
};

typedef float matrix4x4[4][4];	

struct vector3
{
	float x,y,z;

	vector3 operator - (const vector3 &VecIn)
	{
		vector3 VecOut;
		
		VecOut.x = x - VecIn.x;
		VecOut.y = y - VecIn.y;
		VecOut.z = z - VecIn.z;
		
		return VecOut;
	}

};

matrix4x4 Mat4x4_Mat4x4_Mul(matrix4x4 &MatIn1, matrix4x4 &MatIn2);
vector3 Vec3_Mat4x4_Mul(vector3 &VecIn, matrix4x4 MatIn);
float Vec3_Dot(vector3 &VecIn1, vector3 &VecIn2);
vector3 Vec3_Cross(vector3 &VecIn1, vector3 &VecIn2);
vector3 Vec3_Normalize(vector3 &VecIn);
vector3 Vec3_Scale(vector3 &VecIn, float &ValIn);
vector3 Vec3_Add(vector3 &VecIn1, vector3 &VecIn2);
float Vec3_Len(vector3 &VecIn);
vector3 Vec3_Reflect(vector3 &VecIn, vector3 &VecNorm);
void Matrix_Rotation_Axis(vector3 &VecIn, float Angle, matrix4x4 *MatIn);

matrix4x4 CMeshManager::Mat4x4_Mat4x4_Mul(matrix4x4 &MatIn1, matrix4x4 &MatIn2)
{
	matrix4x4 MatOut;

	//row1 * col1
	MatOut.Mat[0][0] = MatIn1.Mat[0][0]*MatIn2.Mat[0][0] + MatIn1.Mat[0][1]*MatIn2.Mat[1][0] + MatIn1.Mat[0][2]*MatIn2.Mat[2][0] + MatIn1.Mat[0][3]*MatIn2.Mat[3][0];
	//row1 * col2
	MatOut.Mat[0][1] = MatIn1.Mat[0][0]*MatIn2.Mat[0][1] + MatIn1.Mat[0][1]*MatIn2.Mat[1][1] + MatIn1.Mat[0][2]*MatIn2.Mat[2][1] + MatIn1.Mat[0][3]*MatIn2.Mat[3][1];
	//row1 * col3
	MatOut.Mat[0][2] = MatIn1.Mat[0][0]*MatIn2.Mat[0][2] + MatIn1.Mat[0][1]*MatIn2.Mat[1][2] + MatIn1.Mat[0][2]*MatIn2.Mat[2][2] + MatIn1.Mat[0][3]*MatIn2.Mat[3][2];
	//row1 * col4
	MatOut.Mat[0][3] = MatIn1.Mat[0][0]*MatIn2.Mat[0][3] + MatIn1.Mat[0][1]*MatIn2.Mat[1][3] + MatIn1.Mat[0][2]*MatIn2.Mat[2][3] + MatIn1.Mat[0][3]*MatIn2.Mat[3][3];

	//row2 * col1
	MatOut.Mat[1][0] = MatIn1.Mat[1][0]*MatIn2.Mat[0][0] + MatIn1.Mat[1][1]*MatIn2.Mat[1][0] + MatIn1.Mat[1][2]*MatIn2.Mat[2][0] + MatIn1.Mat[1][3]*MatIn2.Mat[3][0];
	//row2 * col2
	MatOut.Mat[1][1] = MatIn1.Mat[1][0]*MatIn2.Mat[0][1] + MatIn1.Mat[1][1]*MatIn2.Mat[1][1] + MatIn1.Mat[1][2]*MatIn2.Mat[2][1] + MatIn1.Mat[1][3]*MatIn2.Mat[3][1];
	//row2 * col3
	MatOut.Mat[1][2] = MatIn1.Mat[1][0]*MatIn2.Mat[0][2] + MatIn1.Mat[1][1]*MatIn2.Mat[1][2] + MatIn1.Mat[1][2]*MatIn2.Mat[2][2] + MatIn1.Mat[1][3]*MatIn2.Mat[3][2];
	//row2 * col4
	MatOut.Mat[1][3] = MatIn1.Mat[1][0]*MatIn2.Mat[0][3] + MatIn1.Mat[1][1]*MatIn2.Mat[1][3] + MatIn1.Mat[1][2]*MatIn2.Mat[2][3] + MatIn1.Mat[1][3]*MatIn2.Mat[3][3];

	//row3 * col1
	MatOut.Mat[2][0] = MatIn1.Mat[2][0]*MatIn2.Mat[0][0] + MatIn1.Mat[2][1]*MatIn2.Mat[1][0] + MatIn1.Mat[2][2]*MatIn2.Mat[2][0] + MatIn1.Mat[2][3]*MatIn2.Mat[3][0];
	//row3 * col2
	MatOut.Mat[2][1] = MatIn1.Mat[2][0]*MatIn2.Mat[0][1] + MatIn1.Mat[2][1]*MatIn2.Mat[1][1] + MatIn1.Mat[2][2]*MatIn2.Mat[2][1] + MatIn1.Mat[2][3]*MatIn2.Mat[3][1];
	//row3 * col3
	MatOut.Mat[2][2] = MatIn1.Mat[2][0]*MatIn2.Mat[0][2] + MatIn1.Mat[2][1]*MatIn2.Mat[1][2] + MatIn1.Mat[2][2]*MatIn2.Mat[2][2] + MatIn1.Mat[2][3]*MatIn2.Mat[3][2];
	//row3 * col4
	MatOut.Mat[2][3] = MatIn1.Mat[2][0]*MatIn2.Mat[0][3] + MatIn1.Mat[2][1]*MatIn2.Mat[1][3] + MatIn1.Mat[2][2]*MatIn2.Mat[2][3] + MatIn1.Mat[2][3]*MatIn2.Mat[3][3];

	//row4 * col1
	MatOut.Mat[3][0] = MatIn1.Mat[3][0]*MatIn2.Mat[0][0] + MatIn1.Mat[3][1]*MatIn2.Mat[1][0] + MatIn1.Mat[3][2]*MatIn2.Mat[2][0] + MatIn1.Mat[3][3]*MatIn2.Mat[3][0];
	//row4 * col2
	MatOut.Mat[3][1] = MatIn1.Mat[3][0]*MatIn2.Mat[0][1] + MatIn1.Mat[3][1]*MatIn2.Mat[1][1] + MatIn1.Mat[3][2]*MatIn2.Mat[2][1] + MatIn1.Mat[3][3]*MatIn2.Mat[3][1];
	//row4 * col3
	MatOut.Mat[3][2] = MatIn1.Mat[3][0]*MatIn2.Mat[0][2] + MatIn1.Mat[3][1]*MatIn2.Mat[1][2] + MatIn1.Mat[3][2]*MatIn2.Mat[2][2] + MatIn1.Mat[3][3]*MatIn2.Mat[3][2];
	//row4 * col4
	MatOut.Mat[3][3] = MatIn1.Mat[3][0]*MatIn2.Mat[0][3] + MatIn1.Mat[3][1]*MatIn2.Mat[1][3] + MatIn1.Mat[3][2]*MatIn2.Mat[2][3] + MatIn1.Mat[3][3]*MatIn2.Mat[3][3];

	return MatOut;
}

vector3 CMeshManager::Vec3_Mat4x4_Mul(vector3 &VecIn, matrix4x4 MatIn)
{
	    vector3 VecOut;

		VecOut.x =	VecIn.x * MatIn.Mat[0][0] +
				VecIn.y * MatIn.Mat[1][0] + 
				VecIn.z * MatIn.Mat[2][0] + 
					  MatIn.Mat[3][0];
        
		VecOut.y =	VecIn.x * MatIn.Mat[0][1] + 
				VecIn.y * MatIn.Mat[1][1] + 
				VecIn.z * MatIn.Mat[2][1] + 
					  MatIn.Mat[3][1];
        
		VecOut.z =	VecIn.x * MatIn.Mat[0][2] + 
				VecIn.y * MatIn.Mat[1][2] + 
				VecIn.z * MatIn.Mat[2][2] + 
					  MatIn.Mat[3][2];

		return VecOut;
}

float CMeshManager::Vec3_Dot(vector3 &VecIn1, vector3 &VecIn2)
{
	return VecIn1.x*VecIn2.x + VecIn1.y*VecIn2.y + VecIn1.z* VecIn2.z;
}

vector3 CMeshManager::Vec3_Cross(vector3 &VecIn1, vector3 &VecIn2)
{
	vector3 VecOut;

	VecOut.x = VecIn1.y * VecIn2.z - VecIn1.z * VecIn2.y;
	VecOut.y = VecIn1.z * VecIn2.x - VecIn1.x * VecIn2.z;
	VecOut.z = VecIn1.x * VecIn2.y - VecIn1.y * VecIn2.x;

	return VecOut;
}

vector3 CMeshManager::Vec3_Normalize(vector3 &VecIn)
{
	vector3 VecOut;

	float Len = sqrtf(VecIn.x * VecIn.x + VecIn.y * VecIn.y + VecIn.z * VecIn.z);

	VecOut.x = VecIn.x / Len;
	VecOut.y = VecIn.y / Len;
	VecOut.z = VecIn.z / Len;
	
	return VecOut;

}

vector3 CMeshManager::Vec3_Scale(vector3 &VecIn, float &ValIn)
{
	vector3 VecOut;

	VecOut.x = VecIn.x * ValIn;
	VecOut.y = VecIn.y * ValIn;
	VecOut.z = VecIn.z * ValIn;

	return VecOut;
}

vector3 CMeshManager::Vec3_Add(vector3 &VecIn1, vector3 &VecIn2)
{
	vector3 VecOut;

	VecOut.x = VecIn1.x + VecIn2.x;
	VecOut.y = VecIn1.y + VecIn2.y;
	VecOut.z = VecIn1.z + VecIn2.z;

	return VecOut;
}

float CMeshManager::Vec3_Len(vector3 &VecIn)
{
	return sqrtf(VecIn.x * VecIn.x + VecIn.y * VecIn.y + VecIn.z * VecIn.z);
}

vector3 CMeshManager::Vec3_Reflect(vector3 &VecIn, vector3 &VecNorm)
{
	vector3 VecOut;

	//float s = 2.0f * ( VecIn.x * VecNorm.x + VecIn.y * VecNorm.y + VecIn.z * VecNorm.z );
	float s = 2.0f * Vec3_Dot(VecIn, VecNorm);

	VecOut.x = VecIn.x - s * VecNorm.x;
	VecOut.y = VecIn.y - s * VecNorm.y;
	VecOut.z = VecIn.z - s * VecNorm.z;

	return VecOut;
}


void CMeshManager::Matrix_Rotation_Axis(vector3 &VecIn, float Angle, matrix4x4 *MatOut)
{
		float x = VecIn.x;
		float y = VecIn.y;
		float z = VecIn.z;
	
		float s = sin(Angle);
		float c = cos(Angle);
		float omc = 1.0f - c;

		float xomc = x * omc;
		float yomc = y * omc;
		float zomc = z * omc;

		float xxomc = x * xomc;
		float xyomc = x * yomc;
		float xzomc = x * zomc;
		
		float yyomc = y * yomc;
		float yzomc = y * zomc;
		float zzomc = z * zomc;

		float xs = x * s;
		float ys = y * s;
		float zs = z * s;

		matrix4x4 MatRotate= {xxomc + c,  xyomc + zs, xzomc - ys, 0.0f,
			xyomc - zs, yyomc + c,  yzomc + xs, 0.0f,
			xzomc + ys, yzomc - xs, zzomc + c, 0.0f,
			0.0f ,0.0f, 0.0f, 1.0f};

		memcpy(MatOut, &MatRotate, sizeof(matrix4x4));
}



Матрица вида и проекции, экранная матрица

Тут логика простая, сначала нужно подготовить входящие данные, что бы заполнить нужную матрицу. Когда мы подготовили данные, и потом заполнили этими данными матрицу- то каждую вершину модели мы будем умножать на эту матрицу. Как уже говорилось у куба 8м вершин в нашем примере, каждую из 8ми вершин куба мы будем умножать на матрицу, и это сводится к простому умножению вектора x,y,z на матрицу 4х4.

Матрица Вида


	typedef float matrix4x4[4][4];

	vertex3 vRight = { 1.0, 0.0, 0.0 };
	vertex3 vUp = { 0.0, 1.0, 0.0 };
	vertex3 vPos = { 0.0, 0.0, -40.0 };
	vertex3 vLook = { -1.0 * vPos.x, -1.0 * vPos.y, -1.0 * vPos.z };
	//vertex3 vLook = { 0.0, 0.0, 1.0 };
	vLook = Vec3Normalize(vLook);

	vUp = Vec3Cross(vLook, vRight);
	vUp = Vec3Normalize(vUp);
	vRight = Vec3Cross(vUp, vLook);
	vRight = Vec3Normalize(vRight);

	float xp = - Vec3Dot(vPos, vRight);
	float yp = - Vec3Dot(vPos, vUp);
	float zp = - Vec3Dot(vPos, vLook);

	matrix4x4 mView = {
	vRight.x,	vUp.x,	vLook.x,	0.0,
	vRight.y,       vUp.y,  vLook.y,        0.0,
	vRight.z,       vUp.z,  vLook.z,        0.0,
	xp,		yp,	zp,		1.0 };	

Матрица Проекции


	typedef float matrix4x4[4][4];

	float fFov = 3.14f/2.0f; // FOV 90 degree
	float fAspect = 640.0/480.0;
	float fZFar = 100.0f;
	float fZNear = 1.0f;

	float    h, w, Q;
	w = (float)(1/tan(fFov*0.5f))/fAspect;
	h = (float)1/tan(fFov*0.5f);
	Q = fZFar/(fZFar - fZNear);

    	matrix4x4 mProj={
	w, 0, 0, 0,
	0, h, 0, 0,
	0, 0, Q, 1,
	0, 0, -Q*fZNear, 0      };

Экранная матрица- еще один способ преобразования в экранные координаты.


	float alpha = (0.5f*nViewWidth-0.5f);
	float beta  = (0.5f*nViewHeight-0.5f);
	
	matrix4x4 mScreen(
			alpha,  0,      0,    0, 
			0,      -beta,  0,    0, 
			0,	0,	1,    0,
			alpha,  beta,	0,    1);

	v0 = mScreen * v0;
	v1 = mScreen * v1;
	v2 = mScreen * v2;