Для многих последующих уроков нам понадобится работа с матрицами, поэтому мы создадим отдельный класс CMatrix.
Но сначала давайте упорядочим и перепишем наш класс вектора.

Файл CVector.h

#ifndef __CVECTOR_H
#define __CVECTOR_H#include<math.h>// Введём новый класс для удобства хранения текстурных координат обьекта:
class CTexCoord
{
public:
CTexCoord()
{
tu = 0.0f; tv = 0.0f;
}

CTexCoord(float u, float v)
{
tu = u; tv = v;
}

float tu, tv;                      // Массив текстурных координат
};

class CVector4
{
public:
CVector4();                                        // Конструктор
CVector4(float X, float Y, float Z);               // Перегруженный конструктор
CVector4(float X, float Y, float Z, float W);      // Опять перегруженный конструктор
CVector4(const CVector4 &v);                       // И ещё один.

void operator=(CVector4 v);                        // Перегруженный оператор =
CVector4 operator(CVector4 v);                    // Перегруженный оператор —
CVector4 operator+(CVector4 v);                    // Перегруженный оператор +
CVector4 operator*(CVector4 v);                    // Перегруженный оператор *
CVector4 operator/(CVector4 v);                    // Перегруженный оператор /
CVector4 operator+(float f);                       // Перегруженный оператор +
CVector4 operator(float f);                       // Перегруженный оператор —
CVector4 operator*(float f);                       // Перегруженный оператор *
CVector4 operator/(float f);                       // Перегруженный оператор /

void operator +=(CVector4 v);                      // Перегруженный оператор +=
void operator -=(CVector4 v);                      // Перегруженный оператор -=
void operator *=(CVector4 v);                      // Перегруженный оператор *=
void operator /=(CVector4 v);                      // Перегруженный оператор /=
void operator +=(float f);                         // Перегруженный оператор +=
void operator -=(float f);                         // Перегруженный оператор -=
void operator *=(float f);                         // Перегруженный оператор *=
void operator /=(float f);                         // Перегруженный оператор /=

bool operator ==(CVector4 v);                      // Перегруженный оператор ==
bool operator !=(CVector4 v);                      // Перегруженный оператор !=

void CrossProduct(CVector4 v1, CVector4 v2);       // Возвращает Cross Product векторов v1 и v2.
void CrossProduct3(CVector4 v1, CVector4 v2,
CVector4 v3);                   // Возвращает Cross Product векторов v1, v2, v3.
float DotProduct3(CVector4 v1);                    // Скалярное произведение 3 от v1
float DotProduct4(CVector4 v1);                    // Скалярное произведение 4 от v1
float GetLength();                                 // Возвращает длинно данного обьекта
void Normal();                                     // Нормализует вектор
void Normalize(CVector4 Triangle[]);               // Находит нормаль треугольника
void CalculateTangentVector(CVector4 Point1,
CVector4 Point2,
CVector4 Point3,
CVector4 NormalOfA,
CTexCoord P1Tex,
CTexCoord P2Tex,
CTexCoord P3Tex);      // Вычисляет tagent вектор и сохраняет его
void ExtendVertexPos(CVector4 lightPos,            // Находит точку, основываясь на позиции источника
float Extend);                // света и текущей точки, сохраняет здесь.
void ExtendVertexPos(CVector4 currentVertex,       //
CVector4 lightPos,            //
float Extend);
CVector4 GetRotatedX(double angle);                // Вращение вокруг x.
CVector4 GetRotatedY(double angle);                // Вращение вокруг y.
CVector4 GetRotatedZ(double angle);                // Вращение вокруг z.
CVector4 GetRotatedAxis(double angle, CVector4 axis);  // Вращение вокруг произвольной оси.
void CalculateBinormalVector(CVector4 tangent,
CVector4 normal);     // Вычисляет бинормаль.
void ClampTo01();                                  // «закрепляет» этот вектор между 0 и 1.

float x, y, z, w;                                  // Вершинные x, y, и z координаты.
};

#endif

 

Его реализация в файле CVector.cpp:

#include»CVector.h»        // Класс CVector4.

#define PI_VALUE 3.141592654    // Значение PI

CVector4::CVector4()
{
// Инициализирует переменные значением 0.
x = y = z = 0.0;
}

CVector4::CVector4(float X, float Y, float Z)
{
// Инициализирует переменные значениями X, Y, и Z.
x = X;
y = Y;
z = Z;
}

CVector4::CVector4(float X, float Y, float Z, float W)
{
// Инициализирует переменные значениями X, Y, Z и W.
x = X;
y = Y;
z = Z;
w = W;
}

CVector4::CVector4(const CVector4 &v)
{
// Инициализирует обьект со значениями вектора «v».
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}

void CVector4::operator =(CVector4 v)
{
// Делает переменные x, y,z и w эквивалентными обьекту справа от знака «=».
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}

CVector4 CVector4::operator (CVector4 v)
{
// Возвращает значения этого вектора минус v.
return CVector4(x v.x, y v.y, z v.z);
}

CVector4 CVector4::operator +(CVector4 v)
{
// Возвращает значения этого вектора плюс v.
return CVector4(x + v.x, y + v.y, z + v.z);
}

CVector4 CVector4::operator *(CVector4 v)
{
// Возвращает значения этого вектора, умножить на v.
return CVector4(x * v.x, y * v.y, z * v.z);
}

CVector4 CVector4::operator /(CVector4 v)
{
// Возвращает значения этого вектора, разделить на v.
return CVector4(x / v.x, y / v.y, z / v.z);
}

