1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef API_BASE_MATH_MATRIX_H
17 #define API_BASE_MATH_MATRIX_H
18
19 #include <cstddef>
20
21 #include <base/containers/type_traits.h>
22 #include <base/math/vector.h>
23 #include <base/math/vector_util.h>
24 #include <base/namespace.h>
25
26 // m00[0] m01[3] m02[6]
27 // m10[1] m11[4] m12[7]
28 // m20[2] m21[5] m22[8]
29
30 // m00[0] m01[4] m02[8] m03[12]
31 // m10[1] m11[5] m12[9] m13[13]
32 // m20[2] m21[6] m22[10] m23[14]
33 // m30[3] m31[7] m32[11] m33[15]
34
35 // m00[0] m01[4] m02[8]
36 // m10[1] m11[5] m12[9]
37 // m20[2] m21[6] m22[10]
38 // m30[3] m31[7] m32[11]
BASE_BEGIN_NAMESPACE()39 BASE_BEGIN_NAMESPACE()
40 namespace Math {
41 #include <base/math/disable_warning_4201_heading.h>
42
43 /** @ingroup group_math_matrix */
44 /** Matrix 3X3 presentation in column major format */
45 class Mat3X3 final {
46 public:
47 union {
48 struct {
49 Vec3 x, y, z;
50 };
51 Vec3 base[3];
52 float data[9];
53 };
54
55 /** Subscript operator */
56 constexpr Vec3& operator[](size_t aIndex)
57 {
58 return base[aIndex];
59 }
60
61 /** Subscript operator */
62 constexpr const Vec3& operator[](size_t aIndex) const
63 {
64 return base[aIndex];
65 }
66
67 // Constructors
68 /** Default constructor */
69 inline constexpr Mat3X3() noexcept : data { 0 } {}
70
71 /** Identity constructor */
72 inline explicit constexpr Mat3X3(float id) noexcept : data { id, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, id } {}
73
74 /** Constructor for using Vector3's */
75 inline constexpr Mat3X3(Vec3 const& v0, Vec3 const& v1, Vec3 const& v2) noexcept : x(v0), y(v1), z(v2) {}
76
77 /** Constructor for array of floats */
78 inline constexpr Mat3X3(const float d[9]) noexcept : data { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8] }
79 {}
80
81 inline ~Mat3X3() = default;
82
83 /** Multiply two matrices */
84 inline constexpr Mat3X3 operator*(const Mat3X3& rhs) const
85 {
86 const Vec3& rha { rhs.x.x, rhs.y.x, rhs.z.x };
87 const Vec3& rhb { rhs.x.y, rhs.y.y, rhs.z.y };
88 const Vec3& rhc { rhs.x.z, rhs.y.z, rhs.z.z };
89
90 return { { Dot(x, rha), Dot(x, rhb), Dot(x, rhc) }, { Dot(y, rha), Dot(y, rhb), Dot(y, rhc) },
91 { Dot(z, rha), Dot(z, rhb), Dot(z, rhc) } };
92 }
93
94 /** Multiply columns by float scalar value */
95 inline constexpr Mat3X3 operator*(const float& scalar) const
96 {
97 return Mat3X3(x * scalar, y * scalar, z * scalar);
98 }
99
100 /** Equality operator, returns true if matrices are equal */
101 inline constexpr bool operator==(const Mat3X3& mat) const
102 {
103 for (size_t i = 0; i < countof(data); ++i) {
104 if (data[i] != mat.data[i]) {
105 return false;
106 }
107 }
108 return true;
109 }
110
111 /** Inequality operator, returns true if matrices are inequal */
112 inline constexpr bool operator!=(const Mat3X3& mat) const
113 {
114 for (size_t i = 0; i < countof(data); ++i) {
115 if (data[i] != mat.data[i]) {
116 return true;
117 }
118 }
119 return false;
120 }
121 };
122
123 // Assert that Mat3X3 is the same as 9 floats
124 static_assert(sizeof(Mat3X3) == 9 * sizeof(float));
125
126 static constexpr Mat3X3 IDENTITY_3X3(1.f);
127
128 /** @ingroup group_math_matrix */
129 /** Matrix 4X4 presentation in column major format */
130 class Mat4X4 final {
131 public:
132 union {
133 struct {
134 Vec4 x, y, z, w;
135 };
136 Vec4 base[4]; // base[0] is X ,base [1] is Y, etc..
137 float data[16];
138 };
139
140 // "For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory.
141 // The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix."
142 // https://www.khronos.org/opengl/wiki/General_OpenGL:_Transformations#Are_OpenGL_matrices_column-major_or_row-major.3F
143 // this is also the same as with glm.
144 /** Subscript operator */
145 constexpr Vec4& operator[](size_t aIndex)
146 {
147 return base[aIndex];
148 }
149
150 /** Subscript operator */
151 constexpr const Vec4& operator[](size_t aIndex) const
152 {
153 return base[aIndex];
154 }
155
156 // Constructors
157 /** Zero initializer constructor */
158 inline constexpr Mat4X4() : data { 0 } {}
159
160 /** Constructor for Vector4's */
161 inline constexpr Mat4X4(Vec4 const& v0, Vec4 const& v1, Vec4 const& v2, Vec4 const& v3) : x(v0), y(v1), z(v2), w(v3)
162 {}
163
164 /** Constructor for array of floats */
165 inline constexpr Mat4X4(const float d[16])
166 : data { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15] }
167 {}
168
169 /** Constructor for floats */
170 inline constexpr Mat4X4(float d0, float d1, float d2, float d3, float d4, float d5, float d6, float d7, float d8,
171 float d9, float d10, float d11, float d12, float d13, float d14, float d15)
172 : data { d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15 }
173 {}
174
175 /** Identity constructor */
176 inline explicit constexpr Mat4X4(float id)
177 : data { id, 0.0f, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, 0.0f, id }
178 {}
179
180 /** Conversion constructor from Mat3X3 to Mat4X4 */
181 explicit inline constexpr Mat4X4(const Mat3X3& mat3X3)
182 : data { mat3X3.data[0], mat3X3.data[1], mat3X3.data[2], 0.0f, mat3X3.data[3], mat3X3.data[4], mat3X3.data[5],
183 0.0f, mat3X3.data[6], mat3X3.data[7], mat3X3.data[8], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }
184 {}
185
186 inline ~Mat4X4() = default;
187
188 /** Multiply two matrices */
189 inline constexpr Mat4X4 operator*(const Mat4X4& rhs) const
190 {
191 #define d data
192 Mat4X4 res;
193 res.d[0] = d[0] * rhs.d[0] + d[4] * rhs.d[1] + d[8] * rhs.d[2] + d[12] * rhs.d[3];
194 res.d[4] = d[0] * rhs.d[4] + d[4] * rhs.d[5] + d[8] * rhs.d[6] + d[12] * rhs.d[7];
195 res.d[8] = d[0] * rhs.d[8] + d[4] * rhs.d[9] + d[8] * rhs.d[10] + d[12] * rhs.d[11];
196 res.d[12] = d[0] * rhs.d[12] + d[4] * rhs.d[13] + d[8] * rhs.d[14] + d[12] * rhs.d[15];
197
198 res.d[1] = d[1] * rhs.d[0] + d[5] * rhs.d[1] + d[9] * rhs.d[2] + d[13] * rhs.d[3];
199 res.d[5] = d[1] * rhs.d[4] + d[5] * rhs.d[5] + d[9] * rhs.d[6] + d[13] * rhs.d[7];
200 res.d[9] = d[1] * rhs.d[8] + d[5] * rhs.d[9] + d[9] * rhs.d[10] + d[13] * rhs.d[11];
201 res.d[13] = d[1] * rhs.d[12] + d[5] * rhs.d[13] + d[9] * rhs.d[14] + d[13] * rhs.d[15];
202
203 res.d[2] = d[2] * rhs.d[0] + d[6] * rhs.d[1] + d[10] * rhs.d[2] + d[14] * rhs.d[3];
204 res.d[6] = d[2] * rhs.d[4] + d[6] * rhs.d[5] + d[10] * rhs.d[6] + d[14] * rhs.d[7];
205 res.d[10] = d[2] * rhs.d[8] + d[6] * rhs.d[9] + d[10] * rhs.d[10] + d[14] * rhs.d[11];
206 res.d[14] = d[2] * rhs.d[12] + d[6] * rhs.d[13] + d[10] * rhs.d[14] + d[14] * rhs.d[15];
207
208 res.d[3] = d[3] * rhs.d[0] + d[7] * rhs.d[1] + d[11] * rhs.d[2] + d[15] * rhs.d[3];
209 res.d[7] = d[3] * rhs.d[4] + d[7] * rhs.d[5] + d[11] * rhs.d[6] + d[15] * rhs.d[7];
210 res.d[11] = d[3] * rhs.d[8] + d[7] * rhs.d[9] + d[11] * rhs.d[10] + d[15] * rhs.d[11];
211 res.d[15] = d[3] * rhs.d[12] + d[7] * rhs.d[13] + d[11] * rhs.d[14] + d[15] * rhs.d[15];
212 #undef d
213 return res;
214 }
215
216 /** Multiply columns by float scalar value */
217 inline constexpr Mat4X4 operator*(const float& scalar) const
218 {
219 return Mat4X4(x * scalar, y * scalar, z * scalar, w * scalar);
220 }
221
222 /** Equality operator, returns true if matrices are equal */
223 inline constexpr bool operator==(const Mat4X4& mat) const
224 {
225 for (size_t i = 0; i < countof(data); ++i) {
226 if (data[i] != mat.data[i]) {
227 return false;
228 }
229 }
230 return true;
231 }
232
233 /** Inequality operator, returns true if matrices are inequal */
234 inline constexpr bool operator!=(const Mat4X4& mat) const
235 {
236 for (size_t i = 0; i < countof(data); ++i) {
237 if (data[i] != mat.data[i]) {
238 return true;
239 }
240 }
241 return false;
242 }
243 };
244
245 // Assert that Mat4X4 is the same as 16 floats
246 static_assert(sizeof(Mat4X4) == 16 * sizeof(float));
247
248 static constexpr Mat4X4 IDENTITY_4X4(1.f);
249
250 /** @ingroup group_math_matrix */
251 /** Matrix 4X3 presentation in column major format */
252 class Mat4X3 final {
253 public:
254 union {
255 struct {
256 Vec3 x, y, z, w;
257 };
258 Vec3 base[4]; // base[0] is X ,base [1] is Y, etc..
259 float data[12];
260 };
261
262 // "For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory.
263 // The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix."
264 // https://www.khronos.org/opengl/wiki/General_OpenGL:_Transformations#Are_OpenGL_matrices_column-major_or_row-major.3F
265 // this is also the same as with glm.
266 /** Subscript operator */
267 constexpr Vec3& operator[](size_t aIndex)
268 {
269 return base[aIndex];
270 }
271
272 /** Subscript operator */
273 constexpr const Vec3& operator[](size_t aIndex) const
274 {
275 return base[aIndex];
276 }
277
278 // Constructors
279 /** Zero initializer constructor */
280 inline constexpr Mat4X3() : data { 0 } {}
281
282 /** Constructor for Vector4's */
283 inline constexpr Mat4X3(Vec3 const& v0, Vec3 const& v1, Vec3 const& v2, Vec3 const& v3) : x(v0), y(v1), z(v2), w(v3)
284 {}
285
286 /** Constructor for array of floats */
287 inline constexpr Mat4X3(const float d[12])
288 : data { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11] }
289 {}
290
291 /** Constructor for floats */
292 inline constexpr Mat4X3(float d0, float d1, float d2, float d3, float d4, float d5, float d6, float d7, float d8,
293 float d9, float d10, float d11)
294 : data { d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11 }
295 {}
296
297 /** Identity constructor */
298 inline explicit constexpr Mat4X3(float id)
299 : data { id, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f }
300 {}
301
302 inline ~Mat4X3() = default;
303
304 /** Multiply columns by float scalar value */
305 inline constexpr Mat4X3 operator*(const float& scalar) const
306 {
307 return Mat4X3(x * scalar, y * scalar, z * scalar, w * scalar);
308 }
309
310 /** Equality operator, returns true if matrices are equal */
311 inline constexpr bool operator==(const Mat4X3& mat) const
312 {
313 for (size_t i = 0; i < countof(data); ++i) {
314 if (data[i] != mat.data[i]) {
315 return false;
316 }
317 }
318 return true;
319 }
320
321 /** Inequality operator, returns true if matrices are inequal */
322 inline constexpr bool operator!=(const Mat4X3& mat) const
323 {
324 for (size_t i = 0; i < countof(data); ++i) {
325 if (data[i] != mat.data[i]) {
326 return true;
327 }
328 }
329 return false;
330 }
331 };
332
333 // Assert that Mat4X4 is the same as 12 floats
334 static_assert(sizeof(Mat4X3) == 12 * sizeof(float));
335
336 static constexpr Mat4X3 IDENTITY_4X3(1.f);
337
338 #include <base/math/disable_warning_4201_footer.h>
339 } // namespace Math
340 BASE_END_NAMESPACE()
341
342 #endif // API_BASE_MATH_MATRIX_H
343