2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined( INCLUDED_MATH_MATRIX_H )
23 #define INCLUDED_MATH_MATRIX_H
26 /// \brief Matrix data types and related operations.
28 #include "math/vector.h"
30 /// \brief A 4x4 matrix stored in single-precision floating-point.
38 Matrix4( float xx_, float xy_, float xz_, float xw_,
39 float yx_, float yy_, float yz_, float yw_,
40 float zx_, float zy_, float zz_, float zw_,
41 float tx_, float ty_, float tz_, float tw_ ){
63 const float& xx() const {
69 const float& xy() const {
75 const float& xz() const {
81 const float& xw() const {
87 const float& yx() const {
93 const float& yy() const {
99 const float& yz() const {
100 return m_elements[6];
103 return m_elements[7];
105 const float& yw() const {
106 return m_elements[7];
109 return m_elements[8];
111 const float& zx() const {
112 return m_elements[8];
115 return m_elements[9];
117 const float& zy() const {
118 return m_elements[9];
121 return m_elements[10];
123 const float& zz() const {
124 return m_elements[10];
127 return m_elements[11];
129 const float& zw() const {
130 return m_elements[11];
133 return m_elements[12];
135 const float& tx() const {
136 return m_elements[12];
139 return m_elements[13];
141 const float& ty() const {
142 return m_elements[13];
145 return m_elements[14];
147 const float& tz() const {
148 return m_elements[14];
151 return m_elements[15];
153 const float& tw() const {
154 return m_elements[15];
158 return reinterpret_cast<Vector4&>( xx() );
160 const Vector4& x() const {
161 return reinterpret_cast<const Vector4&>( xx() );
164 return reinterpret_cast<Vector4&>( yx() );
166 const Vector4& y() const {
167 return reinterpret_cast<const Vector4&>( yx() );
170 return reinterpret_cast<Vector4&>( zx() );
172 const Vector4& z() const {
173 return reinterpret_cast<const Vector4&>( zx() );
176 return reinterpret_cast<Vector4&>( tx() );
178 const Vector4& t() const {
179 return reinterpret_cast<const Vector4&>( tx() );
182 const float& index( std::size_t i ) const {
183 return m_elements[i];
185 float& index( std::size_t i ){
186 return m_elements[i];
188 const float& operator[]( std::size_t i ) const {
189 return m_elements[i];
191 float& operator[]( std::size_t i ){
192 return m_elements[i];
194 const float& index( std::size_t r, std::size_t c ) const {
195 return m_elements[( r << 2 ) + c];
197 float& index( std::size_t r, std::size_t c ){
198 return m_elements[( r << 2 ) + c];
202 /// \brief The 4x4 identity matrix.
203 const Matrix4 g_matrix4_identity(
211 /// \brief Returns true if \p self and \p other are exactly element-wise equal.
212 inline bool operator==( const Matrix4& self, const Matrix4& other ){
213 return self.xx() == other.xx() && self.xy() == other.xy() && self.xz() == other.xz() && self.xw() == other.xw()
214 && self.yx() == other.yx() && self.yy() == other.yy() && self.yz() == other.yz() && self.yw() == other.yw()
215 && self.zx() == other.zx() && self.zy() == other.zy() && self.zz() == other.zz() && self.zw() == other.zw()
216 && self.tx() == other.tx() && self.ty() == other.ty() && self.tz() == other.tz() && self.tw() == other.tw();
219 /// \brief Returns true if \p self and \p other are exactly element-wise equal.
220 inline bool matrix4_equal( const Matrix4& self, const Matrix4& other ){
221 return self == other;
224 /// \brief Returns true if \p self and \p other are element-wise equal within \p epsilon.
225 inline bool matrix4_equal_epsilon( const Matrix4& self, const Matrix4& other, float epsilon ){
226 return float_equal_epsilon( self.xx(), other.xx(), epsilon )
227 && float_equal_epsilon( self.xy(), other.xy(), epsilon )
228 && float_equal_epsilon( self.xz(), other.xz(), epsilon )
229 && float_equal_epsilon( self.xw(), other.xw(), epsilon )
230 && float_equal_epsilon( self.yx(), other.yx(), epsilon )
231 && float_equal_epsilon( self.yy(), other.yy(), epsilon )
232 && float_equal_epsilon( self.yz(), other.yz(), epsilon )
233 && float_equal_epsilon( self.yw(), other.yw(), epsilon )
234 && float_equal_epsilon( self.zx(), other.zx(), epsilon )
235 && float_equal_epsilon( self.zy(), other.zy(), epsilon )
236 && float_equal_epsilon( self.zz(), other.zz(), epsilon )
237 && float_equal_epsilon( self.zw(), other.zw(), epsilon )
238 && float_equal_epsilon( self.tx(), other.tx(), epsilon )
239 && float_equal_epsilon( self.ty(), other.ty(), epsilon )
240 && float_equal_epsilon( self.tz(), other.tz(), epsilon )
241 && float_equal_epsilon( self.tw(), other.tw(), epsilon );
244 /// \brief Returns true if \p self and \p other are exactly element-wise equal.
245 /// \p self and \p other must be affine.
246 inline bool matrix4_affine_equal( const Matrix4& self, const Matrix4& other ){
247 return self[0] == other[0]
248 && self[1] == other[1]
249 && self[2] == other[2]
250 && self[4] == other[4]
251 && self[5] == other[5]
252 && self[6] == other[6]
253 && self[8] == other[8]
254 && self[9] == other[9]
255 && self[10] == other[10]
256 && self[12] == other[12]
257 && self[13] == other[13]
258 && self[14] == other[14];
261 enum Matrix4Handedness
263 MATRIX4_RIGHTHANDED = 0,
264 MATRIX4_LEFTHANDED = 1,
267 /// \brief Returns MATRIX4_RIGHTHANDED if \p self is right-handed, else returns MATRIX4_LEFTHANDED.
268 inline Matrix4Handedness matrix4_handedness( const Matrix4& self ){
271 vector3_cross( vector4_to_vector3( self.x() ), vector4_to_vector3( self.y() ) ),
272 vector4_to_vector3( self.z() )
275 ) ? MATRIX4_LEFTHANDED : MATRIX4_RIGHTHANDED;
282 /// \brief Returns \p self post-multiplied by \p other.
283 inline Matrix4 matrix4_multiplied_by_matrix4( const Matrix4& self, const Matrix4& other ){
285 other[0] * self[0] + other[1] * self[4] + other[2] * self[8] + other[3] * self[12],
286 other[0] * self[1] + other[1] * self[5] + other[2] * self[9] + other[3] * self[13],
287 other[0] * self[2] + other[1] * self[6] + other[2] * self[10] + other[3] * self[14],
288 other[0] * self[3] + other[1] * self[7] + other[2] * self[11] + other[3] * self[15],
289 other[4] * self[0] + other[5] * self[4] + other[6] * self[8] + other[7] * self[12],
290 other[4] * self[1] + other[5] * self[5] + other[6] * self[9] + other[7] * self[13],
291 other[4] * self[2] + other[5] * self[6] + other[6] * self[10] + other[7] * self[14],
292 other[4] * self[3] + other[5] * self[7] + other[6] * self[11] + other[7] * self[15],
293 other[8] * self[0] + other[9] * self[4] + other[10] * self[8] + other[11] * self[12],
294 other[8] * self[1] + other[9] * self[5] + other[10] * self[9] + other[11] * self[13],
295 other[8] * self[2] + other[9] * self[6] + other[10] * self[10] + other[11] * self[14],
296 other[8] * self[3] + other[9] * self[7] + other[10] * self[11] + other[11] * self[15],
297 other[12] * self[0] + other[13] * self[4] + other[14] * self[8] + other[15] * self[12],
298 other[12] * self[1] + other[13] * self[5] + other[14] * self[9] + other[15] * self[13],
299 other[12] * self[2] + other[13] * self[6] + other[14] * self[10] + other[15] * self[14],
300 other[12] * self[3] + other[13] * self[7] + other[14] * self[11] + other[15] * self[15]
304 /// \brief Post-multiplies \p self by \p other in-place.
305 inline void matrix4_multiply_by_matrix4( Matrix4& self, const Matrix4& other ){
306 self = matrix4_multiplied_by_matrix4( self, other );
310 /// \brief Returns \p self pre-multiplied by \p other.
311 inline Matrix4 matrix4_premultiplied_by_matrix4( const Matrix4& self, const Matrix4& other ){
313 return matrix4_multiplied_by_matrix4( other, self );
316 self[0] * other[0] + self[1] * other[4] + self[2] * other[8] + self[3] * other[12],
317 self[0] * other[1] + self[1] * other[5] + self[2] * other[9] + self[3] * other[13],
318 self[0] * other[2] + self[1] * other[6] + self[2] * other[10] + self[3] * other[14],
319 self[0] * other[3] + self[1] * other[7] + self[2] * other[11] + self[3] * other[15],
320 self[4] * other[0] + self[5] * other[4] + self[6] * other[8] + self[7] * other[12],
321 self[4] * other[1] + self[5] * other[5] + self[6] * other[9] + self[7] * other[13],
322 self[4] * other[2] + self[5] * other[6] + self[6] * other[10] + self[7] * other[14],
323 self[4] * other[3] + self[5] * other[7] + self[6] * other[11] + self[7] * other[15],
324 self[8] * other[0] + self[9] * other[4] + self[10] * other[8] + self[11] * other[12],
325 self[8] * other[1] + self[9] * other[5] + self[10] * other[9] + self[11] * other[13],
326 self[8] * other[2] + self[9] * other[6] + self[10] * other[10] + self[11] * other[14],
327 self[8] * other[3] + self[9] * other[7] + self[10] * other[11] + self[11] * other[15],
328 self[12] * other[0] + self[13] * other[4] + self[14] * other[8] + self[15] * other[12],
329 self[12] * other[1] + self[13] * other[5] + self[14] * other[9] + self[15] * other[13],
330 self[12] * other[2] + self[13] * other[6] + self[14] * other[10] + self[15] * other[14],
331 self[12] * other[3] + self[13] * other[7] + self[14] * other[11] + self[15] * other[15]
336 /// \brief Pre-multiplies \p self by \p other in-place.
337 inline void matrix4_premultiply_by_matrix4( Matrix4& self, const Matrix4& other ){
338 self = matrix4_premultiplied_by_matrix4( self, other );
341 /// \brief returns true if \p transform is affine.
342 inline bool matrix4_is_affine( const Matrix4& transform ){
343 return transform[3] == 0 && transform[7] == 0 && transform[11] == 0 && transform[15] == 1;
346 /// \brief Returns \p self post-multiplied by \p other.
347 /// \p self and \p other must be affine.
348 inline Matrix4 matrix4_affine_multiplied_by_matrix4( const Matrix4& self, const Matrix4& other ){
350 other[0] * self[0] + other[1] * self[4] + other[2] * self[8],
351 other[0] * self[1] + other[1] * self[5] + other[2] * self[9],
352 other[0] * self[2] + other[1] * self[6] + other[2] * self[10],
354 other[4] * self[0] + other[5] * self[4] + other[6] * self[8],
355 other[4] * self[1] + other[5] * self[5] + other[6] * self[9],
356 other[4] * self[2] + other[5] * self[6] + other[6] * self[10],
358 other[8] * self[0] + other[9] * self[4] + other[10] * self[8],
359 other[8] * self[1] + other[9] * self[5] + other[10] * self[9],
360 other[8] * self[2] + other[9] * self[6] + other[10] * self[10],
362 other[12] * self[0] + other[13] * self[4] + other[14] * self[8] + self[12],
363 other[12] * self[1] + other[13] * self[5] + other[14] * self[9] + self[13],
364 other[12] * self[2] + other[13] * self[6] + other[14] * self[10] + self[14],
369 /// \brief Post-multiplies \p self by \p other in-place.
370 /// \p self and \p other must be affine.
371 inline void matrix4_affine_multiply_by_matrix4( Matrix4& self, const Matrix4& other ){
372 self = matrix4_affine_multiplied_by_matrix4( self, other );
375 /// \brief Returns \p self pre-multiplied by \p other.
376 /// \p self and \p other must be affine.
377 inline Matrix4 matrix4_affine_premultiplied_by_matrix4( const Matrix4& self, const Matrix4& other ){
379 return matrix4_affine_multiplied_by_matrix4( other, self );
382 self[0] * other[0] + self[1] * other[4] + self[2] * other[8],
383 self[0] * other[1] + self[1] * other[5] + self[2] * other[9],
384 self[0] * other[2] + self[1] * other[6] + self[2] * other[10],
386 self[4] * other[0] + self[5] * other[4] + self[6] * other[8],
387 self[4] * other[1] + self[5] * other[5] + self[6] * other[9],
388 self[4] * other[2] + self[5] * other[6] + self[6] * other[10],
390 self[8] * other[0] + self[9] * other[4] + self[10] * other[8],
391 self[8] * other[1] + self[9] * other[5] + self[10] * other[9],
392 self[8] * other[2] + self[9] * other[6] + self[10] * other[10],
394 self[12] * other[0] + self[13] * other[4] + self[14] * other[8] + other[12],
395 self[12] * other[1] + self[13] * other[5] + self[14] * other[9] + other[13],
396 self[12] * other[2] + self[13] * other[6] + self[14] * other[10] + other[14],
403 /// \brief Pre-multiplies \p self by \p other in-place.
404 /// \p self and \p other must be affine.
405 inline void matrix4_affine_premultiply_by_matrix4( Matrix4& self, const Matrix4& other ){
406 self = matrix4_affine_premultiplied_by_matrix4( self, other );
409 /// \brief Returns \p point transformed by \p self.
410 template<typename Element>
411 inline BasicVector3<Element> matrix4_transformed_point( const Matrix4& self, const BasicVector3<Element>& point ){
412 return BasicVector3<Element>(
413 static_cast<Element>( self[0] * point[0] + self[4] * point[1] + self[8] * point[2] + self[12] ),
414 static_cast<Element>( self[1] * point[0] + self[5] * point[1] + self[9] * point[2] + self[13] ),
415 static_cast<Element>( self[2] * point[0] + self[6] * point[1] + self[10] * point[2] + self[14] )
419 /// \brief Transforms \p point by \p self in-place.
420 template<typename Element>
421 inline void matrix4_transform_point( const Matrix4& self, BasicVector3<Element>& point ){
422 point = matrix4_transformed_point( self, point );
425 /// \brief Returns \p direction transformed by \p self.
426 template<typename Element>
427 inline BasicVector3<Element> matrix4_transformed_direction( const Matrix4& self, const BasicVector3<Element>& direction ){
428 return BasicVector3<Element>(
429 static_cast<Element>( self[0] * direction[0] + self[4] * direction[1] + self[8] * direction[2] ),
430 static_cast<Element>( self[1] * direction[0] + self[5] * direction[1] + self[9] * direction[2] ),
431 static_cast<Element>( self[2] * direction[0] + self[6] * direction[1] + self[10] * direction[2] )
435 /// \brief Transforms \p direction by \p self in-place.
436 template<typename Element>
437 inline void matrix4_transform_direction( const Matrix4& self, BasicVector3<Element>& normal ){
438 normal = matrix4_transformed_direction( self, normal );
441 /// \brief Returns \p vector4 transformed by \p self.
442 inline Vector4 matrix4_transformed_vector4( const Matrix4& self, const Vector4& vector4 ){
444 self[0] * vector4[0] + self[4] * vector4[1] + self[8] * vector4[2] + self[12] * vector4[3],
445 self[1] * vector4[0] + self[5] * vector4[1] + self[9] * vector4[2] + self[13] * vector4[3],
446 self[2] * vector4[0] + self[6] * vector4[1] + self[10] * vector4[2] + self[14] * vector4[3],
447 self[3] * vector4[0] + self[7] * vector4[1] + self[11] * vector4[2] + self[15] * vector4[3]
451 /// \brief Transforms \p vector4 by \p self in-place.
452 inline void matrix4_transform_vector4( const Matrix4& self, Vector4& vector4 ){
453 vector4 = matrix4_transformed_vector4( self, vector4 );
457 /// \brief Transposes \p self in-place.
458 inline void matrix4_transpose( Matrix4& self ){
459 std::swap( self.xy(), self.yx() );
460 std::swap( self.xz(), self.zx() );
461 std::swap( self.xw(), self.tx() );
462 std::swap( self.yz(), self.zy() );
463 std::swap( self.yw(), self.ty() );
464 std::swap( self.zw(), self.tz() );
467 /// \brief Returns \p self transposed.
468 inline Matrix4 matrix4_transposed( const Matrix4& self ){
490 /// \brief Inverts an affine transform in-place.
491 /// Adapted from Graphics Gems 2.
492 inline Matrix4 matrix4_affine_inverse( const Matrix4& self ){
495 // determinant of rotation submatrix
497 = self[0] * ( self[5] * self[10] - self[9] * self[6] )
498 - self[1] * ( self[4] * self[10] - self[8] * self[6] )
499 + self[2] * ( self[4] * self[9] - self[8] * self[5] );
501 // throw exception here if (det*det < 1e-25)
503 // invert rotation submatrix
506 result[0] = static_cast<float>( ( self[5] * self[10] - self[6] * self[9] ) * det );
507 result[1] = static_cast<float>( -( self[1] * self[10] - self[2] * self[9] ) * det );
508 result[2] = static_cast<float>( ( self[1] * self[6] - self[2] * self[5] ) * det );
510 result[4] = static_cast<float>( -( self[4] * self[10] - self[6] * self[8] ) * det );
511 result[5] = static_cast<float>( ( self[0] * self[10] - self[2] * self[8] ) * det );
512 result[6] = static_cast<float>( -( self[0] * self[6] - self[2] * self[4] ) * det );
514 result[8] = static_cast<float>( ( self[4] * self[9] - self[5] * self[8] ) * det );
515 result[9] = static_cast<float>( -( self[0] * self[9] - self[1] * self[8] ) * det );
516 result[10] = static_cast<float>( ( self[0] * self[5] - self[1] * self[4] ) * det );
519 // multiply translation part by rotation
520 result[12] = -( self[12] * result[0] +
521 self[13] * result[4] +
522 self[14] * result[8] );
523 result[13] = -( self[12] * result[1] +
524 self[13] * result[5] +
525 self[14] * result[9] );
526 result[14] = -( self[12] * result[2] +
527 self[13] * result[6] +
528 self[14] * result[10] );
534 inline void matrix4_affine_invert( Matrix4& self ){
535 self = matrix4_affine_inverse( self );
538 /// \brief A compile-time-constant integer.
540 struct IntegralConstant
542 enum unnamed_ { VALUE = VALUE_ };
545 /// \brief A compile-time-constant row/column index into a 4x4 matrix.
546 template<typename Row, typename Col>
550 typedef IntegralConstant<Row::VALUE> r;
551 typedef IntegralConstant<Col::VALUE> c;
552 typedef IntegralConstant<( r::VALUE * 4 ) + c::VALUE> i;
555 /// \brief A functor which returns the cofactor of a 3x3 submatrix obtained by ignoring a given row and column of a 4x4 matrix.
556 /// \param Row Defines the compile-time-constant integers x, y and z with values corresponding to the indices of the three rows to use.
557 /// \param Col Defines the compile-time-constant integers x, y and z with values corresponding to the indices of the three columns to use.
558 template<typename Row, typename Col>
559 class Matrix4Cofactor
562 typedef typename Matrix4Index<typename Row::x, typename Col::x>::i xx;
563 typedef typename Matrix4Index<typename Row::x, typename Col::y>::i xy;
564 typedef typename Matrix4Index<typename Row::x, typename Col::z>::i xz;
565 typedef typename Matrix4Index<typename Row::y, typename Col::x>::i yx;
566 typedef typename Matrix4Index<typename Row::y, typename Col::y>::i yy;
567 typedef typename Matrix4Index<typename Row::y, typename Col::z>::i yz;
568 typedef typename Matrix4Index<typename Row::z, typename Col::x>::i zx;
569 typedef typename Matrix4Index<typename Row::z, typename Col::y>::i zy;
570 typedef typename Matrix4Index<typename Row::z, typename Col::z>::i zz;
571 static double apply( const Matrix4& self ){
572 return self[xx::VALUE] * ( self[yy::VALUE] * self[zz::VALUE] - self[zy::VALUE] * self[yz::VALUE] )
573 - self[xy::VALUE] * ( self[yx::VALUE] * self[zz::VALUE] - self[zx::VALUE] * self[yz::VALUE] )
574 + self[xz::VALUE] * ( self[yx::VALUE] * self[zy::VALUE] - self[zx::VALUE] * self[yy::VALUE] );
578 /// \brief The cofactor element indices for a 4x4 matrix row or column.
579 /// \param Element The index of the element to ignore.
580 template<int Element>
584 typedef IntegralConstant<( Element <= 0 ) ? 1 : 0> x;
585 typedef IntegralConstant<( Element <= 1 ) ? 2 : 1> y;
586 typedef IntegralConstant<( Element <= 2 ) ? 3 : 2> z;
589 /// \brief Returns the determinant of \p self.
590 inline double matrix4_determinant( const Matrix4& self ){
591 return self.xx() * Matrix4Cofactor< Cofactor4<0>, Cofactor4<0> >::apply( self )
592 - self.xy() * Matrix4Cofactor< Cofactor4<0>, Cofactor4<1> >::apply( self )
593 + self.xz() * Matrix4Cofactor< Cofactor4<0>, Cofactor4<2> >::apply( self )
594 - self.xw() * Matrix4Cofactor< Cofactor4<0>, Cofactor4<3> >::apply( self );
597 /// \brief Returns the inverse of \p self using the Adjoint method.
598 /// \todo Throw an exception if the determinant is zero.
599 inline Matrix4 matrix4_full_inverse( const Matrix4& self ){
600 double determinant = 1.0 / matrix4_determinant( self );
603 static_cast<float>( Matrix4Cofactor< Cofactor4<0>, Cofactor4<0> >::apply( self ) * determinant ),
604 static_cast<float>( -Matrix4Cofactor< Cofactor4<1>, Cofactor4<0> >::apply( self ) * determinant ),
605 static_cast<float>( Matrix4Cofactor< Cofactor4<2>, Cofactor4<0> >::apply( self ) * determinant ),
606 static_cast<float>( -Matrix4Cofactor< Cofactor4<3>, Cofactor4<0> >::apply( self ) * determinant ),
607 static_cast<float>( -Matrix4Cofactor< Cofactor4<0>, Cofactor4<1> >::apply( self ) * determinant ),
608 static_cast<float>( Matrix4Cofactor< Cofactor4<1>, Cofactor4<1> >::apply( self ) * determinant ),
609 static_cast<float>( -Matrix4Cofactor< Cofactor4<2>, Cofactor4<1> >::apply( self ) * determinant ),
610 static_cast<float>( Matrix4Cofactor< Cofactor4<3>, Cofactor4<1> >::apply( self ) * determinant ),
611 static_cast<float>( Matrix4Cofactor< Cofactor4<0>, Cofactor4<2> >::apply( self ) * determinant ),
612 static_cast<float>( -Matrix4Cofactor< Cofactor4<1>, Cofactor4<2> >::apply( self ) * determinant ),
613 static_cast<float>( Matrix4Cofactor< Cofactor4<2>, Cofactor4<2> >::apply( self ) * determinant ),
614 static_cast<float>( -Matrix4Cofactor< Cofactor4<3>, Cofactor4<2> >::apply( self ) * determinant ),
615 static_cast<float>( -Matrix4Cofactor< Cofactor4<0>, Cofactor4<3> >::apply( self ) * determinant ),
616 static_cast<float>( Matrix4Cofactor< Cofactor4<1>, Cofactor4<3> >::apply( self ) * determinant ),
617 static_cast<float>( -Matrix4Cofactor< Cofactor4<2>, Cofactor4<3> >::apply( self ) * determinant ),
618 static_cast<float>( Matrix4Cofactor< Cofactor4<3>, Cofactor4<3> >::apply( self ) * determinant )
622 /// \brief Inverts \p self in-place using the Adjoint method.
623 inline void matrix4_full_invert( Matrix4& self ){
624 self = matrix4_full_inverse( self );
628 /// \brief Constructs a pure-translation matrix from \p translation.
629 inline Matrix4 matrix4_translation_for_vec3( const Vector3& translation ){
634 translation[0], translation[1], translation[2], 1
638 /// \brief Returns the translation part of \p self.
639 inline Vector3 matrix4_get_translation_vec3( const Matrix4& self ){
640 return vector4_to_vector3( self.t() );
643 /// \brief Concatenates \p self with \p translation.
644 /// The concatenated \p translation occurs before \p self.
645 inline void matrix4_translate_by_vec3( Matrix4& self, const Vector3& translation ){
646 matrix4_multiply_by_matrix4( self, matrix4_translation_for_vec3( translation ) );
649 /// \brief Returns \p self Concatenated with \p translation.
650 /// The concatenated translation occurs before \p self.
651 inline Matrix4 matrix4_translated_by_vec3( const Matrix4& self, const Vector3& translation ){
652 return matrix4_multiplied_by_matrix4( self, matrix4_translation_for_vec3( translation ) );
658 /// \brief Returns \p angle modulated by the range [0, 360).
659 /// \p angle must be in the range [-360, 360).
660 inline float angle_modulate_degrees_range( float angle ){
661 return static_cast<float>( float_mod_range( angle, 360.0 ) );
664 /// \brief Returns \p euler angles converted from radians to degrees.
665 inline Vector3 euler_radians_to_degrees( const Vector3& euler ){
667 static_cast<float>( radians_to_degrees( euler.x() ) ),
668 static_cast<float>( radians_to_degrees( euler.y() ) ),
669 static_cast<float>( radians_to_degrees( euler.z() ) )
673 /// \brief Returns \p euler angles converted from degrees to radians.
674 inline Vector3 euler_degrees_to_radians( const Vector3& euler ){
676 static_cast<float>( degrees_to_radians( euler.x() ) ),
677 static_cast<float>( degrees_to_radians( euler.y() ) ),
678 static_cast<float>( degrees_to_radians( euler.z() ) )
684 /// \brief Constructs a pure-rotation matrix about the x axis from sin \p s and cosine \p c of an angle.
685 inline Matrix4 matrix4_rotation_for_sincos_x( float s, float c ){
694 /// \brief Constructs a pure-rotation matrix about the x axis from an angle in radians.
695 inline Matrix4 matrix4_rotation_for_x( double x ){
696 return matrix4_rotation_for_sincos_x( static_cast<float>( sin( x ) ), static_cast<float>( cos( x ) ) );
699 /// \brief Constructs a pure-rotation matrix about the x axis from an angle in degrees.
700 inline Matrix4 matrix4_rotation_for_x_degrees( float x ){
701 return matrix4_rotation_for_x( degrees_to_radians( x ) );
704 /// \brief Constructs a pure-rotation matrix about the y axis from sin \p s and cosine \p c of an angle.
705 inline Matrix4 matrix4_rotation_for_sincos_y( float s, float c ){
714 /// \brief Constructs a pure-rotation matrix about the y axis from an angle in radians.
715 inline Matrix4 matrix4_rotation_for_y( double y ){
716 return matrix4_rotation_for_sincos_y( static_cast<float>( sin( y ) ), static_cast<float>( cos( y ) ) );
719 /// \brief Constructs a pure-rotation matrix about the y axis from an angle in degrees.
720 inline Matrix4 matrix4_rotation_for_y_degrees( float y ){
721 return matrix4_rotation_for_y( degrees_to_radians( y ) );
724 /// \brief Constructs a pure-rotation matrix about the z axis from sin \p s and cosine \p c of an angle.
725 inline Matrix4 matrix4_rotation_for_sincos_z( float s, float c ){
734 /// \brief Constructs a pure-rotation matrix about the z axis from an angle in radians.
735 inline Matrix4 matrix4_rotation_for_z( double z ){
736 return matrix4_rotation_for_sincos_z( static_cast<float>( sin( z ) ), static_cast<float>( cos( z ) ) );
739 /// \brief Constructs a pure-rotation matrix about the z axis from an angle in degrees.
740 inline Matrix4 matrix4_rotation_for_z_degrees( float z ){
741 return matrix4_rotation_for_z( degrees_to_radians( z ) );
744 /// \brief Constructs a pure-rotation matrix from a set of euler angles (radians) in the order (x, y, z).
746 clockwise rotation around X, Y, Z, facing along axis
747 1 0 0 cy 0 -sy cz sz 0
748 0 cx sx 0 1 0 -sz cz 0
749 0 -sx cx sy 0 cy 0 0 1
751 rows of Z by cols of Y
752 cy*cz -sy*cz+sz -sy*sz+cz
755 .. or something like that..
757 final rotation is Z * Y * X
758 cy*cz -sx*-sy*cz+cx*sz cx*-sy*sz+sx*cz
759 -cy*sz sx*sy*sz+cx*cz -cx*-sy*sz+sx*cz
763 cy.cz + 0.sz + sy.0 cy.-sz + 0 .cz + sy.0 cy.0 + 0 .0 + sy.1 |
764 sx.sy.cz + cx.sz + -sx.cy.0 sx.sy.-sz + cx.cz + -sx.cy.0 sx.sy.0 + cx.0 + -sx.cy.1 |
765 -cx.sy.cz + sx.sz + cx.cy.0 -cx.sy.-sz + sx.cz + cx.cy.0 -cx.sy.0 + 0 .0 + cx.cy.1 |
767 inline Matrix4 matrix4_rotation_for_euler_xyz( const Vector3& euler ){
770 double cx = cos( euler[0] );
771 double sx = sin( euler[0] );
772 double cy = cos( euler[1] );
773 double sy = sin( euler[1] );
774 double cz = cos( euler[2] );
775 double sz = sin( euler[2] );
778 static_cast<float>( cy * cz ),
779 static_cast<float>( cy * sz ),
780 static_cast<float>( -sy ),
782 static_cast<float>( sx * sy * cz + cx * -sz ),
783 static_cast<float>( sx * sy * sz + cx * cz ),
784 static_cast<float>( sx * cy ),
786 static_cast<float>( cx * sy * cz + sx * sz ),
787 static_cast<float>( cx * sy * sz + -sx * cz ),
788 static_cast<float>( cx * cy ),
798 return matrix4_premultiply_by_matrix4(
799 matrix4_premultiply_by_matrix4(
800 matrix4_rotation_for_x( euler[0] ),
801 matrix4_rotation_for_y( euler[1] )
803 matrix4_rotation_for_z( euler[2] )
809 /// \brief Constructs a pure-rotation matrix from a set of euler angles (degrees) in the order (x, y, z).
810 inline Matrix4 matrix4_rotation_for_euler_xyz_degrees( const Vector3& euler ){
811 return matrix4_rotation_for_euler_xyz( euler_degrees_to_radians( euler ) );
814 /// \brief Concatenates \p self with the rotation transform produced by \p euler angles (degrees) in the order (x, y, z).
815 /// The concatenated rotation occurs before \p self.
816 inline void matrix4_rotate_by_euler_xyz_degrees( Matrix4& self, const Vector3& euler ){
817 matrix4_multiply_by_matrix4( self, matrix4_rotation_for_euler_xyz_degrees( euler ) );
821 /// \brief Constructs a pure-rotation matrix from a set of euler angles (radians) in the order (y, z, x).
822 inline Matrix4 matrix4_rotation_for_euler_yzx( const Vector3& euler ){
823 return matrix4_premultiplied_by_matrix4(
824 matrix4_premultiplied_by_matrix4(
825 matrix4_rotation_for_y( euler[1] ),
826 matrix4_rotation_for_z( euler[2] )
828 matrix4_rotation_for_x( euler[0] )
832 /// \brief Constructs a pure-rotation matrix from a set of euler angles (degrees) in the order (y, z, x).
833 inline Matrix4 matrix4_rotation_for_euler_yzx_degrees( const Vector3& euler ){
834 return matrix4_rotation_for_euler_yzx( euler_degrees_to_radians( euler ) );
837 /// \brief Constructs a pure-rotation matrix from a set of euler angles (radians) in the order (x, z, y).
838 inline Matrix4 matrix4_rotation_for_euler_xzy( const Vector3& euler ){
839 return matrix4_premultiplied_by_matrix4(
840 matrix4_premultiplied_by_matrix4(
841 matrix4_rotation_for_x( euler[0] ),
842 matrix4_rotation_for_z( euler[2] )
844 matrix4_rotation_for_y( euler[1] )
848 /// \brief Constructs a pure-rotation matrix from a set of euler angles (degrees) in the order (x, z, y).
849 inline Matrix4 matrix4_rotation_for_euler_xzy_degrees( const Vector3& euler ){
850 return matrix4_rotation_for_euler_xzy( euler_degrees_to_radians( euler ) );
853 /// \brief Constructs a pure-rotation matrix from a set of euler angles (radians) in the order (y, x, z).
855 | cy.cz + sx.sy.-sz + -cx.sy.0 0.cz + cx.-sz + sx.0 sy.cz + -sx.cy.-sz + cx.cy.0 |
856 | cy.sz + sx.sy.cz + -cx.sy.0 0.sz + cx.cz + sx.0 sy.sz + -sx.cy.cz + cx.cy.0 |
857 | cy.0 + sx.sy.0 + -cx.sy.1 0.0 + cx.0 + sx.1 sy.0 + -sx.cy.0 + cx.cy.1 |
859 inline Matrix4 matrix4_rotation_for_euler_yxz( const Vector3& euler ){
862 double cx = cos( euler[0] );
863 double sx = sin( euler[0] );
864 double cy = cos( euler[1] );
865 double sy = sin( euler[1] );
866 double cz = cos( euler[2] );
867 double sz = sin( euler[2] );
870 static_cast<float>( cy * cz + sx * sy * -sz ),
871 static_cast<float>( cy * sz + sx * sy * cz ),
872 static_cast<float>( -cx * sy ),
874 static_cast<float>( cx * -sz ),
875 static_cast<float>( cx * cz ),
876 static_cast<float>( sx ),
878 static_cast<float>( sy * cz + -sx * cy * -sz ),
879 static_cast<float>( sy * sz + -sx * cy * cz ),
880 static_cast<float>( cx * cy ),
890 return matrix4_premultiply_by_matrix4(
891 matrix4_premultiply_by_matrix4(
892 matrix4_rotation_for_y( euler[1] ),
893 matrix4_rotation_for_x( euler[0] )
895 matrix4_rotation_for_z( euler[2] )
901 /// \brief Constructs a pure-rotation matrix from a set of euler angles (degrees) in the order (y, x, z).
902 inline Matrix4 matrix4_rotation_for_euler_yxz_degrees( const Vector3& euler ){
903 return matrix4_rotation_for_euler_yxz( euler_degrees_to_radians( euler ) );
906 /// \brief Returns \p self concatenated with the rotation transform produced by \p euler angles (degrees) in the order (y, x, z).
907 /// The concatenated rotation occurs before \p self.
908 inline Matrix4 matrix4_rotated_by_euler_yxz_degrees( const Matrix4& self, const Vector3& euler ){
909 return matrix4_multiplied_by_matrix4( self, matrix4_rotation_for_euler_yxz_degrees( euler ) );
912 /// \brief Concatenates \p self with the rotation transform produced by \p euler angles (degrees) in the order (y, x, z).
913 /// The concatenated rotation occurs before \p self.
914 inline void matrix4_rotate_by_euler_yxz_degrees( Matrix4& self, const Vector3& euler ){
915 self = matrix4_rotated_by_euler_yxz_degrees( self, euler );
918 /// \brief Constructs a pure-rotation matrix from a set of euler angles (radians) in the order (z, x, y).
919 inline Matrix4 matrix4_rotation_for_euler_zxy( const Vector3& euler ){
921 return matrix4_premultiplied_by_matrix4(
922 matrix4_premultiplied_by_matrix4(
923 matrix4_rotation_for_z( euler[2] ),
924 matrix4_rotation_for_x( euler[0] )
926 matrix4_rotation_for_y( euler[1] )
929 double cx = cos( euler[0] );
930 double sx = sin( euler[0] );
931 double cy = cos( euler[1] );
932 double sy = sin( euler[1] );
933 double cz = cos( euler[2] );
934 double sz = sin( euler[2] );
937 static_cast<float>( cz * cy + sz * sx * sy ),
938 static_cast<float>( sz * cx ),
939 static_cast<float>( cz * -sy + sz * sx * cy ),
941 static_cast<float>( -sz * cy + cz * sx * sy ),
942 static_cast<float>( cz * cx ),
943 static_cast<float>( -sz * -sy + cz * cx * cy ),
945 static_cast<float>( cx * sy ),
946 static_cast<float>( -sx ),
947 static_cast<float>( cx * cy ),
957 /// \brief Constructs a pure-rotation matrix from a set of euler angles (degres=es) in the order (z, x, y).
958 inline Matrix4 matrix4_rotation_for_euler_zxy_degrees( const Vector3& euler ){
959 return matrix4_rotation_for_euler_zxy( euler_degrees_to_radians( euler ) );
962 /// \brief Returns \p self concatenated with the rotation transform produced by \p euler angles (degrees) in the order (z, x, y).
963 /// The concatenated rotation occurs before \p self.
964 inline Matrix4 matrix4_rotated_by_euler_zxy_degrees( const Matrix4& self, const Vector3& euler ){
965 return matrix4_multiplied_by_matrix4( self, matrix4_rotation_for_euler_zxy_degrees( euler ) );
968 /// \brief Concatenates \p self with the rotation transform produced by \p euler angles (degrees) in the order (z, x, y).
969 /// The concatenated rotation occurs before \p self.
970 inline void matrix4_rotate_by_euler_zxy_degrees( Matrix4& self, const Vector3& euler ){
971 self = matrix4_rotated_by_euler_zxy_degrees( self, euler );
974 /// \brief Constructs a pure-rotation matrix from a set of euler angles (radians) in the order (z, y, x).
975 inline Matrix4 matrix4_rotation_for_euler_zyx( const Vector3& euler ){
978 double cx = cos( euler[0] );
979 double sx = sin( euler[0] );
980 double cy = cos( euler[1] );
981 double sy = sin( euler[1] );
982 double cz = cos( euler[2] );
983 double sz = sin( euler[2] );
986 static_cast<float>( cy * cz ),
987 static_cast<float>( sx * sy * cz + cx * sz ),
988 static_cast<float>( cx * -sy * cz + sx * sz ),
990 static_cast<float>( cy * -sz ),
991 static_cast<float>( sx * sy * -sz + cx * cz ),
992 static_cast<float>( cx * -sy * -sz + sx * cz ),
994 static_cast<float>( sy ),
995 static_cast<float>( -sx * cy ),
996 static_cast<float>( cx * cy ),
1006 return matrix4_premultiply_by_matrix4(
1007 matrix4_premultiply_by_matrix4(
1008 matrix4_rotation_for_z( euler[2] ),
1009 matrix4_rotation_for_y( euler[1] )
1011 matrix4_rotation_for_x( euler[0] )
1017 /// \brief Constructs a pure-rotation matrix from a set of euler angles (degrees) in the order (z, y, x).
1018 inline Matrix4 matrix4_rotation_for_euler_zyx_degrees( const Vector3& euler ){
1019 return matrix4_rotation_for_euler_zyx( euler_degrees_to_radians( euler ) );
1023 /// \brief Calculates and returns a set of euler angles that produce the rotation component of \p self when applied in the order (x, y, z).
1024 /// \p self must be affine and orthonormal (unscaled) to produce a meaningful result.
1025 inline Vector3 matrix4_get_rotation_euler_xyz( const Matrix4& self ){
1026 double a = asin( -self[2] );
1027 double ca = cos( a );
1029 if ( fabs( ca ) > 0.005 ) { // Gimbal lock?
1031 static_cast<float>( atan2( self[6] / ca, self[10] / ca ) ),
1032 static_cast<float>( a ),
1033 static_cast<float>( atan2( self[1] / ca, self[0] / ca ) )
1036 else // Gimbal lock has occurred
1039 static_cast<float>( atan2( -self[9], self[5] ) ),
1040 static_cast<float>( a ),
1046 /// \brief \copydoc matrix4_get_rotation_euler_xyz(const Matrix4&)
1047 inline Vector3 matrix4_get_rotation_euler_xyz_degrees( const Matrix4& self ){
1048 return euler_radians_to_degrees( matrix4_get_rotation_euler_xyz( self ) );
1051 /// \brief Calculates and returns a set of euler angles that produce the rotation component of \p self when applied in the order (y, x, z).
1052 /// \p self must be affine and orthonormal (unscaled) to produce a meaningful result.
1053 inline Vector3 matrix4_get_rotation_euler_yxz( const Matrix4& self ){
1054 double a = asin( self[6] );
1055 double ca = cos( a );
1057 if ( fabs( ca ) > 0.005 ) { // Gimbal lock?
1059 static_cast<float>( a ),
1060 static_cast<float>( atan2( -self[2] / ca, self[10] / ca ) ),
1061 static_cast<float>( atan2( -self[4] / ca, self[5] / ca ) )
1064 else // Gimbal lock has occurred
1067 static_cast<float>( a ),
1068 static_cast<float>( atan2( self[8], self[0] ) ),
1074 /// \brief \copydoc matrix4_get_rotation_euler_yxz(const Matrix4&)
1075 inline Vector3 matrix4_get_rotation_euler_yxz_degrees( const Matrix4& self ){
1076 return euler_radians_to_degrees( matrix4_get_rotation_euler_yxz( self ) );
1079 /// \brief Calculates and returns a set of euler angles that produce the rotation component of \p self when applied in the order (z, x, y).
1080 /// \p self must be affine and orthonormal (unscaled) to produce a meaningful result.
1081 inline Vector3 matrix4_get_rotation_euler_zxy( const Matrix4& self ){
1082 double a = asin( -self[9] );
1083 double ca = cos( a );
1085 if ( fabs( ca ) > 0.005 ) { // Gimbal lock?
1087 static_cast<float>( a ),
1088 static_cast<float>( atan2( self[8] / ca, self[10] / ca ) ),
1089 static_cast<float>( atan2( self[1] / ca, self[5] / ca ) )
1092 else // Gimbal lock has occurred
1095 static_cast<float>( a ),
1097 static_cast<float>( atan2( -self[4], self[0] ) )
1102 /// \brief \copydoc matrix4_get_rotation_euler_zxy(const Matrix4&)
1103 inline Vector3 matrix4_get_rotation_euler_zxy_degrees( const Matrix4& self ){
1104 return euler_radians_to_degrees( matrix4_get_rotation_euler_zxy( self ) );
1107 /// \brief Calculates and returns a set of euler angles that produce the rotation component of \p self when applied in the order (z, y, x).
1108 /// \p self must be affine and orthonormal (unscaled) to produce a meaningful result.
1109 inline Vector3 matrix4_get_rotation_euler_zyx( const Matrix4& self ){
1110 double a = asin( self[8] );
1111 double ca = cos( a );
1113 if ( fabs( ca ) > 0.005 ) { // Gimbal lock?
1115 static_cast<float>( atan2( -self[9] / ca, self[10] / ca ) ),
1116 static_cast<float>( a ),
1117 static_cast<float>( atan2( -self[4] / ca, self[0] / ca ) )
1120 else // Gimbal lock has occurred
1124 static_cast<float>( a ),
1125 static_cast<float>( atan2( self[1], self[5] ) )
1130 /// \brief \copydoc matrix4_get_rotation_euler_zyx(const Matrix4&)
1131 inline Vector3 matrix4_get_rotation_euler_zyx_degrees( const Matrix4& self ){
1132 return euler_radians_to_degrees( matrix4_get_rotation_euler_zyx( self ) );
1136 /// \brief Rotate \p self by \p euler angles (degrees) applied in the order (x, y, z), using \p pivotpoint.
1137 inline void matrix4_pivoted_rotate_by_euler_xyz_degrees( Matrix4& self, const Vector3& euler, const Vector3& pivotpoint ){
1138 matrix4_translate_by_vec3( self, pivotpoint );
1139 matrix4_rotate_by_euler_xyz_degrees( self, euler );
1140 matrix4_translate_by_vec3( self, vector3_negated( pivotpoint ) );
1144 /// \brief Constructs a pure-scale matrix from \p scale.
1145 inline Matrix4 matrix4_scale_for_vec3( const Vector3& scale ){
1154 /// \brief Calculates and returns the (x, y, z) scale values that produce the scale component of \p self.
1155 /// \p self must be affine and orthogonal to produce a meaningful result.
1156 inline Vector3 matrix4_get_scale_vec3( const Matrix4& self ){
1158 static_cast<float>( vector3_length( vector4_to_vector3( self.x() ) ) ),
1159 static_cast<float>( vector3_length( vector4_to_vector3( self.y() ) ) ),
1160 static_cast<float>( vector3_length( vector4_to_vector3( self.z() ) ) )
1164 /// \brief Scales \p self by \p scale.
1165 inline void matrix4_scale_by_vec3( Matrix4& self, const Vector3& scale ){
1166 matrix4_multiply_by_matrix4( self, matrix4_scale_for_vec3( scale ) );
1169 /// \brief Scales \p self by \p scale, using \p pivotpoint.
1170 inline void matrix4_pivoted_scale_by_vec3( Matrix4& self, const Vector3& scale, const Vector3& pivotpoint ){
1171 matrix4_translate_by_vec3( self, pivotpoint );
1172 matrix4_scale_by_vec3( self, scale );
1173 matrix4_translate_by_vec3( self, vector3_negated( pivotpoint ) );
1177 /// \brief Transforms \p self by \p translation, \p euler and \p scale.
1178 /// The transforms are combined in the order: scale, rotate-z, rotate-y, rotate-x, translate.
1179 inline void matrix4_transform_by_euler_xyz_degrees( Matrix4& self, const Vector3& translation, const Vector3& euler, const Vector3& scale ){
1180 matrix4_translate_by_vec3( self, translation );
1181 matrix4_rotate_by_euler_xyz_degrees( self, euler );
1182 matrix4_scale_by_vec3( self, scale );
1185 /// \brief Transforms \p self by \p translation, \p euler and \p scale, using \p pivotpoint.
1186 inline void matrix4_pivoted_transform_by_euler_xyz_degrees( Matrix4& self, const Vector3& translation, const Vector3& euler, const Vector3& scale, const Vector3& pivotpoint ){
1187 matrix4_translate_by_vec3( self, pivotpoint + translation );
1188 matrix4_rotate_by_euler_xyz_degrees( self, euler );
1189 matrix4_scale_by_vec3( self, scale );
1190 matrix4_translate_by_vec3( self, vector3_negated( pivotpoint ) );