CVector4 CVector4::operator +(float f)
{
// Возвращает значения этого вектора плюс f.
return CVector4(x + f, y + f, z + f);
}

CVector4 CVector4::operator (float f)
{
// Возвращает значения этого вектора минус f.
return CVector4(x f, y f, z f);
}

CVector4 CVector4::operator *(float f)
{
// Возвращает значения этого вектора умножить на f.
return CVector4(x * f, y * f, z * f);
}

CVector4 CVector4::operator /(float f)
{
// Возвращает значения этого вектора разделить на f.
// Вычисляем значение умножением на «1/f»
f = 1/f;

return CVector4(x * f, y * f, z * f);
}

void CVector4::operator +=(CVector4 v)
{
// Прибавляем к обьекту v и сохраняем результат
x += v.x;
y += v.y;
z += v.z;
}

void CVector4::operator -=(CVector4 v)
{
// Вычитаем из обьекта v и сохраняем результат
x -= v.x;
y -= v.y;
z -= v.z;
}

void CVector4::operator *=(CVector4 v)
{
// Умножам этот обьект на v и сохраняем результат
x *= v.x;
y *= v.y;
z *= v.z;
}

void CVector4::operator /=(CVector4 v)
{
// Делим этот обьект на v и сохраняем результат
x /= v.x;
y /= v.y;
z /= v.z;
}

void CVector4::operator +=(float f)
{
// Прибавляем к обьекту f и сохраняем результат
x += f;
y += f;
z += f;
}

void CVector4::operator -=(float f)
{
// Вычитаем из обьекта f и сохраняем результат
x -= f;
y -= f;
z -= f;
}

void CVector4::operator *=(float f)
{
// Умножаем обьект на f и сохраняем результат
x *= f;
y *= f;
z *= f;
}

void CVector4::operator /=(float f)
{
// Делим обьект на f, путём умножения на 1/f.
f = 1/f;

x *= f;
y *= f;
z *= f;
}

bool CVector4::operator ==(CVector4 v)
{
// Возвращает true если все значения равны друг другу.
return ((x == v.x) && (y== v.y) && (z == v.z));
}

bool CVector4::operator !=(CVector4 v)
{
// Возвращает true если значения не равны друг другу
return !((x == v.x) && (y== v.y) && (z == v.z));
}

void CVector4::CrossProduct(CVector4 v1, CVector4 v2)
{
// Получаем cross product от v1 и v2 и сохраняем здесь же.
x = ((v1.y * v2.z) (v1.z * v2.y));
y = ((v1.z * v2.x) (v1.x * v2.z));
z = ((v1.x * v2.y) (v1.y * v2.x));
}

void CVector4::CrossProduct3(CVector4 v1, CVector4 v2, CVector4 v3)
{
// Получаем cross product из v1, v2 и v3
x = v1.y * v2.z * v3.w +
v1.z * v2.w * v3.y +
v1.w * v2.y * v3.z
v1.y * v2.w * v3.z
v1.z * v2.y * v3.w
v1.w * v2.z * v3.y;

y = v1.x * v2.w * v3.z +
v1.z * v2.x * v3.w +
v1.w * v2.z * v3.x
v1.x * v2.z * v3.w
v1.z * v2.w * v3.x
v1.w * v2.x * v3.z;

z = v1.x * v2.y * v3.w +
v1.y * v2.w * v3.x +
v1.w * v2.x * v3.y
v1.x * v2.w * v3.y
v1.y * v2.x * v3.w
v1.w * v2.y * v3.x;

w = v1.x * v2.z * v3.y +
v1.y * v2.x * v3.z +
v1.z * v2.y * v3.x
v1.x * v2.y * v3.z
v1.y * v2.z * v3.x
v1.z * v2.x * v3.y;
}

float CVector4::DotProduct3(CVector4 v1)
{
// Получаем dot produce из v1 и этого обьекта и возвращаем результат
return x * v1.x + y * v1.y + z * v1.z;
}

float CVector4::DotProduct4(CVector4 v1)
{
// Получаем dot prodict из v1 и этого обьекта и возвращаем результат
return x * v1.x + y * v1.y + z * v1.z + w * v1.w;
}

float CVector4::GetLength()
{
// Возвращаем длинну этого обьекта
return (float)sqrt((x * x + y * y + z * z));
}

void CVector4::Normal()
{
// Уменьшаем длинну обьекта до единицы
float lenght = GetLength();

if(lenght == 0.0f)
lenght = 1.0f;

x = x/lenght;
y = y/lenght;
z = z/lenght;
w = w/lenght;
}

void CVector4::Normalize(CVector4 Triangle[])
{
// Нормализуем треугольник и сохраняем значения в этом обьекте
CVector4 v1, v2;

v1.x = Triangle[0].x Triangle[1].x;
v1.y = Triangle[0].y Triangle[1].y;
v1.z = Triangle[0].z Triangle[1].z;
v1.w = Triangle[0].w Triangle[1].w;

v2.x = Triangle[1].x Triangle[2].x;
v2.y = Triangle[1].y Triangle[2].y;
v2.z = Triangle[1].z Triangle[2].z;
v2.w = Triangle[1].w Triangle[2].w;

CrossProduct(v1, v2);
Normal();
}

