Leviathan  0.8.0.0
Leviathan game engine
Leviathan::Matrix3 Struct Reference

A 3x3 rotation and scale matrix. More...

#include <Matrix.h>

Classes

struct  EulerAngleOrderData
 

Public Member Functions

 Matrix3 ()=default
 
constexpr Matrix3 (const Matrix3 &)=default
 
constexpr Matrix3operator= (const Matrix3 &)=default
 
constexpr Matrix3 (float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
 
 Matrix3 (const Quaternion &rotation)
 
 Matrix3 (const Quaternion &rotation, const Float3 &scale)
 
 Matrix3 (const Float3 &axis, const Radian &angle)
 
 Matrix3 (const Float3 &xaxis, const Float3 &yaxis, const Float3 &zaxis)
 
 Matrix3 (const Radian &xAngle, const Radian &yAngle, const Radian &zAngle)
 
 Matrix3 (const Radian &xAngle, const Radian &yAngle, const Radian &zAngle, EulerAngleOrder order)
 
void swap (Matrix3 &other)
 
float * operator[] (uint32_t row) const
 
Float3 GetColumn (uint32_t col) const
 
void SetColumn (uint32_t col, const Float3 &vec)
 
bool operator!= (const Matrix3 &rhs) const
 
bool operator== (const Matrix3 &rhs) const
 
Matrix3 operator+ (const Matrix3 &rhs) const
 
Matrix3 operator- (const Matrix3 &rhs) const
 
Matrix3 operator* (const Matrix3 &rhs) const
 
Matrix3 operator- () const
 
Matrix3 operator* (float rhs) const
 
DLLEXPORT Float3 Multiply (const Float3 &vec) const
 
DLLEXPORT Matrix3 Transpose () const
 
DLLEXPORT bool Inverse (Matrix3 &mat, float fTolerance=1e-06f) const
 
DLLEXPORT Matrix3 Inverse (float fTolerance=1e-06f) const
 
DLLEXPORT float Determinant () const
 
DLLEXPORT void Decomposition (Quaternion &rotation, Float3 &scale) const
 
DLLEXPORT void SingularValueDecomposition (Matrix3 &matL, Float3 &matS, Matrix3 &matR) const
 
DLLEXPORT void QDUDecomposition (Matrix3 &matQ, Float3 &vecD, Float3 &vecU) const
 
DLLEXPORT void Orthonormalize ()
 
DLLEXPORT void ToAxisAngle (Float3 &axis, Radian &angle) const
 
DLLEXPORT void FromAxisAngle (const Float3 &axis, const Radian &angle)
 
DLLEXPORT void ToQuaternion (Quaternion &quat) const
 
DLLEXPORT void FromQuaternion (const Quaternion &quat)
 
DLLEXPORT void FromAxes (const Float3 &xAxis, const Float3 &yAxis, const Float3 &zAxis)
 
DLLEXPORT bool ToEulerAngles (Radian &xAngle, Radian &yAngle, Radian &zAngle) const
 
DLLEXPORT void FromEulerAngles (const Radian &xAngle, const Radian &yAngle, const Radian &zAngle)
 
DLLEXPORT void FromEulerAngles (const Radian &xAngle, const Radian &yAngle, const Radian &zAngle, EulerAngleOrder order)
 
DLLEXPORT void EigenSolveSymmetric (float eigenValues[3], Float3 eigenVectors[3]) const
 
 VALUE_TYPE (Matrix3)
 

Public Attributes

float m [3][3]
 

Static Public Attributes

static DLLEXPORT const Matrix3 IDENTITY
 
static DLLEXPORT const Matrix3 ZERO = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}
 

Protected Member Functions

void tridiagonal (float diag[3], float subDiag[3])
 
bool QLAlgorithm (float diag[3], float subDiag[3])
 

Static Protected Member Functions

static void bidiagonalize (Matrix3 &matA, Matrix3 &matL, Matrix3 &matR)
 
static void golubKahanStep (Matrix3 &matA, Matrix3 &matL, Matrix3 &matR)
 

Static Protected Attributes

static constexpr const float SVD_EPSILON = 1e-04f
 
static constexpr const unsigned int SVD_MAX_ITERS = 32
 

Friends

struct Matrix4
 
Matrix3 operator* (float lhs, const Matrix3 &rhs)
 

Detailed Description

A 3x3 rotation and scale matrix.

Definition at line 28 of file Matrix.h.

Constructor & Destructor Documentation

◆ Matrix3() [1/9]

Leviathan::Matrix3::Matrix3 ( )
default

◆ Matrix3() [2/9]

constexpr Leviathan::Matrix3::Matrix3 ( const Matrix3 )
default

◆ Matrix3() [3/9]

constexpr Leviathan::Matrix3::Matrix3 ( float  m00,
float  m01,
float  m02,
float  m10,
float  m11,
float  m12,
float  m20,
float  m21,
float  m22 
)
inline

Definition at line 41 of file Matrix.h.

42  :
43  m{{m00, m01, m02}, {m10, m11, m12}, {m20, m21, m22}}
44  {}
float m[3][3]
Definition: Matrix.h:370

◆ Matrix3() [4/9]

Leviathan::Matrix3::Matrix3 ( const Quaternion rotation)
inlineexplicit

Construct a matrix from a quaternion.

Definition at line 47 of file Matrix.h.

48  {
49  FromQuaternion(rotation);
50  }
DLLEXPORT void FromQuaternion(const Quaternion &quat)
Definition: Matrix.cpp:600

◆ Matrix3() [5/9]

Leviathan::Matrix3::Matrix3 ( const Quaternion rotation,
const Float3 scale 
)
inlineexplicit

Construct a matrix that performs rotation and scale.

Definition at line 53 of file Matrix.h.

54  {
55  FromQuaternion(rotation);
56 
57  for(int row = 0; row < 3; row++) {
58  for(int col = 0; col < 3; col++)
59  m[row][col] = scale[row] * m[row][col];
60  }
61  }
DLLEXPORT void FromQuaternion(const Quaternion &quat)
Definition: Matrix.cpp:600
float m[3][3]
Definition: Matrix.h:370

◆ Matrix3() [6/9]

Leviathan::Matrix3::Matrix3 ( const Float3 axis,
const Radian angle 
)
inlineexplicit

Construct a matrix from an angle/axis pair.

Definition at line 64 of file Matrix.h.

65  {
66  FromAxisAngle(axis, angle);
67  }
DLLEXPORT void FromAxisAngle(const Float3 &axis, const Radian &angle)
Definition: Matrix.cpp:569

◆ Matrix3() [7/9]

Leviathan::Matrix3::Matrix3 ( const Float3 xaxis,
const Float3 yaxis,
const Float3 zaxis 
)
inlineexplicit

Construct a matrix from 3 orthonormal local axes.

Definition at line 70 of file Matrix.h.

71  {
72  FromAxes(xaxis, yaxis, zaxis);
73  }
DLLEXPORT void FromAxes(const Float3 &xAxis, const Float3 &yAxis, const Float3 &zAxis)
Definition: Matrix.cpp:18

◆ Matrix3() [8/9]

Leviathan::Matrix3::Matrix3 ( const Radian xAngle,
const Radian yAngle,
const Radian zAngle 
)
inlineexplicit

Construct a matrix from euler angles, YXZ ordering.

See also
Matrix3::fromEulerAngles

Definition at line 80 of file Matrix.h.

