-
Notifications
You must be signed in to change notification settings - Fork 0
/
matrix.inl
171 lines (155 loc) · 7.35 KB
/
matrix.inl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
namespace rapid
{
inline matrix::matrix(float _00, float _01,
float _10, float _11) noexcept:
XMMATRIX(_00, _01, 0.f, 0.f,
_10, _11, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f) {}
inline matrix::matrix(float _00, float _01, float _02,
float _10, float _11, float _12,
float _20, float _21, float _22) noexcept:
XMMATRIX(_00, _01, _02, 0.f,
_10, _11, _12, 0.f,
_20, _21, _22, 0.f,
0.f, 0.f, 0.f, 1.f) {}
inline matrix::matrix(float _00, float _01, float _02, float _03,
float _10, float _11, float _12, float _13,
float _20, float _21, float _22, float _23,
float _30, float _31, float _32, float _33) noexcept:
XMMATRIX(_00, _01, _02, _03,
_10, _11, _12, _13,
_20, _21, _22, _23,
_30, _31, _32, _33) {}
inline matrix::matrix(const float scale, const float3& translation) noexcept:
XMMATRIX(scale, 0.f, 0.f, 0.f,
0.f, scale, 0.f, 0.f,
0.f, 0.f, scale, 0.f,
translation.x, translation.y, translation.z, 1.f) {}
inline float matrix::inverse() noexcept
{
vector d;
*this = XMMatrixInverse(&d.V, *this);
float determinant;
XMStoreFloat(&determinant, d);
return determinant;
}
template<int rows, int cols>
inline void matrix::store(float (&m)[rows][cols]) const noexcept
{
static_assert((rows >= 3) && (rows <= 4), "invalid number of matrix rows");
static_assert((cols >= 3) && (cols <= 4), "invalid number of matrix columns");
}
template<>
inline void matrix::store<3, 3>(float (&m)[3][3]) const noexcept
{
XMStoreFloat3x3(reinterpret_cast<float3x3 *>(m), *this);
}
template<>
inline void matrix::store<3, 4>(float (&m)[3][4]) const noexcept
{
float4x3a mat;
XMStoreFloat4x3A(&mat, *this);
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 4; ++j)
m[i][j] = mat(j, i);
}
template<>
inline void matrix::store<4, 3>(float (&m)[4][3]) const noexcept
{
if (aligned(m))
XMStoreFloat4x3A(reinterpret_cast<float4x3a *>(m), *this);
else
XMStoreFloat4x3(reinterpret_cast<float4x3 *>(m), *this);
}
template<>
inline void matrix::store<4, 4>(float (&m)[4][4]) const noexcept
{
if (aligned(m))
XMStoreFloat4x4A(reinterpret_cast<float4x4a *>(m), *this);
else
XMStoreFloat4x4(reinterpret_cast<float4x4 *>(m), *this);
}
inline matrix transpose(const matrix& m) noexcept
{ return XMMatrixTranspose(m); }
inline matrix identity() noexcept { return XMMatrixIdentity(); }
inline matrix translation(float x, float y) noexcept
{ return XMMatrixTranslation(x, y, 0.f); }
inline matrix translation(float x, float y, float z) noexcept
{ return XMMatrixTranslation(x, y, z); }
inline matrix translation(const vector& offset) noexcept
{ return XMMatrixTranslationFromVector(offset); }
inline matrix scaling(float scaleX, float scaleY, float scaleZ) noexcept
{ return XMMatrixScaling(scaleX, scaleY, scaleZ); }
inline matrix scaling(const vector& scale) noexcept
{ return XMMatrixScalingFromVector(scale); }
inline matrix rotationX(float angle) noexcept
{ return XMMatrixRotationX(angle); }
inline matrix rotationY(float angle) noexcept
{ return XMMatrixRotationY(angle); }
inline matrix rotationZ(float angle) noexcept
{ return XMMatrixRotationZ(angle); }
inline matrix rotationNormal(const vector3& normal, float angle) noexcept
{ return XMMatrixRotationNormal(normal, angle); }
inline matrix rotationAxis(const vector3& axis, float angle) noexcept
{ return XMMatrixRotationAxis(axis, angle); }
inline matrix affine(const vector& scaling, const vector& rotationOrigin, float rotation, const vector& translation) noexcept
{ return XMMatrixAffineTransformation2D(scaling, rotationOrigin, rotation, translation); }
inline matrix affine(const vector& scaling, const vector& rotationOrigin, const quaternion& rotation, const vector& translation) noexcept
{ return XMMatrixAffineTransformation(scaling, rotationOrigin, rotation, translation); }
inline matrix lookAtLH(const vector& eyePosition, const vector& focusPosition, const vector& upDirection) noexcept
{ return XMMatrixLookAtLH(eyePosition, focusPosition, upDirection); }
inline matrix lookAtRH(const vector& eyePosition, const vector& focusPosition, const vector& upDirection) noexcept
{ return XMMatrixLookAtRH(eyePosition, focusPosition, upDirection); }
inline matrix lookToLH(const vector& eyePosition, const vector& eyeDirection, const vector& upDirection) noexcept
{ return XMMatrixLookToLH(eyePosition, eyeDirection, upDirection); }
inline matrix lookToRH(const vector& eyePosition, const vector& eyeDirection, const vector& upDirection) noexcept
{ return XMMatrixLookToRH(eyePosition, eyeDirection, upDirection); }
inline matrix perspectiveLH(float viewWidth, float viewHeight, float nearZ, float farZ) noexcept
{ return XMMatrixPerspectiveLH(viewWidth, viewHeight, nearZ, farZ); }
inline matrix perspectiveRH(float viewWidth, float viewHeight, float nearZ, float farZ) noexcept
{ return XMMatrixPerspectiveRH(viewWidth, viewHeight, nearZ, farZ); }
inline matrix perspectiveFovLH(float fovAngleY, float aspectRatio, float nearZ, float farZ) noexcept
{ return XMMatrixPerspectiveFovLH(fovAngleY, aspectRatio, nearZ, farZ); }
inline matrix perspectiveFovRH(float fovAngleY, float aspectRatio, float nearZ, float farZ) noexcept
{ return XMMatrixPerspectiveFovRH(fovAngleY, aspectRatio, nearZ, farZ); }
inline matrix inverse(const matrix& m, float *determinant = nullptr) noexcept
{
vector d;
matrix inv = XMMatrixInverse(determinant ? &d.V : nullptr, m);
if (determinant) XMStoreFloat(determinant, d);
return inv;
}
inline matrix negateY(const matrix& m) noexcept
{
matrix neg;
neg.r[0] = m.r[0];
neg.r[1] = XMVectorMultiply(m.r[1], g_XMNegateY);
neg.r[2] = m.r[2];
neg.r[3] = m.r[3];
return neg;
}
inline matrix matrix3(const matrix& m) noexcept
{
matrix m3x3;
m3x3.r[0] = m.r[0];
m3x3.r[1] = m.r[1];
m3x3.r[2] = m.r[2];
m3x3.r[3] = g_XMZero;
m3x3.r[0].m128_f32[3] = m3x3.r[1].m128_f32[3] = m3x3.r[2].m128_f32[3] = 0.f;
return m3x3;
}
// Assuming your matrix multiplication follows the convention: M = (S * R * T)
// (where M is your composed matrix, T is a Translation matrix, R rotation, S scale),
// then we can normalize the first three rows of the matrix to get just the T * R part.
// https://gamedev.stackexchange.com/questions/119702/fastest-way-to-neutralize-scale-in-the-transform-matrix
inline matrix excludeNonUniformScaling(const rapid::matrix& m)
{
rapid::matrix uniform;
uniform.r[0] = XMVector3Normalize(m.r[0]);
uniform.r[1] = XMVector3Normalize(m.r[1]);
uniform.r[2] = XMVector3Normalize(m.r[2]);
uniform.r[3] = m.r[3];
return uniform;
}
} // namespace rapid