void CVector4::CalculateTangentVector(CVector4 Point1, CVector4 Point2, CVector4 Point3,
CVector4 NormalOfA, CTexCoord P1Tex, CTexCoord P2Tex,
CTexCoord P3Tex)
{
//Получаем вектор между точками 1 и 2
CVector4 VectorAB = Point2 Point1;

// Получаем вектор между точками 1 и 3
CVector4 VectorAC = Point3 Point1;

// Вычисляем компоненты векторов к вершинным нормалям первой точки
CVector4 ProjAB = VectorAB (NormalOfA * NormalOfA.DotProduct4(VectorAB));
CVector4 ProjAC = VectorAC (NormalOfA * NormalOfA.DotProduct4(VectorAC));

// Вычисляем разницу tu точек 2 и 1, а затем 3 и 1
float TexCoorUAB = P2Tex.tu P1Tex.tu;
float TexCoorUAC = P3Tex.tu P1Tex.tu;

// Вычисляем разницу tv точек 2 и 1, а затем 3 и 1
float TexCoorVAB = P2Tex.tv P1Tex.tv;
float TexCoorVAC = P3Tex.tv P1Tex.tv;

if((TexCoorUAC * TexCoorVAB) > (TexCoorUAB * TexCoorVAC))
{
TexCoorUAC = TexCoorUAC;
TexCoorUAB = TexCoorUAB;
}

// Вычисляем tangent вектор, нормализуем его, затем возвращаем
CVector4 Tangent = (ProjAB * TexCoorUAC) (ProjAC * TexCoorUAB);
Tangent.Normal();

*this += Tangent;
}

void CVector4::ExtendVertexPos(CVector4 currentVertex, CVector4 lightPos, float Extend)
{
CVector4 lightDir;  // Направление света
CVector4 newPos;    // Новая расширенная позиция вершины для обьемных теней

// Получаем направление света из координат вершины и источника света
lightDir = currentVertex lightPos;

// Теперь, зная направление света, прибавляем его к позиции света для получения
// новой позиции. Умножаем его на переданное значение, чтобы придать обьему некоторую
// дистанцию, иначе будет выглядеть не слишком реалистично.
newPos = lightPos + lightDir * Extend;

x = newPos.x;
y = newPos.y;
z = newPos.z;
w = newPos.w;
}

void CVector4::ExtendVertexPos(CVector4 lightPos, float Extend)
{
CVector4 lightDir;  // Направление от источника света к позиции вершины
CVector4 newPos;    // Новая расширенная позиция вершины для обьемных теней

// Получаем направление света из координат вершины и источника света
lightDir = CVector4(x, y, z, w) lightPos;

// Теперь, зная направление света, прибавляем его к позиции света для получения
// новой позиции. Умножаем его на переданное значение, чтобы придать обьему некоторую
// дистанцию, иначе будет выглядеть не слишком реалистично.
newPos = lightPos + lightDir * Extend;

x = newPos.x;
y = newPos.y;
z = newPos.z;
w = newPos.w;
}

CVector4 CVector4::GetRotatedX(double angle)
{
float sinAngle = (float)sin(PI_VALUE * angle / 180);
float cosAngle = (float)cos(PI_VALUE * angle / 180);

return CVector4(x, y * cosAngle z * sinAngle, y * sinAngle + z * cosAngle, w);
}

CVector4 CVector4::GetRotatedY(double angle)
{
float sinAngle = (float)sin(PI_VALUE * angle / 180);
float cosAngle = (float)cos(PI_VALUE * angle / 180);

return CVector4(x * cosAngle + z * sinAngle, y, x * sinAngle + z * cosAngle, w);
}

CVector4 CVector4::GetRotatedZ(double angle)
{
float sinAngle = (float)sin(PI_VALUE * angle / 180);
float cosAngle = (float)cos(PI_VALUE * angle / 180);

return CVector4(x * cosAngle y * sinAngle, x * sinAngle + y * cosAngle, z, w);
}

CVector4 CVector4::GetRotatedAxis(double angle, CVector4 axis)
{
if(angle == 0.0) return(*this);

axis.Normal();

CVector4 RotationRow1, RotationRow2, RotationRow3;

double newAngle = PI_VALUE * angle / 180;
float sinAngle = (float)sin(newAngle);
float cosAngle = (float)cos(newAngle);
float oneSubCos = 1.0f cosAngle;

RotationRow1.x = (axis.x) * (axis.x) + cosAngle * (1 (axis.x) * (axis.x));
RotationRow1.y = (axis.x) * (axis.y) * (oneSubCos) sinAngle * axis.z;
RotationRow1.z = (axis.x) * (axis.z) * (oneSubCos) + sinAngle * axis.y;

RotationRow2.x = (axis.x) * (axis.y) * (oneSubCos) + sinAngle * axis.z;
RotationRow2.y = (axis.y) * (axis.y) + cosAngle * (1 (axis.y) * (axis.y));
RotationRow2.z = (axis.y) * (axis.z) * (oneSubCos) sinAngle * axis.x;

RotationRow3.x = (axis.x) * (axis.z) * (oneSubCos) sinAngle * axis.y;
RotationRow3.y = (axis.y) * (axis.z) * (oneSubCos) + sinAngle * axis.x;
RotationRow3.z = (axis.z) * (axis.z) + cosAngle * (1 (axis.z) * (axis.z));

return CVector4(this->DotProduct3(RotationRow1),
this->DotProduct3(RotationRow2),
this->DotProduct3(RotationRow3));
}

void CVector4::CalculateBinormalVector(CVector4 tangent, CVector4 normal)
{
this->CrossProduct(tangent, normal);
}

void CVector4::ClampTo01()
{
CVector4 temp(x, y, z, w);
temp.Normal();
temp = temp * 0.5f + CVector4(0.5f, 0.5f, 0.5f);

x = temp.x;
y = temp.y;
z = temp.z;
}

 

Возможно, вы немного запутались: добавлен некоторый новый функционал. Его назначение вы поймёте в
дальнейших уроках.