81  {
82  FromEulerAngles(xAngle, yAngle, zAngle);
83  }
DLLEXPORT void FromEulerAngles(const Radian &xAngle, const Radian &yAngle, const Radian &zAngle)
Definition: Matrix.cpp:633

◆ Matrix3() [9/9]

Leviathan::Matrix3::Matrix3 ( const Radian xAngle,
const Radian yAngle,
const Radian zAngle,
EulerAngleOrder  order 
)
inlineexplicit

Construct a matrix from euler angles, custom ordering.

See also
Matrix3::fromEulerAngles

Definition at line 90 of file Matrix.h.

92  {
93  FromEulerAngles(xAngle, yAngle, zAngle, order);
94  }
DLLEXPORT void FromEulerAngles(const Radian &xAngle, const Radian &yAngle, const Radian &zAngle)
Definition: Matrix.cpp:633

Member Function Documentation

◆ bidiagonalize()

void Matrix3::bidiagonalize ( Matrix3 matA,
Matrix3 matL,
Matrix3 matR 
)
staticprotected

Definition at line 90 of file Matrix.cpp.

91 {
92  float v[3], w[3];
93  float length, sign, t1, invT1, t2;
94  bool bIdentity;
95 
96  // Map first column to (*,0,0)
97  length =
98  std::sqrt(matA[0][0] * matA[0][0] + matA[1][0] * matA[1][0] + matA[2][0] * matA[2][0]);
99  if(length > 0.0f) {
100  sign = (matA[0][0] > 0.0f ? 1.0f : -1.0f);
101  t1 = matA[0][0] + sign * length;
102  invT1 = 1.0f / t1;
103  v[1] = matA[1][0] * invT1;
104  v[2] = matA[2][0] * invT1;
105 
106  t2 = -2.0f / (1.0f + v[1] * v[1] + v[2] * v[2]);
107  w[0] = t2 * (matA[0][0] + matA[1][0] * v[1] + matA[2][0] * v[2]);
108  w[1] = t2 * (matA[0][1] + matA[1][1] * v[1] + matA[2][1] * v[2]);
109  w[2] = t2 * (matA[0][2] + matA[1][2] * v[1] + matA[2][2] * v[2]);
110  matA[0][0] += w[0];
111  matA[0][1] += w[1];
112  matA[0][2] += w[2];
113  matA[1][1] += v[1] * w[1];
114  matA[1][2] += v[1] * w[2];
115  matA[2][1] += v[2] * w[1];
116  matA[2][2] += v[2] * w[2];
117 
118  matL[0][0] = 1.0f + t2;
119  matL[0][1] = matL[1][0] = t2 * v[1];
120  matL[0][2] = matL[2][0] = t2 * v[2];
121  matL[1][1] = 1.0f + t2 * v[1] * v[1];
122  matL[1][2] = matL[2][1] = t2 * v[1] * v[2];
123  matL[2][2] = 1.0f + t2 * v[2] * v[2];
124  bIdentity = false;
125  } else {
126  matL = Matrix3::IDENTITY;
127  bIdentity = true;
128  }
129 
130  // Map first row to (*,*,0)
131  length = std::sqrt(matA[0][1] * matA[0][1] + matA[0][2] * matA[0][2]);
132  if(length > 0.0) {
133  sign = (matA[0][1] > 0.0f ? 1.0f : -1.0f);
134  t1 = matA[0][1] + sign * length;
135  v[2] = matA[0][2] / t1;
136 
137  t2 = -2.0f / (1.0f + v[2] * v[2]);
138  w[0] = t2 * (matA[0][1] + matA[0][2] * v[2]);
139  w[1] = t2 * (matA[1][1] + matA[1][2] * v[2]);
140  w[2] = t2 * (matA[2][1] + matA[2][2] * v[2]);
141  matA[0][1] += w[0];
142  matA[1][1] += w[1];
143  matA[1][2] += w[1] * v[2];
144  matA[2][1] += w[2];
145  matA[2][2] += w[2] * v[2];
146 
147  matR[0][0] = 1.0;
148  matR[0][1] = matR[1][0] = 0.0;
149  matR[0][2] = matR[2][0] = 0.0;
150  matR[1][1] = 1.0f + t2;
151  matR[1][2] = matR[2][1] = t2 * v[2];
152  matR[2][2] = 1.0f + t2 * v[2] * v[2];
153  } else {
154  matR = Matrix3::IDENTITY;
155  }
156 
157  // Map second column to (*,*,0)
158  length = std::sqrt(matA[1][1] * matA[1][1] + matA[2][1] * matA[2][1]);
159  if(length > 0.0) {
160  sign = (matA[1][1] > 0.0f ? 1.0f : -1.0f);
161  t1 = matA[1][1] + sign * length;
162  v[2] = matA[2][1] / t1;
163 
164  t2 = -2.0f / (1.0f + v[2] * v[2]);
165  w[1] = t2 * (matA[1][1] + matA[2][1] * v[2]);
166  w[2] = t2 * (matA[1][2] + matA[2][2] * v[2]);
167  matA[1][1] += w[1];
168  matA[1][2] += w[2];
169  matA[2][2] += v[2] * w[2];
170 
171  float a = 1.0f + t2;
172  float b = t2 * v[2];
173  float c = 1.0f + b * v[2];
174 
175  if(bIdentity) {
176  matL[0][0] = 1.0;
177  matL[0][1] = matL[1][0] = 0.0;
178  matL[0][2] = matL[2][0] = 0.0;
179  matL[1][1] = a;
180  matL[1][2] = matL[2][1] = b;
181  matL[2][2] = c;
182  } else {
183  for(int row = 0; row < 3; row++) {
184  float tmp0 = matL[row][1];
185  float tmp1 = matL[row][2];
186  matL[row][1] = a * tmp0 + b * tmp1;
187  matL[row][2] = b * tmp0 + c * tmp1;
188  }
189  }
190  }
191 }
static DLLEXPORT const Matrix3 IDENTITY
Definition: Matrix.h:374

◆ Decomposition()

DLLEXPORT void Matrix3::Decomposition ( Quaternion rotation,
Float3 scale 
) const

Decompose a Matrix3 to rotation and scale.

Note
Matrix must consist only of rotation and uniform scale transformations, otherwise accurate results are not guaranteed. Applying non-uniform scale guarantees rotation portion will not be accurate.

Definition at line 436 of file Matrix.cpp.

437 {
438  Matrix3 matQ;
439  Float3 vecU;
440  QDUDecomposition(matQ, scale, vecU);
441 
442  rotation = Quaternion(matQ);
443 }
A 3x3 rotation and scale matrix.
Definition: Matrix.h:28
DLLEXPORT void QDUDecomposition(Matrix3 &matQ, Float3 &vecD, Float3 &vecU) const
Definition: Matrix.cpp:445
A Quaternion type to make quaternion specific operations easier to access.
Definition: Quaternion.h:14

◆ Determinant()

DLLEXPORT float Matrix3::Determinant ( ) const

Calculates the matrix determinant.

Definition at line 79 of file Matrix.cpp.

80 {
81  float cofactor00 = m[1][1] * m[2][2] - m[1][2] * m[2][1];
82  float cofactor10 = m[1][2] * m[2][0] - m[1][0] * m[2][2];
83  float cofactor20 = m[1][0] * m[2][1] - m[1][1] * m[2][0];
84 
85  float det = m[0][0] * cofactor00 + m[0][1] * cofactor10 + m[0][2] * cofactor20;
86 
87  return det;
88 }
float m[3][3]
Definition: Matrix.h:370

