class float4x4
{
public:
union
{
struct
{
float v00;
float v01;
float v02;
float v03;
float v10;
float v11;
float v12;
float v13;
float v20;
float v21;
float v22;
float v23;
float v30;
float v31;
float v32;
float v33;
};
float4 ArrVector[4];
float Arr1D[16] = { };
float Arr2D[4][4];
};
float4x4()
{
Identity(); // 무조건 항등행렬로 생성
}
float4x4& operator=(const float4x4& _Value)
{
memcpy_s(Arr1D, sizeof(float) * 16, _Value.Arr1D, sizeof(float) * 16);
// _Value.Arr1D에 존재하는 내용을 (sizeof(float) * 16) 크기만큼,
// Arr1D의 (sizeof(float) * 16) 크기에 복사하라는 뜻
return *this;
}
float4x4 operator*(const float4x4& _Value)
{
return ::operator*(*this, _Value);
}
// 3차원 변환행렬로써 사용할 경우...
float4 LeftVector() // X벡터
{
return -ArrVector[0].Normalize2DReturn();
}
float4 RightVector() // X벡터
{
return ArrVector[0].Normalize2DReturn();
}
float4 UpVector() // Y벡터
{
return ArrVector[1].Normalize2DReturn();
}
float4 DownVector() // Y벡터
{
return -ArrVector[1].Normalize2DReturn();
}
float4 ForwardVector() // Z벡터
{
return ArrVector[2].Normalize2DReturn();
}
float4 BackVector() // Z벡터
{
return -ArrVector[2].Normalize2DReturn();
}
};
using FMatrix = float4x4;
행렬 1 ⇒ Y1 x X1
행렬 2 ⇒ Y2 x X2
(행렬 1 * 행렬 2) 연산을 수행할 경우…
/*
(1 x 4) * (4 x 4) 의 경우
a00 a01 a02 a03 x b00 b01 b02 b03 = ab00 ab01 ab02 ab03
b10 b11 b12 b13
b20 b21 b22 b23
b30 b31 b32 b33
ab00 = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30
ab01 = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31
ab02 = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32
ab03 = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33
*/
float4 float4::operator*(const float4x4& _Other) const
{
float4 Result;
Result.X = (Arr2D[0][0] * _Other.Arr2D[0][0]) + (Arr2D[0][1] * _Other.Arr2D[1][0]) + (Arr2D[0][2] * _Other.Arr2D[2][0]) + (Arr2D[0][3] * _Other.Arr2D[3][0]);
Result.Y = (Arr2D[0][0] * _Other.Arr2D[0][1]) + (Arr2D[0][1] * _Other.Arr2D[1][1]) + (Arr2D[0][2] * _Other.Arr2D[2][1]) + (Arr2D[0][3] * _Other.Arr2D[3][1]);
Result.Z = (Arr2D[0][0] * _Other.Arr2D[0][2]) + (Arr2D[0][1] * _Other.Arr2D[1][2]) + (Arr2D[0][2] * _Other.Arr2D[2][2]) + (Arr2D[0][3] * _Other.Arr2D[3][2]);
Result.W = (Arr2D[0][0] * _Other.Arr2D[0][3]) + (Arr2D[0][1] * _Other.Arr2D[1][3]) + (Arr2D[0][2] * _Other.Arr2D[2][3]) + (Arr2D[0][3] * _Other.Arr2D[3][3]);
return Result;
}
float4& float4::operator*=(const class float4x4& _Other)
{
float4 Result;
Result.X = (Arr2D[0][0] * _Other.Arr2D[0][0]) + (Arr2D[0][1] * _Other.Arr2D[1][0]) + (Arr2D[0][2] * _Other.Arr2D[2][0]) + (Arr2D[0][3] * _Other.Arr2D[3][0]);
Result.Y = (Arr2D[0][0] * _Other.Arr2D[0][1]) + (Arr2D[0][1] * _Other.Arr2D[1][1]) + (Arr2D[0][2] * _Other.Arr2D[2][1]) + (Arr2D[0][3] * _Other.Arr2D[3][1]);
Result.Z = (Arr2D[0][0] * _Other.Arr2D[0][2]) + (Arr2D[0][1] * _Other.Arr2D[1][2]) + (Arr2D[0][2] * _Other.Arr2D[2][2]) + (Arr2D[0][3] * _Other.Arr2D[3][2]);
Result.W = (Arr2D[0][0] * _Other.Arr2D[0][3]) + (Arr2D[0][1] * _Other.Arr2D[1][3]) + (Arr2D[0][2] * _Other.Arr2D[2][3]) + (Arr2D[0][3] * _Other.Arr2D[3][3]);
*this = Result;
return *this;
}
/*
(4 x 4) * (4 x 4) 의 경우
a00 a01 a02 a03 x b00 b01 b02 b03 = ab00 ab01 ab02 ab03
a10 a11 a12 a13 b10 b11 b12 b13 ab10 ab11 ab12 ab13
a20 a21 a22 a23 b20 b21 b22 b23 ab20 ab21 ab22 ab23
a30 a31 a32 a33 b30 b31 b32 b33 ab30 ab31 ab32 ab33
ab00 = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30
ab01 = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31
ab02 = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32
ab03 = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33
ab10 = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30
ab11 = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31
ab12 = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32
ab13 = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33
ab20 = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30
ab21 = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31
ab22 = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32
ab23 = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33
ab30 = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30
ab31 = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31
ab32 = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32
ab33 = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33
*/
float4x4 operator*(const float4x4& _Left, const float4x4& _Right)
{
float4x4 Result;
const float4x4& A = _Left;
const float4x4& B = _Right;
Result.Arr2D[0][0] = (A.Arr2D[0][0] * B.Arr2D[0][0]) + (A.Arr2D[0][1] * B.Arr2D[1][0]) + (A.Arr2D[0][2] * B.Arr2D[2][0]) + (A.Arr2D[0][3] * B.Arr2D[3][0]);
Result.Arr2D[0][1] = (A.Arr2D[0][0] * B.Arr2D[0][1]) + (A.Arr2D[0][1] * B.Arr2D[1][1]) + (A.Arr2D[0][2] * B.Arr2D[2][1]) + (A.Arr2D[0][3] * B.Arr2D[3][1]);
Result.Arr2D[0][2] = (A.Arr2D[0][0] * B.Arr2D[0][2]) + (A.Arr2D[0][1] * B.Arr2D[1][2]) + (A.Arr2D[0][2] * B.Arr2D[2][2]) + (A.Arr2D[0][3] * B.Arr2D[3][2]);
Result.Arr2D[0][3] = (A.Arr2D[0][0] * B.Arr2D[0][3]) + (A.Arr2D[0][1] * B.Arr2D[1][3]) + (A.Arr2D[0][2] * B.Arr2D[2][3]) + (A.Arr2D[0][3] * B.Arr2D[3][3]);
Result.Arr2D[1][0] = (A.Arr2D[1][0] * B.Arr2D[0][0]) + (A.Arr2D[1][1] * B.Arr2D[1][0]) + (A.Arr2D[1][2] * B.Arr2D[2][0]) + (A.Arr2D[1][3] * B.Arr2D[3][0]);
Result.Arr2D[1][1] = (A.Arr2D[1][0] * B.Arr2D[0][1]) + (A.Arr2D[1][1] * B.Arr2D[1][1]) + (A.Arr2D[1][2] * B.Arr2D[2][1]) + (A.Arr2D[1][3] * B.Arr2D[3][1]);
Result.Arr2D[1][2] = (A.Arr2D[1][0] * B.Arr2D[0][2]) + (A.Arr2D[1][1] * B.Arr2D[1][2]) + (A.Arr2D[1][2] * B.Arr2D[2][2]) + (A.Arr2D[1][3] * B.Arr2D[3][2]);
Result.Arr2D[1][3] = (A.Arr2D[1][0] * B.Arr2D[0][3]) + (A.Arr2D[1][1] * B.Arr2D[1][3]) + (A.Arr2D[1][2] * B.Arr2D[2][3]) + (A.Arr2D[1][3] * B.Arr2D[3][3]);
Result.Arr2D[2][0] = (A.Arr2D[2][0] * B.Arr2D[0][0]) + (A.Arr2D[2][1] * B.Arr2D[1][0]) + (A.Arr2D[2][2] * B.Arr2D[2][0]) + (A.Arr2D[2][3] * B.Arr2D[3][0]);
Result.Arr2D[2][1] = (A.Arr2D[2][0] * B.Arr2D[0][1]) + (A.Arr2D[2][1] * B.Arr2D[1][1]) + (A.Arr2D[2][2] * B.Arr2D[2][1]) + (A.Arr2D[2][3] * B.Arr2D[3][1]);
Result.Arr2D[2][2] = (A.Arr2D[2][0] * B.Arr2D[0][2]) + (A.Arr2D[2][1] * B.Arr2D[1][2]) + (A.Arr2D[2][2] * B.Arr2D[2][2]) + (A.Arr2D[2][3] * B.Arr2D[3][2]);
Result.Arr2D[2][3] = (A.Arr2D[2][0] * B.Arr2D[0][3]) + (A.Arr2D[2][1] * B.Arr2D[1][3]) + (A.Arr2D[2][2] * B.Arr2D[2][3]) + (A.Arr2D[2][3] * B.Arr2D[3][3]);
Result.Arr2D[3][0] = (A.Arr2D[3][0] * B.Arr2D[0][0]) + (A.Arr2D[3][1] * B.Arr2D[1][0]) + (A.Arr2D[3][2] * B.Arr2D[2][0]) + (A.Arr2D[3][3] * B.Arr2D[3][0]);
Result.Arr2D[3][1] = (A.Arr2D[3][0] * B.Arr2D[0][1]) + (A.Arr2D[3][1] * B.Arr2D[1][1]) + (A.Arr2D[3][2] * B.Arr2D[2][1]) + (A.Arr2D[3][3] * B.Arr2D[3][1]);
Result.Arr2D[3][2] = (A.Arr2D[3][0] * B.Arr2D[0][2]) + (A.Arr2D[3][1] * B.Arr2D[1][2]) + (A.Arr2D[3][2] * B.Arr2D[2][2]) + (A.Arr2D[3][3] * B.Arr2D[3][2]);
Result.Arr2D[3][3] = (A.Arr2D[3][0] * B.Arr2D[0][3]) + (A.Arr2D[3][1] * B.Arr2D[1][3]) + (A.Arr2D[3][2] * B.Arr2D[2][3]) + (A.Arr2D[3][3] * B.Arr2D[3][3]);
/*
for (size_t y = 0; y < 4; y++)
{
for (size_t x = 0; x < 4; x++)
{
for (size_t i = 0; i < 4; i++)
{
Result.Arr2D[y][x] += _Left.Arr2D[y][i] * _Right.Arr2D[i][x];
}
}
}
*/
return Result;
}
: 곱했을 때 자기자신이 나오는 행렬
/*
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
어떤행렬 * 항등행렬 = 어떤행렬
항등행렬 * 어떤행렬 = 어떤행렬
*/
void Identity()
{
memset(Arr1D, 0, sizeof(float) * 16);
// Arr1D의 주소값 위치부터 (sizeof(float) * 16) 크기만큼을 0으로 채우라는 뜻
Arr2D[0][0] = 1.0f;
Arr2D[1][1] = 1.0f;
Arr2D[2][2] = 1.0f;
Arr2D[3][3] = 1.0f;
}
: 행과 열을 바꾼 행렬
/*
00 01 02 03 -(전치)-> 00 10 20 30
10 11 12 13 01 11 21 31
20 21 22 23 02 12 22 32
30 31 32 33 03 13 23 33
*/
void Transpose()
{
float4x4 Result = *this;
for (size_t y = 0; y < 4; y++)
{
for (size_t x = 0; x < 4; x++)
{
Result.Arr2D[y][x] = Arr2D[x][y];
}
}
*this = Result;
}