Теперь напишем новый класс для работы с матрицами.
Файл CMatrix.h:

#ifndef __CMATRIX_H
#define __CMATRIX_H
#include <string.h>
#include «CVector.h»class CMatrix4x4
{
public:
CMatrix4x4();                                // Конструктор.
CMatrix4x4(const CMatrix4x4 &m);             // Перегруженный конструктор.
CMatrix4x4(float r11, float r12, float r13, float r14,
float r21, float r22, float r23, float r24,
float r31, float r32, float r33, float r34,
float r41, float r42, float r43, float r44);
~CMatrix4x4();                               // Деструктор.void Clear();                                // Сброс матрицы.
void Zero();                                 // Сброс матрицы, все значения = 0.

void operator=(CMatrix4x4 m);                // Перегруженный оператор =
CMatrix4x4 operator(CMatrix4x4 m);          // Перегруженный оператор —
CMatrix4x4 operator+(CMatrix4x4 m);          // Перегруженный оператор +
CMatrix4x4 operator*(CMatrix4x4 m);          // Перегруженный оператор *
CMatrix4x4 operator/(CMatrix4x4 m);          // Перегруженный оператор /

void operator +=(CMatrix4x4 m);              // Перегруженный оператор +=
void operator -=(CMatrix4x4 m);              // Перегруженный оператор -=
void operator *=(CMatrix4x4 m);              // Перегруженный оператор *=
void operator /=(CMatrix4x4 m);              // Перегруженный оператор /=

CMatrix4x4 operator(float f);               // Перегруженный оператор —
CMatrix4x4 operator+(float f);               // Перегруженный оператор +
CMatrix4x4 operator*(float f);               // Перегруженный оператор *
CMatrix4x4 operator/(float f);               // Перегруженный оператор /

CVector4 operator *(CVector4 v);             // CVector4 * matrix (умножение вектора на матрицу)

void operator -=(float f);                   // Перегруженный оператор -=
void operator +=(float f);                   // Перегруженный оператор +=
void operator *=(float f);                   // Перегруженный оператор *=
void operator /=(float f);                   // Перегруженный оператор /=

bool operator ==(CMatrix4x4 v);              // Перегруженный оператор ==
bool operator !=(CMatrix4x4 v);              // Перегруженный оператор !=

void Translate(CVector4 Translate);          // Трансляция точки в 3D.
void Translate(float x, float y, float z);   // Трансляция точки в 3D.
void Rotate(double angle, int x, int y,
int z);                          // Вращение 3D точки.
bool inverseMatrix(CMatrix4x4 m);            // Инверсия текущих данных матрицы.
bool invertMatrix(CMatrix4x4 m);             // инвертирование матрицы.
CVector4 VectorMatrixMultiply(CVector4 v);
CVector4 VectorMatrixMultiply3x3(CVector4 v);
CVector4 transformPoint(CVector4 v);         // трансформация точки против матрицы.
bool CreateShadowMatrix(CVector4 planeNormal,
CVector4 lightPos);  // Создание матрицы теней.

float matrix[16];                            // 4×4 матрица в одномерном массиве.
};

#endif

 

Теперь опишем реализацию класса в файле CMatrix.cpp

#include»CMatrix.h»

CMatrix4x4::CMatrix4x4()
{
// Инициализируем все переменные
Clear();
}

CMatrix4x4::CMatrix4x4(const CMatrix4x4 &m)
{
matrix[0]  = m.matrix[0];
matrix[4]  = m.matrix[4];
matrix[8]  = m.matrix[8];
matrix[12] = m.matrix[12];

matrix[1]  = m.matrix[1];
matrix[5]  = m.matrix[5];
matrix[9]  = m.matrix[9];
matrix[13] = m.matrix[13];

matrix[2]  = m.matrix[2];
matrix[6]  = m.matrix[6];
matrix[10] = m.matrix[10];
matrix[14] = m.matrix[14];

matrix[3]  = m.matrix[3];
matrix[7]  = m.matrix[7];
matrix[11] = m.matrix[11];
matrix[15] = m.matrix[15];
}

CMatrix4x4::CMatrix4x4(float r11, float r12, float r13, float r14,
float r21, float r22, float r23, float r24,
float r31, float r32, float r33, float r34,
float r41, float r42, float r43, float r44)
{
// Чтобы тождественность матрицы, устанавливайте её значения примерно так…
matrix[0]  = r11; matrix[1]  = r12; matrix[2]  = r13; matrix[3]  = r14;
matrix[4]  = r21; matrix[5]  = r22; matrix[6]  = r23; matrix[7]  = r24;
matrix[8]  = r31; matrix[9]  = r32; matrix[10] = r33; matrix[11] = r34;
matrix[12] = r41; matrix[13] = r42; matrix[14] = r43; matrix[15] = r44;
}

CMatrix4x4::~CMatrix4x4()
{

}

void CMatrix4x4::operator =(CMatrix4x4 m)
{
// Устанавливает все значения матрицы в значения «m»
matrix[0]  = m.matrix[0]; matrix[1]   = m.matrix[1]; matrix[2]   = m.matrix[2];
matrix[3]  = m.matrix[3];
matrix[4]  = m.matrix[4]; matrix[5]   = m.matrix[5]; matrix[6]   = m.matrix[6];
matrix[7]  = m.matrix[7];
matrix[8]  = m.matrix[8]; matrix[9]   = m.matrix[9]; matrix[10]  = m.matrix[10];
matrix[11] = m.matrix[11];
matrix[12] = m.matrix[12]; matrix[13] = m.matrix[13]; matrix[14] = m.matrix[14];
matrix[15] = m.matrix[15];
}