◆ EigenSolveSymmetric()

DLLEXPORT void Matrix3::EigenSolveSymmetric ( float  eigenValues[3],
Float3  eigenVectors[3] 
) const

Eigensolver, matrix must be symmetric.

Note
Eigenvectors are vectors which when transformed by the matrix, only change in magnitude, but not in direction. Eigenvalue is that magnitude. In other words you will get the same result whether you multiply the vector by the matrix or by its eigenvalue.

Definition at line 814 of file Matrix.cpp.

815 {
816  Matrix3 mat = *this;
817  float subDiag[3];
818  mat.tridiagonal(eigenValues, subDiag);
819  mat.QLAlgorithm(eigenValues, subDiag);
820 
821  for(uint32_t i = 0; i < 3; i++) {
822  eigenVectors[i][0] = mat[0][i];
823  eigenVectors[i][1] = mat[1][i];
824  eigenVectors[i][2] = mat[2][i];
825  }
826 
827  // Make eigenvectors form a right--handed system
828  Float3 cross = eigenVectors[1].Cross(eigenVectors[2]);
829  float det = eigenVectors[0].Dot(cross);
830  if(det < 0.0f) {
831  eigenVectors[2][0] = -eigenVectors[2][0];
832  eigenVectors[2][1] = -eigenVectors[2][1];
833  eigenVectors[2][2] = -eigenVectors[2][2];
834  }
835 }
A 3x3 rotation and scale matrix.
Definition: Matrix.h:28
void tridiagonal(float diag[3], float subDiag[3])
Definition: Matrix.cpp:684
DLLEXPORT constexpr float Dot(const Float3 &val) const noexcept
Definition: Types.h:1227
bool QLAlgorithm(float diag[3], float subDiag[3])
Definition: Matrix.cpp:739
unsigned int uint32_t
Definition: core.h:40
DLLEXPORT constexpr Float3 Cross(const Float3 &val) const
Definition: Types.h:1233

◆ FromAxes()

DLLEXPORT void Matrix3::FromAxes ( const Float3 xAxis,
const Float3 yAxis,
const Float3 zAxis 
)

Creates a matrix from a three axes.

Definition at line 18 of file Matrix.cpp.

19 {
20  SetColumn(0, xAxis);
21  SetColumn(1, yAxis);
22  SetColumn(2, zAxis);
23 }
void SetColumn(uint32_t col, const Float3 &vec)
Definition: Matrix.h:125

◆ FromAxisAngle()

DLLEXPORT void Matrix3::FromAxisAngle ( const Float3 axis,
const Radian angle 
)

Creates a rotation matrix from an axis angle representation.

Definition at line 569 of file Matrix.cpp.

570 {
571  float cos = std::cos(angle.ValueInRadians());
572  float sin = std::sin(angle.ValueInRadians());
573  float oneMinusCos = 1.0f - cos;
574  float x2 = axis.X * axis.X;
575  float y2 = axis.Y * axis.Y;
576  float z2 = axis.Z * axis.Z;
577  float xym = axis.X * axis.Y * oneMinusCos;
578  float xzm = axis.X * axis.Z * oneMinusCos;
579  float yzm = axis.Y * axis.Z * oneMinusCos;
580  float xSin = axis.X * sin;
581  float ySin = axis.Y * sin;
582  float zSin = axis.Z * sin;
583 
584  m[0][0] = x2 * oneMinusCos + cos;
585  m[0][1] = xym - zSin;
586  m[0][2] = xzm + ySin;
587  m[1][0] = xym + zSin;
588  m[1][1] = y2 * oneMinusCos + cos;
589  m[1][2] = yzm - xSin;
590  m[2][0] = xzm - ySin;
591  m[2][1] = yzm + xSin;
592  m[2][2] = z2 * oneMinusCos + cos;
593 }
float m[3][3]
Definition: Matrix.h:370
constexpr float ValueInRadians() const noexcept
Definition: Types.h:159

◆ FromEulerAngles() [1/2]

DLLEXPORT void Matrix3::FromEulerAngles ( const Radian xAngle,
const Radian yAngle,
const Radian zAngle 
)

Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.

Parameters
[in]xAngleRotation about x axis. (AKA Pitch)
[in]yAngleRotation about y axis. (AKA Yaw)
[in]zAngleRotation about z axis. (AKA Roll)
Note
Matrix must be orthonormal. Since different values will be produced depending in which order are the rotations applied, this method assumes they are applied in YXZ order. If you need a specific order, use the overloaded "fromEulerAngles" method instead.

Definition at line 633 of file Matrix.cpp.

635 {
636  float cx = std::cos(xAngle.ValueInRadians());
637  float sx = std::sin(xAngle.ValueInRadians());
638 
639  float cy = std::cos(yAngle.ValueInRadians());
640  float sy = std::sin(yAngle.ValueInRadians());
641 
642  float cz = std::cos(zAngle.ValueInRadians());
643  float sz = std::sin(zAngle.ValueInRadians());
644 
645  m[0][0] = cy * cz - sx * sy * sz;
646  m[0][1] = -cx * sz;
647  m[0][2] = cz * sy + cy * sx * sz;
648 
649  m[1][0] = cz * sx * sy + cy * sz;
650  m[1][1] = cx * cz;
651  m[1][2] = -cy * cz * sx + sy * sz;
652 
653  m[2][0] = -cx * sy;
654  m[2][1] = sx;
655  m[2][2] = cx * cy;
656 }
float m[3][3]
Definition: Matrix.h:370
constexpr float ValueInRadians() const noexcept
Definition: Types.h:159

◆ FromEulerAngles() [2/2]

DLLEXPORT void Matrix3::FromEulerAngles ( const Radian xAngle,
const Radian yAngle,
const Radian zAngle,
EulerAngleOrder  order 
)

Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.

Parameters
[in]xAngleRotation about x axis. (AKA Pitch)
[in]yAngleRotation about y axis. (AKA Yaw)
[in]zAngleRotation about z axis. (AKA Roll)
[in]orderThe order in which rotations will be applied. Different rotations can be created depending on the order.
Note
Matrix must be orthonormal.

Definition at line 658 of file Matrix.cpp.

660 {
661  // Euler angle conversions
662  static constexpr const EulerAngleOrderData EA_LOOKUP[6] = {{0, 1, 2, 1.0f},
663  {0, 2, 1, -1.0f}, {1, 0, 2, -1.0f}, {1, 2, 0, 1.0f}, {2, 0, 1, 1.0f},
664  {2, 1, 0, -1.0f}};
665 
666  const EulerAngleOrderData& l = EA_LOOKUP[(int)order];
667 
668  Matrix3 mats[3];
669  float cx = std::cos(xAngle.ValueInRadians());
670  float sx = std::sin(xAngle.ValueInRadians());
671  mats[0] = Matrix3(1.0f, 0.0f, 0.0f, 0.0f, cx, -sx, 0.0f, sx, cx);
672 
673  float cy = std::cos(yAngle.ValueInRadians());
674  float sy = std::sin(yAngle.ValueInRadians());
675  mats[1] = Matrix3(cy, 0.0f, sy, 0.0f, 1.0f, 0.0f, -sy, 0.0f, cy);
676 
677  float cz = std::cos(zAngle.ValueInRadians());
678  float sz = std::sin(zAngle.ValueInRadians());
679  mats[2] = Matrix3(cz, -sz, 0.0f, sz, cz, 0.0f, 0.0f, 0.0f, 1.0f);
680 
681  *this = mats[l.c] * (mats[l.b] * mats[l.a]);
682 }
A 3x3 rotation and scale matrix.
Definition: Matrix.h:28
constexpr float ValueInRadians() const noexcept
Definition: Types.h:159

