1 /*
2 * Copyright (C) 2023 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 <base/containers/array_view.h>
20 #include <base/math/vector_util.h>
21 #include <base/namespace.h>
22
23 // m00[0] m01[3] m02[6]
24 // m10[1] m11[4] m12[7]
25 // m20[2] m21[5] m22[8]
26 // m00[0] m01[4] m02[8] m03[12]
27 // m10[1] m11[5] m12[9] m13[13]
28 // m20[2] m21[6] m22[10] m23[14]
29 // m30[3] m31[7] m32[11] m33[15]
BASE_BEGIN_NAMESPACE()30 BASE_BEGIN_NAMESPACE()
31 namespace Math {
32 #include <base/math/disable_warning_4201_heading.h>
33
34 /** @ingroup group_math_matrix */
35 /** Matrix 3X3 presentation in column major format */
36 class Mat3X3 final {
37 public:
38 union {
39 struct {
40 Vec3 x, y, z;
41 };
42 Vec3 base[3];
43 float data[9];
44 };
45
46 /** Subscript operator */
47 constexpr Vec3& operator[](size_t aIndex)
48 {
49 return base[aIndex];
50 }
51
52 /** Subscript operator */
53 constexpr const Vec3& operator[](size_t aIndex) const
54 {
55 return base[aIndex];
56 }
57
58 // Constructors
59 /** Default constructor */
60 inline constexpr Mat3X3() noexcept : data { 0 } {}
61
62 /** Identity constructor */
63 inline explicit constexpr Mat3X3(float id) noexcept : data { id, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, id } {}
64
65 /** Constructor for using Vector3's */
66 inline constexpr Mat3X3(Vec3 const& v0, Vec3 const& v1, Vec3 const& v2) noexcept : x(v0), y(v1), z(v2) {}
67
68 /** Constructor for array of floats */
69 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] }
70 {}
71
72 inline ~Mat3X3() = default;
73
74 /** Multiply two matrices */
75 inline constexpr Mat3X3 operator*(const Mat3X3& rhs) const
76 {
77 const Vec3& rha { rhs.x.x, rhs.y.x, rhs.z.x };
78 const Vec3& rhb { rhs.x.y, rhs.y.y, rhs.z.y };
79 const Vec3& rhc { rhs.x.z, rhs.y.z, rhs.z.z };
80
81 return { { Dot(x, rha), Dot(x, rhb), Dot(x, rhc) }, { Dot(y, rha), Dot(y, rhb), Dot(y, rhc) },
82 { Dot(z, rha), Dot(z, rhb), Dot(z, rhc) } };
83 }
84
85 /** Multiply columns by float scalar value */
86 inline constexpr Mat3X3 operator*(const float& scalar) const
87 {
88 return Mat3X3(x * scalar, y * scalar, z * scalar);
89 }
90
91 /** Equality operator, returns true if matrices are equal */
92 inline constexpr bool operator==(const Mat3X3& mat) const
93 {
94 for (size_t i = 0; i < countof(data); ++i) {
95 if (data[i] != mat.data[i]) {
96 return false;
97 }
98 }
99 return true;
100 }
101
102 /** Inequality operator, returns true if matrices are inequal */
103 inline constexpr bool operator!=(const Mat3X3& mat) const
104 {
105 for (size_t i = 0; i < countof(data); ++i) {
106 if (data[i] != mat.data[i]) {
107 return true;
108 }
109 }
110 return false;
111 }
112 };
113
114 // Assert that Mat3X3 is the same as 9 floats
115 static_assert(sizeof(Mat3X3) == 9 * sizeof(float));
116
117 static constexpr Mat3X3 IDENTITY_3X3(1.f);
118
119 /** @ingroup group_math_matrix */
120 /** Matrix 4X4 presentation in column major format */
121 class Mat4X4 final {
122 public:
123 union {
124 struct {
125 Vec4 x, y, z, w;
126 };
127 Vec4 base[4]; // base[0] is X ,base [1] is Y, etc..
128 float data[16];
129 };
130
131 // "For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory.
132 // The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix."
133 // https://www.khronos.org/opengl/wiki/General_OpenGL:_Transformations#Are_OpenGL_matrices_column-major_or_row-major.3F
134 // this is also the same as with glm.
135 /** Subscript operator */
136 constexpr Vec4& operator[](size_t aIndex)
137 {
138 return base[aIndex];
139 }
140
141 /** Subscript operator */
142 constexpr const Vec4& operator[](size_t aIndex) const
143 {
144 return base[aIndex];
145 }
146
147 // Constructors
148 /** Zero initializer constructor */
149 inline constexpr Mat4X4() : data { 0 } {}
150
151 /** Constructor for Vector4's */
152 inline constexpr Mat4X4(Vec4 const& v0, Vec4 const& v1, Vec4 const& v2, Vec4 const& v3) : x(v0), y(v1), z(v2), w(v3)
153 {}
154
155 /** Constructor for array of floats */
156 inline constexpr Mat4X4(const float d[16])
157 : 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] }
158 {}
159
160 /** Constructor for floats */
161 inline constexpr Mat4X4(float d0, float d1, float d2, float d3, float d4, float d5, float d6, float d7, float d8,
162 float d9, float d10, float d11, float d12, float d13, float d14, float d15)
163 : data { d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15 }
164 {}
165
166 /** Identity constructor */
167 inline explicit constexpr Mat4X4(float id)
168 : 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 }
169 {}
170
171 /** Conversion constructor from Mat3X3 to Mat4X4 */
172 explicit inline constexpr Mat4X4(const Mat3X3& mat3X3)
173 : data { mat3X3.data[0], mat3X3.data[1], mat3X3.data[2], 0.0f, mat3X3.data[3], mat3X3.data[4], mat3X3.data[5],
174 0.0f, mat3X3.data[6], mat3X3.data[7], mat3X3.data[8], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }
175 {}
176
177 inline ~Mat4X4() = default;
178
179 /** Multiply two matrices */
180 inline constexpr Mat4X4 operator*(const Mat4X4& rhs) const
181 {
182 #define d data
183 Mat4X4 res;
184 res.d[0] = d[0] * rhs.d[0] + d[4] * rhs.d[1] + d[8] * rhs.d[2] + d[12] * rhs.d[3];
185 res.d[4] = d[0] * rhs.d[4] + d[4] * rhs.d[5] + d[8] * rhs.d[6] + d[12] * rhs.d[7];
186 res.d[8] = d[0] * rhs.d[8] + d[4] * rhs.d[9] + d[8] * rhs.d[10] + d[12] * rhs.d[11];
187 res.d[12] = d[0] * rhs.d[12] + d[4] * rhs.d[13] + d[8] * rhs.d[14] + d[12] * rhs.d[15];
188
189 res.d[1] = d[1] * rhs.d[0] + d[5] * rhs.d[1] + d[9] * rhs.d[2] + d[13] * rhs.d[3];
190 res.d[5] = d[1] * rhs.d[4] + d[5] * rhs.d[5] + d[9] * rhs.d[6] + d[13] * rhs.d[7];
191 res.d[9] = d[1] * rhs.d[8] + d[5] * rhs.d[9] + d[9] * rhs.d[10] + d[13] * rhs.d[11];
192 res.d[13] = d[1] * rhs.d[12] + d[5] * rhs.d[13] + d[9] * rhs.d[14] + d[13] * rhs.d[15];
193
194 res.d[2] = d[2] * rhs.d[0] + d[6] * rhs.d[1] + d[10] * rhs.d[2] + d[14] * rhs.d[3];
195 res.d[6] = d[2] * rhs.d[4] + d[6] * rhs.d[5] + d[10] * rhs.d[6] + d[14] * rhs.d[7];
196 res.d[10] = d[2] * rhs.d[8] + d[6] * rhs.d[9] + d[10] * rhs.d[10] + d[14] * rhs.d[11];
197 res.d[14] = d[2] * rhs.d[12] + d[6] * rhs.d[13] + d[10] * rhs.d[14] + d[14] * rhs.d[15];
198
199 res.d[3] = d[3] * rhs.d[0] + d[7] * rhs.d[1] + d[11] * rhs.d[2] + d[15] * rhs.d[3];
200 res.d[7] = d[3] * rhs.d[4] + d[7] * rhs.d[5] + d[11] * rhs.d[6] + d[15] * rhs.d[7];
201 res.d[11] = d[3] * rhs.d[8] + d[7] * rhs.d[9] + d[11] * rhs.d[10] + d[15] * rhs.d[11];
202 res.d[15] = d[3] * rhs.d[12] + d[7] * rhs.d[13] + d[11] * rhs.d[14] + d[15] * rhs.d[15];
203 #undef d
204 return res;
205 }
206
207 /** Multiply columns by float scalar value */
208 inline constexpr Mat4X4 operator*(const float& scalar) const
209 {
210 return Mat4X4(x * scalar, y * scalar, z * scalar, w * scalar);
211 }
212
213 /** Equality operator, returns true if matrices are equal */
214 inline constexpr bool operator==(const Mat4X4& mat) const
215 {
216 for (size_t i = 0; i < countof(data); ++i) {
217 if (data[i] != mat.data[i]) {
218 return false;
219 }
220 }
221 return true;
222 }
223
224 /** Inequality operator, returns true if matrices are inequal */
225 inline constexpr bool operator!=(const Mat4X4& mat) const
226 {
227 for (size_t i = 0; i < countof(data); ++i) {
228 if (data[i] != mat.data[i]) {
229 return true;
230 }
231 }
232 return false;
233 }
234 };
235
236 // Assert that Mat4X4 is the same as 16 floats
237 static_assert(sizeof(Mat4X4) == 16 * sizeof(float));
238
239 static constexpr Mat4X4 IDENTITY_4X4(1.f);
240
241 /*
242 m00[0] m01[4] m02[8] m03[12]
243 m10[1] m11[5] m12[9] m13[13]
244 m20[2] m21[6] m22[10] m23[14]
245 m30[3] m31[7] m32[11] m33[15]
246 */
247 #include <base/math/disable_warning_4201_footer.h>
248 } // namespace Math
249 BASE_END_NAMESPACE()
250
251 #endif // API_BASE_MATH_MATRIX_H
252