CMatrix4x4 CMatrix4x4::operator (CMatrix4x4 m)
{
// Возвращает значение матрица — m
return CMatrix4x4(matrix[0] m.matrix[0], matrix[1] m.matrix[1], matrix[2] m.matrix[2],
matrix[3] m.matrix[3], matrix[4] m.matrix[4], matrix[5] m.matrix[5],
matrix[6] m.matrix[6], matrix[7] m.matrix[7], matrix[8] m.matrix[8],
matrix[9] m.matrix[9], matrix[10] m.matrix[10], matrix[11] m.matrix[11],
matrix[12] m.matrix[12], matrix[13] m.matrix[13],
matrix[14] m.matrix[14], matrix[15] m.matrix[15]);
}

CMatrix4x4 CMatrix4x4::operator +(CMatrix4x4 m)
{
// Возвращает значение матрица + m.
return CMatrix4x4(matrix[0] + m.matrix[0], matrix[1] + m.matrix[1], matrix[2] + m.matrix[2],
matrix[3] + m.matrix[3], matrix[4] + m.matrix[4], matrix[5] + m.matrix[5],
matrix[6] + m.matrix[6], matrix[7] + m.matrix[7], matrix[8] + m.matrix[8],
matrix[9] + m.matrix[9], matrix[10] + m.matrix[10], matrix[11] + m.matrix[11],
matrix[12] + m.matrix[12], matrix[13] + m.matrix[13],
matrix[14] + m.matrix[14], matrix[15] + m.matrix[15]);
}

CMatrix4x4 CMatrix4x4::operator *(CMatrix4x4 m)
{
// Возвращает значение матрица * m.
return CMatrix4x4(matrix[0] * m.matrix[0] + matrix[4] * m.matrix[1] + matrix[8] *
m.matrix[2] + matrix[12] * m.matrix[3],
matrix[1] * m.matrix[0] + matrix[5] * m.matrix[1] + matrix[9] *
m.matrix[2] + matrix[13] * m.matrix[3],
matrix[2] * m.matrix[0] + matrix[6] * m.matrix[1] + matrix[10] *
m.matrix[2] + matrix[14] * m.matrix[3],
matrix[3] * m.matrix[0] + matrix[7] * m.matrix[1] + matrix[11] *
m.matrix[2] + matrix[15] * m.matrix[3],
matrix[0] * m.matrix[4] + matrix[4] * m.matrix[5] + matrix[8] *
m.matrix[6] + matrix[12] * m.matrix[7],
matrix[1] * m.matrix[4] + matrix[5] * m.matrix[5] + matrix[9] *
m.matrix[6] + matrix[13] * m.matrix[7],
matrix[2] * m.matrix[4] + matrix[6] * m.matrix[5] + matrix[10] *
m.matrix[6] + matrix[14] * m.matrix[7],
matrix[3] * m.matrix[4] + matrix[7] * m.matrix[5] + matrix[11] *
m.matrix[6] + matrix[15] * m.matrix[7],
matrix[0] * m.matrix[8] + matrix[4] * m.matrix[9] + matrix[8] *
m.matrix[10] + matrix[12] * m.matrix[11],
matrix[1] * m.matrix[8] + matrix[5] * m.matrix[9] + matrix[9] *
m.matrix[10] + matrix[13] * m.matrix[11],
matrix[2] * m.matrix[8] + matrix[6] * m.matrix[9] + matrix[10] *
m.matrix[10] + matrix[14] * m.matrix[11],
matrix[3] * m.matrix[8] + matrix[7] * m.matrix[9] + matrix[11] *
m.matrix[10] + matrix[15] * m.matrix[11],
matrix[0] * m.matrix[12] + matrix[4] * m.matrix[13] + matrix[8] *
m.matrix[14] + matrix[12] * m.matrix[15],
matrix[1] * m.matrix[12] + matrix[5] * m.matrix[13] + matrix[9] *
m.matrix[14] + matrix[13] * m.matrix[15],
matrix[2] * m.matrix[12] + matrix[6] * m.matrix[13] + matrix[10] *
m.matrix[14] + matrix[14] * m.matrix[15],
matrix[3] * m.matrix[12] + matrix[7] * m.matrix[13] + matrix[11] *
m.matrix[14] + matrix[15] * m.matrix[15]);
}