◆ FromQuaternion()

DLLEXPORT void Matrix3::FromQuaternion ( const Quaternion quat)

Creates a rotation matrix from a quaternion representation.

Definition at line 600 of file Matrix.cpp.

601 {
602  quat.ToRotationMatrix(*this);
603 }
DLLEXPORT void ToRotationMatrix(Matrix3 &matrix) const
Definition: Quaternion.cpp:105

◆ GetColumn()

Float3 Leviathan::Matrix3::GetColumn ( uint32_t  col) const
inline

Definition at line 118 of file Matrix.h.

119  {
120  LEVIATHAN_ASSERT(col < 3, "col out of range");
121 
122  return Float3(m[0][col], m[1][col], m[2][col]);
123  }
float m[3][3]
Definition: Matrix.h:370
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100

◆ golubKahanStep()

void Matrix3::golubKahanStep ( Matrix3 matA,
Matrix3 matL,
Matrix3 matR 
)
staticprotected

Definition at line 193 of file Matrix.cpp.

194 {
195  float f11 = matA[0][1] * matA[0][1] + matA[1][1] * matA[1][1];
196  float t22 = matA[1][2] * matA[1][2] + matA[2][2] * matA[2][2];
197  float t12 = matA[1][1] * matA[1][2];
198  float trace = f11 + t22;
199  float diff = f11 - t22;
200  float discr = std::sqrt(diff * diff + 4.0f * t12 * t12);
201  float root1 = 0.5f * (trace + discr);
202  float root2 = 0.5f * (trace - discr);
203 
204  // Adjust right
205  float y = matA[0][0] - (std::abs(root1 - t22) <= std::abs(root2 - t22) ? root1 : root2);
206  float z = matA[0][1];
207  float invLength = 1.f / std::sqrt(y * y + z * z);
208  float sin = z * invLength;
209  float cos = -y * invLength;
210 
211  float tmp0 = matA[0][0];
212  float tmp1 = matA[0][1];
213  matA[0][0] = cos * tmp0 - sin * tmp1;
214  matA[0][1] = sin * tmp0 + cos * tmp1;
215  matA[1][0] = -sin * matA[1][1];
216  matA[1][1] *= cos;
217 
218  uint32_t row;
219  for(row = 0; row < 3; row++) {
220  tmp0 = matR[0][row];
221  tmp1 = matR[1][row];
222  matR[0][row] = cos * tmp0 - sin * tmp1;
223  matR[1][row] = sin * tmp0 + cos * tmp1;
224  }
225 
226  // Adjust left
227  y = matA[0][0];
228  z = matA[1][0];
229  invLength = 1.f / std::sqrt(y * y + z * z);
230  sin = z * invLength;
231  cos = -y * invLength;
232 
233  matA[0][0] = cos * matA[0][0] - sin * matA[1][0];
234  tmp0 = matA[0][1];
235  tmp1 = matA[1][1];
236  matA[0][1] = cos * tmp0 - sin * tmp1;
237  matA[1][1] = sin * tmp0 + cos * tmp1;
238  matA[0][2] = -sin * matA[1][2];
239  matA[1][2] *= cos;
240 
241  uint32_t col;
242  for(col = 0; col < 3; col++) {
243  tmp0 = matL[col][0];
244  tmp1 = matL[col][1];
245  matL[col][0] = cos * tmp0 - sin * tmp1;
246  matL[col][1] = sin * tmp0 + cos * tmp1;
247  }
248 
249  // Adjust right
250  y = matA[0][1];
251  z = matA[0][2];
252  invLength = 1.f / std::sqrt(y * y + z * z);
253  sin = z * invLength;
254  cos = -y * invLength;
255 
256  matA[0][1] = cos * matA[0][1] - sin * matA[0][2];
257  tmp0 = matA[1][1];
258  tmp1 = matA[1][2];
259  matA[1][1] = cos * tmp0 - sin * tmp1;
260  matA[1][2] = sin * tmp0 + cos * tmp1;
261  matA[2][1] = -sin * matA[2][2];
262  matA[2][2] *= cos;
263 
264  for(row = 0; row < 3; row++) {
265  tmp0 = matR[1][row];
266  tmp1 = matR[2][row];
267  matR[1][row] = cos * tmp0 - sin * tmp1;
268  matR[2][row] = sin * tmp0 + cos * tmp1;
269  }
270 
271  // Adjust left
272  y = matA[1][1];
273  z = matA[2][1];
274  invLength = 1.f / std::sqrt(y * y + z * z);
275  sin = z * invLength;
276  cos = -y * invLength;
277 
278  matA[1][1] = cos * matA[1][1] - sin * matA[2][1];
279  tmp0 = matA[1][2];
280  tmp1 = matA[2][2];
281  matA[1][2] = cos * tmp0 - sin * tmp1;
282  matA[2][2] = sin * tmp0 + cos * tmp1;
283 
284  for(col = 0; col < 3; col++) {
285  tmp0 = matL[col][1];
286  tmp1 = matL[col][2];
287  matL[col][1] = cos * tmp0 - sin * tmp1;
288  matL[col][2] = sin * tmp0 + cos * tmp1;
289  }
290 }
unsigned int uint32_t
Definition: core.h:40

◆ Inverse() [1/2]

DLLEXPORT bool Matrix3::Inverse ( Matrix3 mat,
float  fTolerance = 1e-06f 
) const

Calculates an inverse of the matrix if it exists.

Parameters
[out]matResulting matrix inverse.
[in]fTolerance(optional) Tolerance to use when checking if determinant is zero (or near zero in this case). Zero determinant means inverse doesn't exist.
Returns
True if inverse exists, false otherwise.

Definition at line 46 of file Matrix.cpp.

