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