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] 39BASE_BEGIN_NAMESPACE() 40namespace Math { 41#include <base/math/disable_warning_4201_heading.h> 42 43/** @ingroup group_math_matrix */ 44/** Matrix 3X3 presentation in column major format */ 45class Mat3X3 final { 46public: 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 124static_assert(sizeof(Mat3X3) == 9 * sizeof(float)); 125 126static constexpr Mat3X3 IDENTITY_3X3(1.f); 127 128/** @ingroup group_math_matrix */ 129/** Matrix 4X4 presentation in column major format */ 130class Mat4X4 final { 131public: 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 246static_assert(sizeof(Mat4X4) == 16 * sizeof(float)); 247 248static constexpr Mat4X4 IDENTITY_4X4(1.f); 249 250/** @ingroup group_math_matrix */ 251/** Matrix 4X3 presentation in column major format */ 252class Mat4X3 final { 253public: 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 334static_assert(sizeof(Mat4X3) == 12 * sizeof(float)); 335 336static constexpr Mat4X3 IDENTITY_4X3(1.f); 337 338#include <base/math/disable_warning_4201_footer.h> 339} // namespace Math 340BASE_END_NAMESPACE() 341 342#endif // API_BASE_MATH_MATRIX_H 343