Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
Matrix4x4.cpp
1/*
2Copyright (C) 2014-2019,2025,2026 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#include <cmath>
17#include <ostream>
18#include <iomanip>
21#include "aeongames/Vector3.hpp"
22#include "3DMath.h"
23
24namespace AeonGames
25{
26 static_assert ( sizeof ( Matrix4x4 ) == sizeof ( float ) * 16, "Size of Matrix4x4 is not the same as float[16]." );
31
32 Matrix4x4::Matrix4x4 ( const Transform& aTransform ) : Matrix4x4{ aTransform.GetMatrix() }
33 {
34 }
35
36 Matrix4x4::Matrix4x4 ( const float* const aMatrix4x4 )
37 {
38 memcpy ( mMatrix, aMatrix4x4, sizeof ( float ) * 16 );
39 }
40
41 Matrix4x4::Matrix4x4 ( const std::initializer_list<const float> aList )
42 {
43 const float* scalar = aList.begin();
44 for ( size_t i = 0; i < 16; ++i )
45 {
46 mMatrix[i] = ( scalar != aList.end() ) ? *scalar++ : ( i % 5 ) ? 0.0f : 1.0f;
47 }
48 }
49
51 = default;
52
53 const float* const Matrix4x4::GetMatrix4x4() const
54 {
55 return mMatrix;
56 }
57
59 {
61 return *this;
62 }
63
65 {
66 return Matrix4x4 ( *this ).Invert();
67 }
68
69 void Matrix4x4::Frustum ( float aLeft, float aRight, float aBottom, float aTop, float aNear, float aFar )
70 {
71 // glFrustum, +X right, +Y forward, +Z up
72 // X
73 mMatrix[0] = ( 2 * aNear ) / ( aRight - aLeft );
74 mMatrix[1] = 0.0f;
75 mMatrix[2] = 0.0f;
76 mMatrix[3] = 0.0f;
77
78 // Y
79 mMatrix[4] = - ( ( aRight + aLeft ) / ( aRight - aLeft ) );
80 mMatrix[5] = - ( ( aBottom + aTop ) / ( aBottom - aTop ) );
81 mMatrix[6] = ( ( aFar + aNear ) / ( aFar - aNear ) );
82 mMatrix[7] = 1.0f;
83
84 // Z
85 mMatrix[8] = 0.0f;
86 mMatrix[9] = ( 2 * aNear ) / ( aBottom - aTop );
87 mMatrix[10] = 0.0f;
88 mMatrix[11] = 0.0f;
89
90 // Pos
91 mMatrix[12] = 0.0f;
92 mMatrix[13] = 0.0f;
93 mMatrix[14] = - ( ( 2 * aFar * aNear ) / ( aFar - aNear ) );
94 mMatrix[15] = 0.0f;
95 }
96
97 void Matrix4x4::Ortho ( float aLeft, float aRight, float aBottom, float aTop, float aNear, float aFar )
98 {
100 // glOrtho, +Z up, +Y forward
101
102 // X
103 mMatrix[0] = ( 2.0f / ( aRight - aLeft ) );
104 mMatrix[1] = 0.0f;
105 mMatrix[2] = 0.0f;
106 mMatrix[3] = 0.0f;
107
108 // Y
109 mMatrix[4] = 0.0f;
110 mMatrix[5] = 0.0f;
111 mMatrix[6] = - ( 2.0f / ( aFar - aNear ) );
112 mMatrix[7] = 0.0f;
113
114 // Z
115 mMatrix[8] = 0.0f;
116 mMatrix[9] = ( 2.0f / ( aTop - aBottom ) );
117 mMatrix[10] = 0.0f;
118 mMatrix[11] = 0.0f;
119
120 // Pos
121 mMatrix[12] = - ( ( aRight + aLeft ) / ( aRight - aLeft ) );
122 mMatrix[13] = - ( ( aTop + aBottom ) / ( aTop - aBottom ) );
123 mMatrix[14] = - ( ( aFar + aNear ) / ( aFar - aNear ) );
124 mMatrix[15] = 1.0f;
125 }
126
127 void Matrix4x4::Perspective ( float aFieldOfVision, float aAspect, float aNear, float aFar )
128 {
129 float fH = std::tan ( aFieldOfVision * static_cast<float> ( M_PI ) / 360.0f ) * aNear;
130 float fW = fH * aAspect;
131 Frustum ( -fW, fW, -fH, fH, aNear, aFar );
132 }
133
134 Matrix4x4 & Matrix4x4::Rotate ( float angle, float x, float y, float z )
135 {
136 /*
137 This replicates how glRotatef works.
138 */
139 return *this *= GetRotationMatrix ( angle, x, y, z );
140 }
141
143 {
144 // Item 22 from MEC++
145 float local[16]
146 {
147 mMatrix[0], mMatrix[1], mMatrix[2], mMatrix[3],
148 mMatrix[4], mMatrix[5], mMatrix[6], mMatrix[7],
149 mMatrix[8], mMatrix[9], mMatrix[10], mMatrix[11],
150 mMatrix[12], mMatrix[13], mMatrix[14], mMatrix[15]
151 };
152 mMatrix[0] = local[0] * lhs.mMatrix[0] + local[4] * lhs.mMatrix[1] + local[8] * lhs.mMatrix[2] + local[12] * lhs.mMatrix[3];
153 mMatrix[1] = local[1] * lhs.mMatrix[0] + local[5] * lhs.mMatrix[1] + local[9] * lhs.mMatrix[2] + local[13] * lhs.mMatrix[3];
154 mMatrix[2] = local[2] * lhs.mMatrix[0] + local[6] * lhs.mMatrix[1] + local[10] * lhs.mMatrix[2] + local[14] * lhs.mMatrix[3];
155 mMatrix[3] = local[3] * lhs.mMatrix[0] + local[7] * lhs.mMatrix[1] + local[11] * lhs.mMatrix[2] + local[15] * lhs.mMatrix[3];
156
157 mMatrix[4] = local[0] * lhs.mMatrix[4] + local[4] * lhs.mMatrix[5] + local[8] * lhs.mMatrix[6] + local[12] * lhs.mMatrix[7];
158 mMatrix[5] = local[1] * lhs.mMatrix[4] + local[5] * lhs.mMatrix[5] + local[9] * lhs.mMatrix[6] + local[13] * lhs.mMatrix[7];
159 mMatrix[6] = local[2] * lhs.mMatrix[4] + local[6] * lhs.mMatrix[5] + local[10] * lhs.mMatrix[6] + local[14] * lhs.mMatrix[7];
160 mMatrix[7] = local[3] * lhs.mMatrix[4] + local[7] * lhs.mMatrix[5] + local[11] * lhs.mMatrix[6] + local[15] * lhs.mMatrix[7];
161
162 mMatrix[8] = local[0] * lhs.mMatrix[8] + local[4] * lhs.mMatrix[9] + local[8] * lhs.mMatrix[10] + local[12] * lhs.mMatrix[11];
163 mMatrix[9] = local[1] * lhs.mMatrix[8] + local[5] * lhs.mMatrix[9] + local[9] * lhs.mMatrix[10] + local[13] * lhs.mMatrix[11];
164 mMatrix[10] = local[2] * lhs.mMatrix[8] + local[6] * lhs.mMatrix[9] + local[10] * lhs.mMatrix[10] + local[14] * lhs.mMatrix[11];
165 mMatrix[11] = local[3] * lhs.mMatrix[8] + local[7] * lhs.mMatrix[9] + local[11] * lhs.mMatrix[10] + local[15] * lhs.mMatrix[11];
166
167 mMatrix[12] = local[0] * lhs.mMatrix[12] + local[4] * lhs.mMatrix[13] + local[8] * lhs.mMatrix[14] + local[12] * lhs.mMatrix[15];
168 mMatrix[13] = local[1] * lhs.mMatrix[12] + local[5] * lhs.mMatrix[13] + local[9] * lhs.mMatrix[14] + local[13] * lhs.mMatrix[15];
169 mMatrix[14] = local[2] * lhs.mMatrix[12] + local[6] * lhs.mMatrix[13] + local[10] * lhs.mMatrix[14] + local[14] * lhs.mMatrix[15];
170 mMatrix[15] = local[3] * lhs.mMatrix[12] + local[7] * lhs.mMatrix[13] + local[11] * lhs.mMatrix[14] + local[15] * lhs.mMatrix[15];
171 return *this;
172 }
173
174 const float Matrix4x4::operator[] ( size_t aIndex ) const
175 {
176 assert ( aIndex < 16 );
177 return mMatrix[aIndex];
178 }
179
180 const Matrix4x4 Matrix4x4::GetRotationMatrix ( float angle, float x, float y, float z )
181 {
182 auto radians = float ( ( angle / 180.0f ) * M_PI );
183 float c = cosf ( radians );
184 float s = sinf ( radians );
185 return Matrix4x4
186 {
187 x * x * ( 1 - c ) + c,
188 x * y * ( 1 - c ) - z * s,
189 x * z * ( 1 - c ) + y * s,
190 0,
191 y * x * ( 1 - c ) + z * s,
192 y * y * ( 1 - c ) + c,
193 y * z * ( 1 - c ) - x * s,
194 0,
195 x * z * ( 1 - c ) - y * s,
196 y * z * ( 1 - c ) + x * s,
197 z * z * ( 1 - c ) + c,
198 0,
199 0, 0, 0, 1
200 };
201 }
202
203 const Matrix4x4 operator* ( const Matrix4x4& lhs, const Matrix4x4& rhs )
204 {
205 /* Here Matrix4x4(lhs) *MAY* mean cast away constness
206 rather tan create a temporary object in some compilers,
207 we want the temporary, NOT the cast.*/
208 return Matrix4x4 ( lhs ) *= rhs;
209 }
210
211 const Vector3 operator* ( const Matrix4x4 & lhs, const Vector3 & rhs )
212 {
213 return Vector3
214 {
215 rhs[0] * lhs[0] + rhs[1] * lhs[4] + rhs[2] * lhs[8] + lhs[12],
216 rhs[0] * lhs[1] + rhs[1] * lhs[5] + rhs[2] * lhs[9] + lhs[13],
217 rhs[0] * lhs[2] + rhs[1] * lhs[6] + rhs[2] * lhs[10] + lhs[14]
218 };
219 }
220
221 const bool operator== ( const Matrix4x4& lhs, const Matrix4x4& rhs )
222 {
223 return memcmp ( lhs.GetMatrix4x4(), rhs.GetMatrix4x4(), sizeof ( float ) * 16 ) == 0;
224 }
225
226 const Matrix4x4 Abs ( const Matrix4x4& aMatrix4x4 )
227 {
228 return Matrix4x4
229 {
230 std::abs ( aMatrix4x4[0] ),
231 std::abs ( aMatrix4x4[1] ),
232 std::abs ( aMatrix4x4[2] ),
233 std::abs ( aMatrix4x4[3] ),
234 std::abs ( aMatrix4x4[4] ),
235 std::abs ( aMatrix4x4[5] ),
236 std::abs ( aMatrix4x4[6] ),
237 std::abs ( aMatrix4x4[7] ),
238 std::abs ( aMatrix4x4[8] ),
239 std::abs ( aMatrix4x4[9] ),
240 std::abs ( aMatrix4x4[10] ),
241 std::abs ( aMatrix4x4[11] ),
242 std::abs ( aMatrix4x4[12] ),
243 std::abs ( aMatrix4x4[13] ),
244 std::abs ( aMatrix4x4[14] ),
245 std::abs ( aMatrix4x4[15] )
246 };
247 }
248
249 std::ostream& operator<< ( std::ostream& os, const Matrix4x4& aMatrix )
250 {
251 const float* m = aMatrix.GetMatrix4x4();
252 os << std::fixed << std::setprecision ( 4 );
253 os << "[\n";
254 for ( int row = 0; row < 4; ++row )
255 {
256 os << " [ ";
257 for ( int col = 0; col < 4; ++col )
258 {
259 os << std::setw ( 10 ) << m[col * 4 + row];
260 if ( col < 3 ) os << ", ";
261 }
262 os << " ]\n";
263 }
264 os << "]";
265 return os;
266 }
267
268 const Matrix4x4 Matrix4x4::Identity{};
269}
Inline functions related to 3D Math.
float * SetIdentityMatrix4x4(float *M)
Set a matrix to the Identity.
Definition 3DMath.h:410
float * InvertMatrix(float *mat, float *dest)
Invert a 4x4 matrix.
Definition 3DMath.h:637
Header for 4x4 matrix class.
Header for Transform component class.
Header for the 3D vector class.
4 by 4 matrix in colum mayor order.
Definition Matrix4x4.hpp:35
DLL const float *const GetMatrix4x4() const
Get a pointer to the internal matrix data.
Definition Matrix4x4.cpp:53
DLL Matrix4x4()
Default constructor.
Definition Matrix4x4.cpp:27
DLL void Frustum(float aLeft, float aRight, float aBottom, float aTop, float aNear, float aFar)
Set up a perspective projection matrix defined by a frustum.
Definition Matrix4x4.cpp:69
DLL void Perspective(float aFieldOfVision, float aAspect, float aNear, float aFar)
Set up a symmetric perspective projection matrix.
DLL const float operator[](size_t aIndex) const
Access a matrix element by index.
static DLL const Matrix4x4 GetRotationMatrix(float angle, float x, float y, float z)
Constructs the rotation matrix defined by the axis-angle provided.
DLL Matrix4x4 & operator*=(const Matrix4x4 &lhs)
Multiply this matrix by another matrix.
DLL const Matrix4x4 GetInvertedMatrix4x4()
Get the inverted matrix.
Definition Matrix4x4.cpp:64
float mMatrix[16]
Lineal row mayor matrix.
DLL Matrix4x4 & Invert()
Invert this matrix in place.
Definition Matrix4x4.cpp:58
static DLL const Matrix4x4 Identity
The 4x4 identity matrix constant.
DLL void Ortho(float aLeft, float aRight, float aBottom, float aTop, float aNear, float aFar)
Set up an orthographic projection matrix.
Definition Matrix4x4.cpp:97
DLL ~Matrix4x4()
destructor.
DLL Matrix4x4 & Rotate(float angle, float x, float y, float z)
Apply a rotation to this matrix.
Component class for any object that requires space transformations.
Definition Transform.hpp:34
3D vector class.
Definition Vector3.hpp:32
<- This is here just for the literals
Definition AABB.hpp:31
std::ostream & operator<<(std::ostream &os, LogLevel level)
Inserts a color-coded log level tag into an output stream.
Definition LogLevel.hpp:40
DLL const Matrix3x3 operator*(const Matrix3x3 &lhs, const Matrix3x3 &rhs)
Multiplies two 3x3 matrices. Multiplies two 3x3 matrices.
DLL const Matrix3x3 Abs(const Matrix3x3 &aMatrix3x3)
Compute the element-wise absolute value of a matrix.
DLL const bool operator==(const Matrix3x3 &lhs, const Matrix3x3 &rhs)
Compare two 3x3 matrices for equality.