CMatrix4x4 CMatrix4x4::operator /(CMatrix4x4 m)
{
return CMatrix4x4(matrix[0] / m.matrix[0] + matrix[4] / m.matrix[1] + matrix[8] /
m.matrix[2] + matrix[12] / m.matrix[3],
matrix[1] / m.matrix[0] + matrix[5] / m.matrix[1] + matrix[9] /
m.matrix[2] + matrix[13] / m.matrix[3],
matrix[2] / m.matrix[0] + matrix[6] / m.matrix[1] + matrix[10] /
m.matrix[2] + matrix[14] / m.matrix[3],
matrix[3] / m.matrix[0] + matrix[7] / m.matrix[1] + matrix[11] /
m.matrix[2] + matrix[15] / m.matrix[3],
matrix[0] / m.matrix[4] + matrix[4] / m.matrix[5] + matrix[8] /
m.matrix[6] + matrix[12] / m.matrix[7],
matrix[1] / m.matrix[4] + matrix[5] / m.matrix[5] + matrix[9] /
m.matrix[6] + matrix[13] / m.matrix[7],
matrix[2] / m.matrix[4] + matrix[6] / m.matrix[5] + matrix[10] /
m.matrix[6] + matrix[14] / m.matrix[7],
matrix[3] / m.matrix[4] + matrix[7] / m.matrix[5] + matrix[11] /
m.matrix[6] + matrix[15] / m.matrix[7],
matrix[0] / m.matrix[8] + matrix[4] / m.matrix[9] + matrix[8] /
m.matrix[10] + matrix[12] / m.matrix[11],
matrix[1] / m.matrix[8] + matrix[5] / m.matrix[9] + matrix[9] /
m.matrix[10] + matrix[13] / m.matrix[11],
matrix[2] / m.matrix[8] + matrix[6] / m.matrix[9] + matrix[10] /
m.matrix[10] + matrix[14] / m.matrix[11],
matrix[3] / m.matrix[8] + matrix[7] / m.matrix[9] + matrix[11] /
m.matrix[10] + matrix[15] / m.matrix[11],
matrix[0] / m.matrix[12] + matrix[4] / m.matrix[13] + matrix[8] /
m.matrix[14] + matrix[12] / m.matrix[15],
matrix[1] / m.matrix[12] + matrix[5] / m.matrix[13] + matrix[9] /
m.matrix[14] + matrix[13] / m.matrix[15],
matrix[2] / m.matrix[12] + matrix[6] / m.matrix[13] + matrix[10] /
m.matrix[14] + matrix[14] / m.matrix[15],
matrix[3] / m.matrix[12] + matrix[7] / m.matrix[13] + matrix[11] /
m.matrix[14] + matrix[15] / m.matrix[15]);
}

CMatrix4x4 CMatrix4x4::operator (float f)
{
return CMatrix4x4(matrix[0]   f, matrix[1]   f, matrix[2]   f, matrix[3]   f,
matrix[4]   f, matrix[5]   f, matrix[6]   f, matrix[7]   f,
matrix[8]   f, matrix[9]   f, matrix[10] f, matrix[11] f,
matrix[12] f, matrix[13] f, matrix[14] f, matrix[15] f);
}

CMatrix4x4 CMatrix4x4::operator +(float f)
{
return CMatrix4x4(matrix[0]  + f, matrix[1]  + f, matrix[2]  + f, matrix[3]  + f,
matrix[4]  + f, matrix[5]  + f, matrix[6]  + f, matrix[7]  + f,
matrix[8]  + f, matrix[9]  + f, matrix[10] + f, matrix[11] + f,
matrix[12] + f, matrix[13] + f, matrix[14] + f, matrix[15] + f);
}

CMatrix4x4 CMatrix4x4::operator *(float f)
{
return CMatrix4x4(matrix[0]  * f, matrix[1]  * f, matrix[2]  * f, matrix[3]  * f,
matrix[4]  * f, matrix[5]  * f, matrix[6]  * f, matrix[7]  * f,
matrix[8]  * f, matrix[9]  * f, matrix[10] * f, matrix[11] * f,
matrix[12] * f, matrix[13] * f, matrix[14] * f, matrix[15] * f);
}

CMatrix4x4 CMatrix4x4::operator /(float f)
{
// Возвращает значение этого вектора / f. Делаем это умножением на (1/f)
if(f == 0) f = 1;
f = 1/f;

return CMatrix4x4(matrix[0]  * f, matrix[1]  * f, matrix[2]  * f, matrix[3]  * f,
matrix[4]  * f, matrix[5]  * f, matrix[6]  * f, matrix[7]  * f,
matrix[8]  * f, matrix[9]  * f, matrix[10] * f, matrix[11] * f,
matrix[12] * f, matrix[13] * f, matrix[14] * f, matrix[15] * f);
}

bool CMatrix4x4::operator ==(CMatrix4x4 m)
{
// Возвращает true если все значения эквивалентны
for(int i = 0; i < 16; i++)
{
if(matrix[i] != m.matrix[i])
return false;
}

return true;
}

void CMatrix4x4::operator +=(CMatrix4x4 m)
{
(*this) = (*this) + m;
}

void CMatrix4x4::operator -=(CMatrix4x4 m)
{
(*this) = (*this) m;
}

void CMatrix4x4::operator *=(CMatrix4x4 m)
{
(*this) = (*this) * m;
}

void CMatrix4x4::operator /=(CMatrix4x4 m)
{
(*this) = (*this) / m;
}

bool CMatrix4x4::operator !=(CMatrix4x4 m)
{
return !((*this) == m);
}

void CMatrix4x4::operator -=(float f)
{
(*this) = (*this) f;
}

void CMatrix4x4::operator +=(float f)
{
(*this) = (*this) + f;
}

void CMatrix4x4::operator *=(float f)
{
(*this) = (*this) * f;
}

void CMatrix4x4::operator /=(float f)
{
// Делит этот обьект на f и сохраняет результат
(*this) = (*this) / f;
}

void CMatrix4x4::Clear()
{
matrix[0]  = 1.0f; matrix[1]  = 0.0f; matrix[2]  = 0.0f; matrix[3]  = 0.0f;
matrix[4]  = 0.0f; matrix[5]  = 1.0f; matrix[6]  = 0.0f; matrix[7]  = 0.0f;
matrix[8]  = 0.0f; matrix[9]  = 0.0f; matrix[10] = 1.0f; matrix[11] = 0.0f;
matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f;

// Если вы помните матрицы из школьного/институтского курса, вы заметите, что
// здесь диагональ: matrix[0], [5], [10], и [15]. Таким образом и сбрасывается матрица.
}