47 {
48  matInv[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
49  matInv[0][1] = m[0][2] * m[2][1] - m[0][1] * m[2][2];
50  matInv[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
51  matInv[1][0] = m[1][2] * m[2][0] - m[1][0] * m[2][2];
52  matInv[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
53  matInv[1][2] = m[0][2] * m[1][0] - m[0][0] * m[1][2];
54  matInv[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
55  matInv[2][1] = m[0][1] * m[2][0] - m[0][0] * m[2][1];
56  matInv[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
57 
58  float det = m[0][0] * matInv[0][0] + m[0][1] * matInv[1][0] + m[0][2] * matInv[2][0];
59 
60  if(std::abs(det) <= tolerance)
61  return false;
62 
63  float invDet = 1.0f / det;
64  for(uint32_t row = 0; row < 3; row++) {
65  for(uint32_t col = 0; col < 3; col++)
66  matInv[row][col] *= invDet;
67  }
68 
69  return true;
70 }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ Inverse() [2/2]

DLLEXPORT Matrix3 Matrix3::Inverse ( float  fTolerance = 1e-06f) const

Calculates an inverse of the matrix if it exists.

Parameters
[in]fTolerance(optional) Tolerance to use when checking if determinant is zero (or near zero in this case). Zero determinant means inverse doesn't exist.
Returns
Resulting matrix inverse if it exists, otherwise a zero matrix.

Definition at line 72 of file Matrix.cpp.

73 {
74  Matrix3 matInv = Matrix3::ZERO;
75  Inverse(matInv, tolerance);
76  return matInv;
77 }
A 3x3 rotation and scale matrix.
Definition: Matrix.h:28
static DLLEXPORT const Matrix3 ZERO
Definition: Matrix.h:375
DLLEXPORT bool Inverse(Matrix3 &mat, float fTolerance=1e-06f) const
Definition: Matrix.cpp:46

◆ Multiply()

DLLEXPORT Float3 Matrix3::Multiply ( const Float3 vec) const

Transforms the given vector by this matrix and returns the newly transformed vector.

Definition at line 25 of file Matrix.cpp.

26 {
27  Float3 prod;
28  for(uint32_t row = 0; row < 3; row++) {
29  prod[row] = m[row][0] * vec[0] + m[row][1] * vec[1] + m[row][2] * vec[2];
30  }
31 
32  return prod;
33 }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ operator!=()

bool Leviathan::Matrix3::operator!= ( const Matrix3 rhs) const
inline

Definition at line 134 of file Matrix.h.

135  {
136  return !operator==(rhs);
137  }
bool operator==(const Matrix3 &rhs) const
Definition: Matrix.h:139

◆ operator*() [1/2]

Matrix3 Leviathan::Matrix3::operator* ( const Matrix3 rhs) const
inline

Definition at line 175 of file Matrix.h.

176  {
177  Matrix3 prod;
178  for(uint32_t row = 0; row < 3; row++) {
179  for(uint32_t col = 0; col < 3; col++) {
180  prod.m[row][col] = m[row][0] * rhs.m[0][col] + m[row][1] * rhs.m[1][col] +
181  m[row][2] * rhs.m[2][col];
182  }
183  }
184 
185  return prod;
186  }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ operator*() [2/2]

Matrix3 Leviathan::Matrix3::operator* ( float  rhs) const
inline

Definition at line 199 of file Matrix.h.

200  {
201  Matrix3 prod;
202  for(uint32_t row = 0; row < 3; row++) {
203  for(uint32_t col = 0; col < 3; col++)
204  prod[row][col] = rhs * m[row][col];
205  }
206 
207  return prod;
208  }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ operator+()

Matrix3 Leviathan::Matrix3::operator+ ( const Matrix3 rhs) const
inline

Definition at line 151 of file Matrix.h.

152  {
153  Matrix3 sum;
154  for(uint32_t row = 0; row < 3; row++) {
155  for(uint32_t col = 0; col < 3; col++) {
156  sum.m[row][col] = m[row][col] + rhs.m[row][col];
157  }
158  }
159 
160  return sum;
161  }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ operator-() [1/2]

Matrix3 Leviathan::Matrix3::operator- ( const Matrix3 rhs) const
inline

Definition at line 163 of file Matrix.h.

164  {
165  Matrix3 diff;
166  for(uint32_t row = 0; row < 3; row++) {
167  for(uint32_t col = 0; col < 3; col++) {
168  diff.m[row][col] = m[row][col] - rhs.m[row][col];
169  }
170  }
171 
172  return diff;
173  }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ operator-() [2/2]

Matrix3 Leviathan::Matrix3::operator- ( ) const
inline

Definition at line 188 of file Matrix.h.

189  {
190  Matrix3 neg;
191  for(uint32_t row = 0; row < 3; row++) {
192  for(uint32_t col = 0; col < 3; col++)
193  neg[row][col] = -m[row][col];
194  }
195 
196  return neg;
197  }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ operator=()

constexpr Matrix3& Leviathan::Matrix3::operator= ( const Matrix3 )
default

◆ operator==()

bool Leviathan::Matrix3::operator== ( const Matrix3 rhs) const
inline

Definition at line 139 of file Matrix.h.

140  {
141  for(uint32_t row = 0; row < 3; row++) {
142  for(uint32_t col = 0; col < 3; col++) {
143  if(m[row][col] != rhs.m[row][col])
144  return false;
145  }
146  }
147 
148  return true;
149  }
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ operator[]()

float* Leviathan::Matrix3::operator[] ( uint32_t  row) const
inline

Returns a row of the matrix.

Definition at line 111 of file Matrix.h.

112  {
113  // assert(row < 3);
114 
115  return (float*)m[row];
116  }
float m[3][3]
Definition: Matrix.h:370

◆ Orthonormalize()

DLLEXPORT void Matrix3::Orthonormalize ( )

Gram-Schmidt orthonormalization (applied to columns of rotation matrix)

Definition at line 398 of file Matrix.cpp.

399 {
400  // Compute q0
401  float invLength =
402  1.f / std::sqrt(m[0][0] * m[0][0] + m[1][0] * m[1][0] + m[2][0] * m[2][0]);
403 
404  m[0][0] *= invLength;
405  m[1][0] *= invLength;
406  m[2][0] *= invLength;
407 
408  // Compute q1
409  float dot0 = m[0][0] * m[0][1] + m[1][0] * m[1][1] + m[2][0] * m[2][1];
410 
411  m[0][1] -= dot0 * m[0][0];
412  m[1][1] -= dot0 * m[1][0];
413  m[2][1] -= dot0 * m[2][0];
414 
415  invLength = 1.f / std::sqrt(m[0][1] * m[0][1] + m[1][1] * m[1][1] + m[2][1] * m[2][1]);
416 
417  m[0][1] *= invLength;
418  m[1][1] *= invLength;
419  m[2][1] *= invLength;
420 
421  // Compute q2
422  float dot1 = m[0][1] * m[0][2] + m[1][1] * m[1][2] + m[2][1] * m[2][2];
423  dot0 = m[0][0] * m[0][2] + m[1][0] * m[1][2] + m[2][0] * m[2][2];
424 
425  m[0][2] -= dot0 * m[0][0] + dot1 * m[0][1];
426  m[1][2] -= dot0 * m[1][0] + dot1 * m[1][1];
427  m[2][2] -= dot0 * m[2][0] + dot1 * m[2][1];
428 
429  invLength = 1.f / std::sqrt(m[0][2] * m[0][2] + m[1][2] * m[1][2] + m[2][2] * m[2][2]);
430 
431  m[0][2] *= invLength;
432  m[1][2] *= invLength;
433  m[2][2] *= invLength;
434 }
float m[3][3]
Definition: Matrix.h:370

◆ QDUDecomposition()

DLLEXPORT void Matrix3::QDUDecomposition ( Matrix3 matQ,
Float3 vecD,
Float3 vecU 
) const

Decomposes the matrix into a set of values.

Parameters
[out]matQColumns form orthonormal bases. If your matrix is affine and doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
[out]vecDIf the matrix is affine these will be scaling factors of the matrix.
[out]vecUIf the matrix is affine these will be shear factors of the matrix.

Definition at line 445 of file Matrix.cpp.

446 {
447  // Build orthogonal matrix Q
448  float invLength =
449  1.f / std::sqrt(m[0][0] * m[0][0] + m[1][0] * m[1][0] + m[2][0] * m[2][0]);
450  matQ[0][0] = m[0][0] * invLength;
451  matQ[1][0] = m[1][0] * invLength;
452  matQ[2][0] = m[2][0] * invLength;
453 
454  float dot = matQ[0][0] * m[0][1] + matQ[1][0] * m[1][1] + matQ[2][0] * m[2][1];
455  matQ[0][1] = m[0][1] - dot * matQ[0][0];
456  matQ[1][1] = m[1][1] - dot * matQ[1][0];
457  matQ[2][1] = m[2][1] - dot * matQ[2][0];
458 
459  invLength = 1.f / std::sqrt(matQ[0][1] * matQ[0][1] + matQ[1][1] * matQ[1][1] +
460  matQ[2][1] * matQ[2][1]);
461  matQ[0][1] *= invLength;
462  matQ[1][1] *= invLength;
463  matQ[2][1] *= invLength;
464 
465  dot = matQ[0][0] * m[0][2] + matQ[1][0] * m[1][2] + matQ[2][0] * m[2][2];
466  matQ[0][2] = m[0][2] - dot * matQ[0][0];
467  matQ[1][2] = m[1][2] - dot * matQ[1][0];
468  matQ[2][2] = m[2][2] - dot * matQ[2][0];
469 
470  dot = matQ[0][1] * m[0][2] + matQ[1][1] * m[1][2] + matQ[2][1] * m[2][2];
471  matQ[0][2] -= dot * matQ[0][1];
472  matQ[1][2] -= dot * matQ[1][1];
473  matQ[2][2] -= dot * matQ[2][1];
474 
475  invLength = 1.f / std::sqrt(matQ[0][2] * matQ[0][2] + matQ[1][2] * matQ[1][2] +
476  matQ[2][2] * matQ[2][2]);
477  matQ[0][2] *= invLength;
478  matQ[1][2] *= invLength;
479  matQ[2][2] *= invLength;
480 
481  // Guarantee that orthogonal matrix has determinant 1 (no reflections)
482  float fDet = matQ[0][0] * matQ[1][1] * matQ[2][2] + matQ[0][1] * matQ[1][2] * matQ[2][0] +
483  matQ[0][2] * matQ[1][0] * matQ[2][1] - matQ[0][2] * matQ[1][1] * matQ[2][0] -
484  matQ[0][1] * matQ[1][0] * matQ[2][2] - matQ[0][0] * matQ[1][2] * matQ[2][1];
485 
486  if(fDet < 0.0f) {
487  for(uint32_t row = 0; row < 3; row++)
488  for(uint32_t col = 0; col < 3; col++)
489  matQ[row][col] = -matQ[row][col];
490  }
491 
492  // Build "right" matrix R
493  Matrix3 matRight;
494  matRight[0][0] = matQ[0][0] * m[0][0] + matQ[1][0] * m[1][0] + matQ[2][0] * m[2][0];
495  matRight[0][1] = matQ[0][0] * m[0][1] + matQ[1][0] * m[1][1] + matQ[2][0] * m[2][1];
496  matRight[1][1] = matQ[0][1] * m[0][1] + matQ[1][1] * m[1][1] + matQ[2][1] * m[2][1];
497  matRight[0][2] = matQ[0][0] * m[0][2] + matQ[1][0] * m[1][2] + matQ[2][0] * m[2][2];
498  matRight[1][2] = matQ[0][1] * m[0][2] + matQ[1][1] * m[1][2] + matQ[2][1] * m[2][2];
499  matRight[2][2] = matQ[0][2] * m[0][2] + matQ[1][2] * m[1][2] + matQ[2][2] * m[2][2];
500 
501  // The scaling component
502  vecD[0] = matRight[0][0];
503  vecD[1] = matRight[1][1];
504  vecD[2] = matRight[2][2];
505 
506  // The shear component
507  float invD0 = 1.0f / vecD[0];
508  vecU[0] = matRight[0][1] * invD0;
509  vecU[1] = matRight[0][2] * invD0;
510  vecU[2] = matRight[1][2] / vecD[1];
511 }
A 3x3 rotation and scale matrix.
Definition: Matrix.h:28
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ QLAlgorithm()

bool Matrix3::QLAlgorithm ( float  diag[3],
float  subDiag[3] 
)
protected

Definition at line 739 of file Matrix.cpp.

740 {
741  // QL iteration with implicit shifting to reduce matrix from tridiagonal to diagonal
742 
743  for(int i = 0; i < 3; i++) {
744  const unsigned int maxIter = 32;
745  unsigned int iter;
746  for(iter = 0; iter < maxIter; iter++) {
747  int j;
748  for(j = i; j <= 1; j++) {
749  float sum = std::abs(diag[j]) + std::abs(diag[j + 1]);
750 
751  if(std::abs(subDiag[j]) + sum == sum)
752  break;
753  }
754 
755  if(j == i)
756  break;
757 
758  float tmp0 = (diag[i + 1] - diag[i]) / (2.0f * subDiag[i]);
759  float tmp1 = std::sqrt(tmp0 * tmp0 + 1.0f);
760 
761  if(tmp0 < 0.0f)
762  tmp0 = diag[j] - diag[i] + subDiag[i] / (tmp0 - tmp1);
763  else
764  tmp0 = diag[j] - diag[i] + subDiag[i] / (tmp0 + tmp1);
765 
766  float sin = 1.0f;
767  float cos = 1.0f;
768  float tmp2 = 0.0f;
769  for(int k = j - 1; k >= i; k--) {
770  float tmp3 = sin * subDiag[k];
771  float tmp4 = cos * subDiag[k];
772 
773  if(std::abs(tmp3) >= std::abs(tmp0)) {
774  cos = tmp0 / tmp3;
775  tmp1 = std::sqrt(cos * cos + 1.0f);
776  subDiag[k + 1] = tmp3 * tmp1;
777  sin = 1.0f / tmp1;
778  cos *= sin;
779  } else {
780  sin = tmp3 / tmp0;
781  tmp1 = std::sqrt(sin * sin + 1.0f);
782  subDiag[k + 1] = tmp0 * tmp1;
783  cos = 1.0f / tmp1;
784  sin *= cos;
785  }
786 
787  tmp0 = diag[k + 1] - tmp2;
788  tmp1 = (diag[k] - tmp0) * sin + 2.0f * tmp4 * cos;
789  tmp2 = sin * tmp1;
790  diag[k + 1] = tmp0 + tmp2;
791  tmp0 = cos * tmp1 - tmp4;
792 
793  for(int row = 0; row < 3; row++) {
794  tmp3 = m[row][k + 1];
795  m[row][k + 1] = sin * m[row][k] + cos * tmp3;
796  m[row][k] = cos * m[row][k] - sin * tmp3;
797  }
798  }
799 
800  diag[i] -= tmp2;
801  subDiag[i] = tmp0;
802  subDiag[j] = 0.0;
803  }
804 
805  if(iter == maxIter) {
806  // Should not get here under normal circumstances
807  return false;
808  }
809  }
810 
811  return true;
812 }
float m[3][3]
Definition: Matrix.h:370

◆ SetColumn()

void Leviathan::Matrix3::SetColumn ( uint32_t  col,
const Float3 vec 
)
inline

Definition at line 125 of file Matrix.h.

126  {
127  LEVIATHAN_ASSERT(col < 3, "col out of range");
128 
129  m[0][col] = vec.X;
130  m[1][col] = vec.Y;
131  m[2][col] = vec.Z;
132  }
float m[3][3]
Definition: Matrix.h:370
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100

◆ SingularValueDecomposition()

DLLEXPORT void Matrix3::SingularValueDecomposition ( Matrix3 matL,
Float3 matS,
Matrix3 matR 
) const

Decomposes the matrix into various useful values.

Parameters
[out]matLUnitary matrix. Columns form orthonormal bases. If your matrix is affine and doesn't use non-uniform scaling this matrix will be a conjugate transpose of the rotation part of the matrix.
[out]matSSingular values of the matrix. If your matrix is affine these will be scaling factors of the matrix.
[out]matRUnitary matrix. Columns form orthonormal bases. If your matrix is affine and doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.

Definition at line 292 of file Matrix.cpp.

294 {
295  uint32_t row, col;
296 
297  Matrix3 mat = *this;
298  bidiagonalize(mat, matL, matR);
299 
300  for(unsigned int i = 0; i < SVD_MAX_ITERS; i++) {
301  float tmp, tmp0, tmp1;
302  float sin0, cos0, tan0;
303  float sin1, cos1, tan1;
304 
305  bool test1 =
306  (std::abs(mat[0][1]) <= SVD_EPSILON * (std::abs(mat[0][0]) + std::abs(mat[1][1])));
307  bool test2 =
308  (std::abs(mat[1][2]) <= SVD_EPSILON * (std::abs(mat[1][1]) + std::abs(mat[2][2])));
309 
310  if(test1) {
311  if(test2) {
312  matS[0] = mat[0][0];
313  matS[1] = mat[1][1];
314  matS[2] = mat[2][2];
315  break;
316  } else {
317  // 2x2 closed form factorization
318  tmp = (mat[1][1] * mat[1][1] - mat[2][2] * mat[2][2] + mat[1][2] * mat[1][2]) /
319  (mat[1][2] * mat[2][2]);
320  tan0 = 0.5f * (tmp + std::sqrt(tmp * tmp + 4.0f));
321  cos0 = 1.f / std::sqrt(1.0f + tan0 * tan0);
322  sin0 = tan0 * cos0;
323 
324  for(col = 0; col < 3; col++) {
325  tmp0 = matL[col][1];
326  tmp1 = matL[col][2];
327  matL[col][1] = cos0 * tmp0 - sin0 * tmp1;
328  matL[col][2] = sin0 * tmp0 + cos0 * tmp1;
329  }
330 
331  tan1 = (mat[1][2] - mat[2][2] * tan0) / mat[1][1];
332  cos1 = 1.f / std::sqrt(1.0f + tan1 * tan1);
333  sin1 = -tan1 * cos1;
334 
335  for(row = 0; row < 3; row++) {
336  tmp0 = matR[1][row];
337  tmp1 = matR[2][row];
338  matR[1][row] = cos1 * tmp0 - sin1 * tmp1;
339  matR[2][row] = sin1 * tmp0 + cos1 * tmp1;
340  }
341 
342  matS[0] = mat[0][0];
343  matS[1] =
344  cos0 * cos1 * mat[1][1] - sin1 * (cos0 * mat[1][2] - sin0 * mat[2][2]);
345  matS[2] =
346  sin0 * sin1 * mat[1][1] + cos1 * (sin0 * mat[1][2] + cos0 * mat[2][2]);
347  break;
348  }
349  } else {
350  if(test2) {
351  // 2x2 closed form factorization
352  tmp = (mat[0][0] * mat[0][0] + mat[1][1] * mat[1][1] - mat[0][1] * mat[0][1]) /
353  (mat[0][1] * mat[1][1]);
354  tan0 = 0.5f * (-tmp + std::sqrt(tmp * tmp + 4.0f));
355  cos0 = 1.f / std::sqrt(1.0f + tan0 * tan0);
356  sin0 = tan0 * cos0;
357 
358  for(col = 0; col < 3; col++) {
359  tmp0 = matL[col][0];
360  tmp1 = matL[col][1];
361  matL[col][0] = cos0 * tmp0 - sin0 * tmp1;
362  matL[col][1] = sin0 * tmp0 + cos0 * tmp1;
363  }
364 
365  tan1 = (mat[0][1] - mat[1][1] * tan0) / mat[0][0];
366  cos1 = 1.f / std::sqrt(1.0f + tan1 * tan1);
367  sin1 = -tan1 * cos1;
368 
369  for(row = 0; row < 3; row++) {
370  tmp0 = matR[0][row];
371  tmp1 = matR[1][row];
372  matR[0][row] = cos1 * tmp0 - sin1 * tmp1;
373  matR[1][row] = sin1 * tmp0 + cos1 * tmp1;
374  }
375 
376  matS[0] =
377  cos0 * cos1 * mat[0][0] - sin1 * (cos0 * mat[0][1] - sin0 * mat[1][1]);
378  matS[1] =
379  sin0 * sin1 * mat[0][0] + cos1 * (sin0 * mat[0][1] + cos0 * mat[1][1]);
380  matS[2] = mat[2][2];
381  break;
382  } else {
383  golubKahanStep(mat, matL, matR);
384  }
385  }
386  }
387 
388  // Positize diagonal
389  for(row = 0; row < 3; row++) {
390  if(matS[row] < 0.0) {
391  matS[row] = -matS[row];
392  for(col = 0; col < 3; col++)
393  matR[row][col] = -matR[row][col];
394  }
395  }
396 }
static constexpr const float SVD_EPSILON
Definition: Matrix.h:363
A 3x3 rotation and scale matrix.
Definition: Matrix.h:28
static void golubKahanStep(Matrix3 &matA, Matrix3 &matL, Matrix3 &matR)
Definition: Matrix.cpp:193
static constexpr const unsigned int SVD_MAX_ITERS
Definition: Matrix.h:365
static void bidiagonalize(Matrix3 &matA, Matrix3 &matL, Matrix3 &matR)
Definition: Matrix.cpp:90
unsigned int uint32_t
Definition: core.h:40

◆ swap()

void Leviathan::Matrix3::swap ( Matrix3 other)
inline

Swaps the contents of this matrix with another.

Definition at line 97 of file Matrix.h.

98  {
99  std::swap(m[0][0], other.m[0][0]);
100  std::swap(m[0][1], other.m[0][1]);
101  std::swap(m[0][2], other.m[0][2]);
102  std::swap(m[1][0], other.m[1][0]);
103  std::swap(m[1][1], other.m[1][1]);
104  std::swap(m[1][2], other.m[1][2]);
105  std::swap(m[2][0], other.m[2][0]);
106  std::swap(m[2][1], other.m[2][1]);
107  std::swap(m[2][2], other.m[2][2]);
108  }
void swap(Value &a, Value &b)
Definition: json.h:1359
float m[3][3]
Definition: Matrix.h:370

◆ ToAxisAngle()

DLLEXPORT void Matrix3::ToAxisAngle ( Float3 axis,
Radian angle 
) const

Converts an orthonormal matrix to axis angle representation.

Note
Matrix must be orthonormal.

Definition at line 513 of file Matrix.cpp.

514 {
515  float trace = m[0][0] + m[1][1] + m[2][2];
516  float cos = 0.5f * (trace - 1.0f);
517  radians = Radian(std::acos(cos)); // In [0, PI]
518 
519  if(radians > Radian(0.0f)) {
520  if(radians < Radian(PI)) {
521  axis.X = m[2][1] - m[1][2];
522  axis.Y = m[0][2] - m[2][0];
523  axis.Z = m[1][0] - m[0][1];
524  axis.Normalize();
525  } else {
526  // Angle is PI
527  float fHalfInverse;
528  if(m[0][0] >= m[1][1]) {
529  // r00 >= r11
530  if(m[0][0] >= m[2][2]) {
531  // r00 is maximum diagonal term
532  axis.X = 0.5f * std::sqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f);
533  fHalfInverse = 0.5f / axis.X;
534  axis.Y = fHalfInverse * m[0][1];
535  axis.Z = fHalfInverse * m[0][2];
536  } else {
537  // r22 is maximum diagonal term
538  axis.Z = 0.5f * std::sqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
539  fHalfInverse = 0.5f / axis.Z;
540  axis.X = fHalfInverse * m[0][2];
541  axis.Y = fHalfInverse * m[1][2];
542  }
543  } else {
544  // r11 > r00
545  if(m[1][1] >= m[2][2]) {
546  // r11 is maximum diagonal term
547  axis.Y = 0.5f * std::sqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f);
548  fHalfInverse = 0.5f / axis.Y;
549  axis.X = fHalfInverse * m[0][1];
550  axis.Z = fHalfInverse * m[1][2];
551  } else {
552  // r22 is maximum diagonal term
553  axis.Z = 0.5f * std::sqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
554  fHalfInverse = 0.5f / axis.Z;
555  axis.X = fHalfInverse * m[0][2];
556  axis.Y = fHalfInverse * m[1][2];
557  }
558  }
559  }
560  } else {
561  // The angle is 0 and the matrix is the identity. Any axis will
562  // work, so just use the x-axis.
563  axis.X = 1.0f;
564  axis.Y = 0.0f;
565  axis.Z = 0.0f;
566  }
567 }
Represents an angle in radians.
Definition: Types.h:129
DLLEXPORT Float3 Normalize() const
Definition: Types.h:1250
float m[3][3]
Definition: Matrix.h:370
constexpr float PI
Definition: Define.h:65

◆ ToEulerAngles()

DLLEXPORT bool Matrix3::ToEulerAngles ( Radian xAngle,
Radian yAngle,
Radian zAngle 
) const

Converts an orthonormal matrix to euler angle (pitch/yaw/roll) representation.

Parameters
[in,out]xAngleRotation about x axis. (AKA Pitch)
[in,out]yAngleRotation about y axis. (AKA Yaw)
[in,out]zAngleRotation about z axis. (AKA Roll)
Returns
True if unique solution was found, false otherwise.
Note
Matrix must be orthonormal.

Definition at line 605 of file Matrix.cpp.

606 {
607  float m21 = m[2][1];
608  if(m21 < 1) {
609  if(m21 > -1) {
610  xAngle = Radian(std::asin(m21));
611  yAngle = Radian(std::atan2(-m[2][0], m[2][2]));
612  zAngle = Radian(std::atan2(-m[0][1], m[1][1]));
613 
614  return true;
615  } else {
616  // Note: Not an unique solution.
617  xAngle = Radian(-HALF_PI);
618  yAngle = Radian(0.0f);
619  zAngle = Radian(-std::atan2(m[0][2], m[0][0]));
620 
621  return false;
622  }
623  } else {
624  // Note: Not an unique solution.
625  xAngle = Radian(HALF_PI);
626  yAngle = Radian(0.0f);
627  zAngle = Radian(std::atan2(m[0][2], m[0][0]));
628 
629  return false;
630  }
631 }
constexpr float HALF_PI
Definition: Define.h:66
Represents an angle in radians.
Definition: Types.h:129
float m[3][3]
Definition: Matrix.h:370

◆ ToQuaternion()

DLLEXPORT void Matrix3::ToQuaternion ( Quaternion quat) const

Converts an orthonormal matrix to quaternion representation.

Note
Matrix must be orthonormal.

Definition at line 595 of file Matrix.cpp.

596 {
597  quat.FromRotationMatrix(*this);
598 }
DLLEXPORT void FromRotationMatrix(const Matrix3 &matrix)
Definition: Quaternion.cpp:59

◆ Transpose()

DLLEXPORT Matrix3 Matrix3::Transpose ( ) const

Returns a transpose of the matrix (switched columns and rows).

Definition at line 35 of file Matrix.cpp.

36 {
37  Matrix3 matTranspose;
38  for(uint32_t row = 0; row < 3; row++) {
39  for(uint32_t col = 0; col < 3; col++)
40  matTranspose[row][col] = m[col][row];
41  }
42 
43  return matTranspose;
44 }
A 3x3 rotation and scale matrix.
Definition: Matrix.h:28
float m[3][3]
Definition: Matrix.h:370
unsigned int uint32_t
Definition: core.h:40

◆ tridiagonal()

void Matrix3::tridiagonal ( float  diag[3],
float  subDiag[3] 
)
protected

Definition at line 684 of file Matrix.cpp.

685 {
686  // Householder reduction T = Q^t M Q
687  // Input:
688  // mat, symmetric 3x3 matrix M
689  // Output:
690  // mat, orthogonal matrix Q
691  // diag, diagonal entries of T
692  // subd, subdiagonal entries of T (T is symmetric)
693 
694  float fA = m[0][0];
695  float fB = m[0][1];
696  float fC = m[0][2];
697  float fD = m[1][1];
698  float fE = m[1][2];
699  float fF = m[2][2];
700 
701  diag[0] = fA;
702  subDiag[2] = 0.0;
703  if(std::abs(fC) >= EPSILON) {
704  float length = std::sqrt(fB * fB + fC * fC);
705  float invLength = 1.0f / length;
706  fB *= invLength;
707  fC *= invLength;
708  float fQ = 2.0f * fB * fE + fC * (fF - fD);
709  diag[1] = fD + fC * fQ;
710  diag[2] = fF - fC * fQ;
711  subDiag[0] = length;
712  subDiag[1] = fE - fB * fQ;
713  m[0][0] = 1.0;
714  m[0][1] = 0.0;
715  m[0][2] = 0.0;
716  m[1][0] = 0.0;
717  m[1][1] = fB;
718  m[1][2] = fC;
719  m[2][0] = 0.0;
720  m[2][1] = fC;
721  m[2][2] = -fB;
722  } else {
723  diag[1] = fD;
724  diag[2] = fF;
725  subDiag[0] = fB;
726  subDiag[1] = fE;
727  m[0][0] = 1.0;
728  m[0][1] = 0.0;
729  m[0][2] = 0.0;
730  m[1][0] = 0.0;
731  m[1][1] = 1.0;
732  m[1][2] = 0.0;
733  m[2][0] = 0.0;
734  m[2][1] = 0.0;
735  m[2][2] = 1.0;
736  }
737 }
constexpr float EPSILON
Definition: Define.h:70
float m[3][3]
Definition: Matrix.h:370

◆ VALUE_TYPE()

Leviathan::Matrix3::VALUE_TYPE ( Matrix3  )

Friends And Related Function Documentation

◆ Matrix4

friend struct Matrix4
friend

Definition at line 356 of file Matrix.h.

◆ operator*

Matrix3 operator* ( float  lhs,
const Matrix3 rhs 
)
friend

Member Data Documentation

◆ IDENTITY

DLLEXPORT const Matrix3 Matrix3::IDENTITY
static
Initial value:
= {
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}

Definition at line 374 of file Matrix.h.

◆ m

float Leviathan::Matrix3::m[3][3]

Definition at line 370 of file Matrix.h.

◆ SVD_EPSILON

constexpr const float Leviathan::Matrix3::SVD_EPSILON = 1e-04f
staticprotected

Definition at line 363 of file Matrix.h.

◆ SVD_MAX_ITERS

constexpr const unsigned int Leviathan::Matrix3::SVD_MAX_ITERS = 32
staticprotected

Definition at line 365 of file Matrix.h.

◆ ZERO

DLLEXPORT const Matrix3 Matrix3::ZERO = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}
static

Definition at line 375 of file Matrix.h.


The documentation for this struct was generated from the following files: