1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:37:45 +00:00

LibGfx: Make Matrix class consistently row-major

Matrix elements were interpreted in different ways.
This makes it definitely row-major, allowing initialization via
initializer list in a standard scientific order. Also matrix
multiplication now happens in the correct order and accessing
elements happens as m_elements[row][column].
This commit is contained in:
Stephan Unverwerth 2021-05-13 19:59:57 +02:00 committed by Andreas Kling
parent a5194274af
commit 0833db0874
4 changed files with 49 additions and 31 deletions

View file

@ -87,6 +87,10 @@ void GLContextWidget::timer_event(Core::TimerEvent&)
* FloatMatrix4x4::rotate(FloatVector3(0, 1, 0), 0.0f) * FloatMatrix4x4::rotate(FloatVector3(0, 1, 0), 0.0f)
* FloatMatrix4x4::rotate(FloatVector3(0, 0, 1), angle); * FloatMatrix4x4::rotate(FloatVector3(0, 0, 1), angle);
// We need to transpose here because OpenGL expects matrices in column major order
// but our matrix class stores elements in row major order.
matrix = matrix.transpose();
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadMatrixf((float*)matrix.elements()); glLoadMatrixf((float*)matrix.elements());

View file

@ -37,11 +37,14 @@ void glPopMatrix()
void glLoadMatrixf(const GLfloat* matrix) void glLoadMatrixf(const GLfloat* matrix)
{ {
// Transpose the matrix here because glLoadMatrix expects elements
// in column major order but out Matrix class stores elements in
// row major order.
FloatMatrix4x4 mat( FloatMatrix4x4 mat(
matrix[0], matrix[1], matrix[2], matrix[3], matrix[0], matrix[4], matrix[8], matrix[12],
matrix[4], matrix[5], matrix[6], matrix[7], matrix[1], matrix[5], matrix[9], matrix[13],
matrix[8], matrix[9], matrix[10], matrix[11], matrix[2], matrix[6], matrix[10], matrix[14],
matrix[12], matrix[13], matrix[14], matrix[15]); matrix[3], matrix[7], matrix[11], matrix[15]);
g_gl_context->gl_load_matrix(mat); g_gl_context->gl_load_matrix(mat);
} }

View file

@ -49,23 +49,23 @@ public:
auto& element = product.m_elements[i][j]; auto& element = product.m_elements[i][j];
if constexpr (N == 4) { if constexpr (N == 4) {
element = m_elements[0][j] * other.m_elements[i][0] element = m_elements[i][0] * other.m_elements[0][j]
+ m_elements[1][j] * other.m_elements[i][1] + m_elements[i][1] * other.m_elements[1][j]
+ m_elements[2][j] * other.m_elements[i][2] + m_elements[i][2] * other.m_elements[2][j]
+ m_elements[3][j] * other.m_elements[i][3]; + m_elements[i][3] * other.m_elements[3][j];
} else if constexpr (N == 3) { } else if constexpr (N == 3) {
element = m_elements[0][j] * other.m_elements[i][0] element = m_elements[i][0] * other.m_elements[0][j]
+ m_elements[1][j] * other.m_elements[i][1] + m_elements[i][1] * other.m_elements[1][j]
+ m_elements[2][j] * other.m_elements[i][2]; + m_elements[i][2] * other.m_elements[2][j];
} else if constexpr (N == 2) { } else if constexpr (N == 2) {
element = m_elements[0][j] * other.m_elements[i][0] element = m_elements[i][0] * other.m_elements[0][j]
+ m_elements[1][j] * other.m_elements[i][1]; + m_elements[i][1] * other.m_elements[1][j];
} else if constexpr (N == 1) { } else if constexpr (N == 1) {
element = m_elements[0][j] * other.m_elements[i][0]; element = m_elements[i][0] * other.m_elements[0][j];
} else { } else {
T value {}; T value {};
for (size_t k = 0; k < N; ++k) for (size_t k = 0; k < N; ++k)
value += m_elements[k][j] * other.m_elements[i][k]; value += m_elements[i][k] * other.m_elements[k][j];
element = value; element = value;
} }

View file

@ -14,7 +14,7 @@
namespace Gfx { namespace Gfx {
template<typename T> template<typename T>
class Matrix4x4 final : public Matrix<4, T> { class Matrix4x4 final {
public: public:
constexpr Matrix4x4() = default; constexpr Matrix4x4() = default;
constexpr Matrix4x4(T _11, T _12, T _13, T _14, constexpr Matrix4x4(T _11, T _12, T _13, T _14,
@ -38,10 +38,10 @@ public:
Matrix4x4 product; Matrix4x4 product;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) { for (int j = 0; j < 4; ++j) {
product.m_elements[i][j] = m_elements[0][j] * other.m_elements[i][0] product.m_elements[i][j] = m_elements[i][0] * other.m_elements[0][j]
+ m_elements[1][j] * other.m_elements[i][1] + m_elements[i][1] * other.m_elements[1][j]
+ m_elements[2][j] * other.m_elements[i][2] + m_elements[i][2] * other.m_elements[2][j]
+ m_elements[3][j] * other.m_elements[i][3]; + m_elements[i][3] * other.m_elements[3][j];
} }
} }
return product; return product;
@ -50,18 +50,18 @@ public:
constexpr Vector4<T> operator*(const Vector4<T>& v) const constexpr Vector4<T> operator*(const Vector4<T>& v) const
{ {
return Vector4<T>( return Vector4<T>(
v.x() * m_elements[0][0] + v.y() * m_elements[1][0] + v.z() * m_elements[2][0] + v.w() * m_elements[3][0], v.x() * m_elements[0][0] + v.y() * m_elements[0][1] + v.z() * m_elements[0][2] + v.w() * m_elements[0][3],
v.x() * m_elements[0][1] + v.y() * m_elements[1][1] + v.z() * m_elements[2][1] + v.w() * m_elements[3][1], v.x() * m_elements[1][0] + v.y() * m_elements[1][1] + v.z() * m_elements[1][2] + v.w() * m_elements[1][3],
v.x() * m_elements[0][2] + v.y() * m_elements[1][2] + v.z() * m_elements[2][2] + v.w() * m_elements[3][2], v.x() * m_elements[2][0] + v.y() * m_elements[2][1] + v.z() * m_elements[2][2] + v.w() * m_elements[2][3],
v.x() * m_elements[0][3] + v.y() * m_elements[1][3] + v.z() * m_elements[2][3] + v.w() * m_elements[3][3]); v.x() * m_elements[3][0] + v.y() * m_elements[3][1] + v.z() * m_elements[3][2] + v.w() * m_elements[3][3]);
} }
constexpr Vector3<T> transform_point(const Vector3<T>& p) const constexpr Vector3<T> transform_point(const Vector3<T>& p) const
{ {
return Vector3<T>( return Vector3<T>(
p.x() * m_elements[0][0] + p.y() * m_elements[1][0] + p.z() * m_elements[2][0] + m_elements[3][0], p.x() * m_elements[0][0] + p.y() * m_elements[0][1] + p.z() * m_elements[0][2] + m_elements[0][3],
p.x() * m_elements[0][1] + p.y() * m_elements[1][1] + p.z() * m_elements[2][1] + m_elements[3][1], p.x() * m_elements[1][0] + p.y() * m_elements[1][1] + p.z() * m_elements[1][2] + m_elements[1][3],
p.x() * m_elements[0][2] + p.y() * m_elements[1][2] + p.z() * m_elements[2][2] + m_elements[3][2]); p.x() * m_elements[2][0] + p.y() * m_elements[2][1] + p.z() * m_elements[2][2] + m_elements[2][3]);
} }
constexpr static Matrix4x4 identity() constexpr static Matrix4x4 identity()
@ -76,10 +76,10 @@ public:
constexpr static Matrix4x4 translate(const Vector3<T>& p) constexpr static Matrix4x4 translate(const Vector3<T>& p)
{ {
return Matrix4x4( return Matrix4x4(
1, 0, 0, 0, 1, 0, 0, p.x(),
0, 1, 0, 0, 0, 1, 0, p.y(),
0, 0, 1, 0, 0, 0, 1, p.z(),
p.x(), p.y(), p.z(), 1); 0, 0, 0, 1);
} }
constexpr static Matrix4x4 scale(const Vector3<T>& s) constexpr static Matrix4x4 scale(const Vector3<T>& s)
@ -107,6 +107,17 @@ public:
0, 0, 0, 1); 0, 0, 0, 1);
} }
constexpr Matrix4x4 transpose() const
{
Matrix4x4 result;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
result.m_elements[i][j] = m_elements[j][i];
}
}
return result;
}
private: private:
T m_elements[4][4]; T m_elements[4][4];
}; };