void CMatrix4x4::Zero()
{
// Чтобы установить значения матрицы в нули, делайте примерно так…
matrix[0]  = 0.0f; matrix[1]  = 0.0f; matrix[2]  = 0.0f; matrix[3]  = 0.0f;
matrix[4]  = 0.0f; matrix[5]  = 0.0f; matrix[6]  = 0.0f; matrix[7]  = 0.0f;
matrix[8]  = 0.0f; matrix[9]  = 0.0f; matrix[10] = 0.0f; matrix[11] = 0.0f;
matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 0.0f;
}

void CMatrix4x4::Translate(CVector4 Translate)
{
Clear();

// Чтобы транслировать матрицу 4×4, нужно переместить значения нижних рядов.
matrix[12] = Translate.x;
matrix[13] = Translate.y;
matrix[14] = Translate.z;
matrix[15] = 1.0f;
}

void CMatrix4x4::Translate(float x, float y, float z)
{
Clear();

matrix[12] = x;
matrix[13] = y;
matrix[14] = z;
matrix[15] = 1.0f;
}

void CMatrix4x4::Rotate(double angle, int x, int y, int z)
{
float sine = (float)sin(angle);
float cosine = (float)cos(angle);

if(x)
{
matrix[5] = cosine;
matrix[6] = sine;
matrix[9] = sine;
matrix[10] = cosine;
}

if(y)
{
matrix[0] = cosine;
matrix[2] = sine;
matrix[8] = sine;
matrix[10] = cosine;
}

if(z)
{
matrix[0] = cosine;
matrix[1] = sine;
matrix[4] = sine;
matrix[5] = cosine;
}
}

bool CMatrix4x4::inverseMatrix(CMatrix4x4 m)
{
float tempMatrix[16] = {0};
float d12, d13, d23, d24, d34, d41;

d12 = m.matrix[2]  * m.matrix[7]   m.matrix[3]  * m.matrix[6];
d13 = m.matrix[2]  * m.matrix[11] m.matrix[3]  * m.matrix[10];
d23 = m.matrix[6]  * m.matrix[11] m.matrix[7]  * m.matrix[10];
d24 = m.matrix[6]  * m.matrix[15] m.matrix[7]  * m.matrix[14];
d34 = m.matrix[10] * m.matrix[15] m.matrix[11] * m.matrix[14];
d41 = m.matrix[14] * m.matrix[3]   m.matrix[15] * m.matrix[2];

tempMatrix[0] =   m.matrix[5] * d34 m.matrix[9] * d24 + m.matrix[13] * d23;
tempMatrix[1] = (m.matrix[1] * d34 + m.matrix[9] * d41 + m.matrix[13] * d13);
tempMatrix[2] =   m.matrix[1] * d24 + m.matrix[5] * d41 + m.matrix[13] * d12;
tempMatrix[3] = (m.matrix[1] * d23 m.matrix[5] * d13 + m.matrix[9]  * d12);

// Вычисляем детерминант
float determinant = m.matrix[0] * tempMatrix[0] + m.matrix[4] * tempMatrix[1] +
m.matrix[8] * tempMatrix[2] + m.matrix[12] * tempMatrix[3];

// Очищаем, если детерминант равен нулю.
if(determinant == 0.0)
{
Clear();
return false;
}

float invDeterminant = 1.0f / determinant;

// Вычисляем инверсию
tempMatrix[0] *= invDeterminant;
tempMatrix[1] *= invDeterminant;
tempMatrix[2] *= invDeterminant;
tempMatrix[3] *= invDeterminant;

tempMatrix[4] = (m.matrix[4] * d34 m.matrix[8] * d24 + m.matrix[12] * d23) * invDeterminant;
tempMatrix[5] =   m.matrix[0] * d34 + m.matrix[8] * d41 + m.matrix[12] * d13  * invDeterminant;
tempMatrix[6] = (m.matrix[0] * d24 + m.matrix[4] * d41 + m.matrix[12] * d12) * invDeterminant;
tempMatrix[7] =   m.matrix[0] * d23 m.matrix[4] * d13 + m.matrix[8]  * d12  * invDeterminant;

// Пред-вычисляем 2х2 детерминанты для первых двух рядов
d12 = m.matrix[0]  * m.matrix[5]   m.matrix[1]  * m.matrix[12];
d13 = m.matrix[0]  * m.matrix[9]   m.matrix[1]  * m.matrix[8];
d23 = m.matrix[4]  * m.matrix[9]   m.matrix[5]  * m.matrix[8];
d24 = m.matrix[4]  * m.matrix[13] m.matrix[5]  * m.matrix[12];
d34 = m.matrix[8]  * m.matrix[13] m.matrix[9]  * m.matrix[12];
d41 = m.matrix[12] * m.matrix[1]   m.matrix[13] * m.matrix[0];

tempMatrix[8]  =   m.matrix[7] * d34 m.matrix[11] * d24 + m.matrix[15] * d23 * invDeterminant;
tempMatrix[9]  = (m.matrix[3] * d34 + m.matrix[11] * d41 + m.matrix[15] * d13) * invDeterminant;
tempMatrix[10] =   m.matrix[3] * d24 + m.matrix[7]  * d41 + m.matrix[15] * d12 * invDeterminant;
tempMatrix[11] = (m.matrix[3] * d23 m.matrix[7]  * d13 + m.matrix[11] * d12) * invDeterminant;
tempMatrix[12] = (m.matrix[6] * d34 m.matrix[10] * d24 + m.matrix[14] * d23) * invDeterminant;
tempMatrix[13] =   m.matrix[2] * d34 + m.matrix[10] * d41 + m.matrix[14] * d13 * invDeterminant;
tempMatrix[14] = (m.matrix[2] * d24 + m.matrix[6]  * d41 + m.matrix[14] * d12) * invDeterminant;
tempMatrix[15] =   m.matrix[2] * d23 m.matrix[6]  * d13 + m.matrix[10] * d12 * invDeterminant;

// Сохраняем временную матрицу в нашу матрицу
matrix[0]  = tempMatrix[0];  matrix[1]  = tempMatrix[1];
matrix[2]  = tempMatrix[2];  matrix[3]  = tempMatrix[3];
matrix[4]  = tempMatrix[4];  matrix[5]  = tempMatrix[5];
matrix[6]  = tempMatrix[6];  matrix[7]  = tempMatrix[7];
matrix[8]  = tempMatrix[8];  matrix[9]  = tempMatrix[9];
matrix[10] = tempMatrix[10]; matrix[11] = tempMatrix[11];
matrix[12] = tempMatrix[12]; matrix[13] = tempMatrix[13];
matrix[14] = tempMatrix[14]; matrix[15] = tempMatrix[15];

return true;
}

bool CMatrix4x4::invertMatrix(CMatrix4x4 m)
{
matrix[ 0] = m.matrix[ 0];  matrix[ 1] = m.matrix[ 4];  matrix[ 2] = m.matrix[ 8];
matrix[ 4] = m.matrix[ 1];  matrix[ 5] = m.matrix[ 5];  matrix[ 6] = m.matrix[ 9];
matrix[ 8] = m.matrix[ 2];  matrix[ 9] = m.matrix[ 6];  matrix[10] = m.matrix[10];

// Очищаем
matrix[3] = 0.0f; matrix[7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;

// Трансляция — это разница между скалярным произведением вращения и вращением
matrix[12] = (m.matrix[12]*m.matrix[0]) (m.matrix[13]*m.matrix[1]) (m.matrix[14]*m.matrix[ 2]);
matrix[13] = (m.matrix[12]*m.matrix[4]) (m.matrix[13]*m.matrix[5]) (m.matrix[14]*m.matrix[ 6]);
matrix[14] = (m.matrix[12]*m.matrix[8]) (m.matrix[13]*m.matrix[9]) (m.matrix[14]*m.matrix[10]);
return true;
}

CVector4 CMatrix4x4::VectorMatrixMultiply(CVector4 v)
{
CVector4 out;

out.x = (v.x * matrix[0]) + (v.y * matrix[4]) + (v.z * matrix[8]) + matrix[12];
out.y = (v.x * matrix[1]) + (v.y * matrix[5]) + (v.z * matrix[9]) + matrix[13];
out.z = (v.x * matrix[2]) + (v.y * matrix[6]) + (v.z * matrix[10]) + matrix[14];

return out;
}

CVector4 CMatrix4x4::VectorMatrixMultiply3x3(CVector4 v)
{
CVector4 out;

out.x = (v.x * matrix[0]) + (v.y * matrix[4]) + (v.z * matrix[8]);
out.y = (v.x * matrix[1]) + (v.y * matrix[5]) + (v.z * matrix[9]);
out.z = (v.x * matrix[2]) + (v.y * matrix[6]) + (v.z * matrix[10]);

return out;
}

CVector4 CMatrix4x4::transformPoint(CVector4 v)
{
float x = v.x;
float y = v.y;
float z = v.z;

v.x = x * matrix[0] +
y * matrix[4] +
z * matrix[8] + matrix[12];

v.y = x * matrix[1] +
y * matrix[5] +
z * matrix[9] + matrix[13];

v.z = x * matrix[2] +
y * matrix[6] +
z * matrix[10]+ matrix[14];

v.w = x * matrix[2] +
y * matrix[7] +
z * matrix[11]+ matrix[15];

return v;
}

bool CMatrix4x4::CreateShadowMatrix(CVector4 planeNormal, CVector4 lightPos)
{
Clear();

// Чтобы создать матрицу теней, сначала нужно получить скалярное произведение нормали
// поверхности и позиции света. Мы сохраним результат в float-переменной dotProduct.
// Используем функцию DotProduct из нашего класса CVector4.
float dotProduct = planeNormal.DotProduct4(lightPos);

// Создаем матрицу теней путем добавления наших значений…
matrix[0]  = dotProduct lightPos.x * planeNormal.x;
matrix[4]  = 0.0f       lightPos.x * planeNormal.y;
matrix[8]  = 0.0f       lightPos.x * planeNormal.z;
matrix[12] = 0.0f       lightPos.x * planeNormal.w;

matrix[1]  = 0.0f       lightPos.y * planeNormal.x;
matrix[5]  = dotProduct lightPos.y * planeNormal.y;
matrix[9]  = 0.0f       lightPos.y * planeNormal.z;
matrix[13] = 0.0f       lightPos.y * planeNormal.w;

matrix[2]  = 0.0f       lightPos.z * planeNormal.x;
matrix[6]  = 0.0f       lightPos.z * planeNormal.y;
matrix[10] = dotProduct lightPos.z * planeNormal.z;
matrix[14] = 0.0f       lightPos.z * planeNormal.w;

matrix[3]  = 0.0f       lightPos.w * planeNormal.x;
matrix[7]  = 0.0f       lightPos.w * planeNormal.y;
matrix[11] = 0.0f       lightPos.w * planeNormal.z;
matrix[15] = dotProduct lightPos.w * planeNormal.w;

return true;
}

 

Очень много непонятных рассчетов, да? Ничего, скорее всего в ближайшем будущем вы будете только использовать
эти функции, не модифицируя их.