TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
G3D::Matrix3 Class Reference

#include <Matrix3.h>

Public Member Functions

 Matrix3 (const Any &any)
 
Any toAny () const
 
 Matrix3 ()
 
 Matrix3 (class BinaryInput &b)
 
 Matrix3 (const float aafEntry[3][3])
 
 Matrix3 (const Matrix3 &rkMatrix)
 
 Matrix3 (float fEntry00, float fEntry01, float fEntry02, float fEntry10, float fEntry11, float fEntry12, float fEntry20, float fEntry21, float fEntry22)
 
bool fuzzyEq (const Matrix3 &b) const
 
 Matrix3 (const class Quat &q)
 
void serialize (class BinaryOutput &b) const
 
void deserialize (class BinaryInput &b)
 
bool isRightHanded () const
 
void set (float fEntry00, float fEntry01, float fEntry02, float fEntry10, float fEntry11, float fEntry12, float fEntry20, float fEntry21, float fEntry22)
 
float * operator[] (int iRow)
 
const float * operator[] (int iRow) const
 
 operator float * ()
 
 operator const float * () const
 
Vector3 column (int c) const
 
const Vector3row (int r) const
 
void setColumn (int iCol, const Vector3 &vector)
 
void setRow (int iRow, const Vector3 &vector)
 
Matrix3operator= (const Matrix3 &rkMatrix)
 
bool operator== (const Matrix3 &rkMatrix) const
 
bool operator!= (const Matrix3 &rkMatrix) const
 
Matrix3 operator+ (const Matrix3 &rkMatrix) const
 
Matrix3 operator- (const Matrix3 &rkMatrix) const
 
Matrix3 operator* (const Matrix3 &rkMatrix) const
 
Matrix3 operator- () const
 
Matrix3operator+= (const Matrix3 &rkMatrix)
 
Matrix3operator-= (const Matrix3 &rkMatrix)
 
Matrix3operator*= (const Matrix3 &rkMatrix)
 
Vector3 operator* (const Vector3 &v) const
 
Matrix3 operator* (float fScalar) const
 
Matrix3operator*= (float k)
 
Matrix3operator/= (float k)
 
bool isOrthonormal () const
 
Matrix3 transpose () const
 
bool inverse (Matrix3 &rkInverse, float fTolerance=1e-06f) const
 
Matrix3 inverse (float fTolerance=1e-06f) const
 
float determinant () const
 
void singularValueDecomposition (Matrix3 &rkL, Vector3 &rkS, Matrix3 &rkR) const
 
void singularValueComposition (const Matrix3 &rkL, const Vector3 &rkS, const Matrix3 &rkR)
 
void orthonormalize ()
 
void qDUDecomposition (Matrix3 &rkQ, Vector3 &rkD, Vector3 &rkU) const
 
void polarDecomposition (Matrix3 &R, Matrix3 &S) const
 
float spectralNorm () const
 
float squaredFrobeniusNorm () const
 
float frobeniusNorm () const
 
float l1Norm () const
 
float lInfNorm () const
 
float diffOneNorm (const Matrix3 &y) const
 
void toAxisAngle (Vector3 &rkAxis, float &rfRadians) const
 
bool toEulerAnglesXYZ (float &rfYAngle, float &rfPAngle, float &rfRAngle) const
 
bool toEulerAnglesXZY (float &rfYAngle, float &rfPAngle, float &rfRAngle) const
 
bool toEulerAnglesYXZ (float &rfYAngle, float &rfPAngle, float &rfRAngle) const
 
bool toEulerAnglesYZX (float &rfYAngle, float &rfPAngle, float &rfRAngle) const
 
bool toEulerAnglesZXY (float &rfYAngle, float &rfPAngle, float &rfRAngle) const
 
bool toEulerAnglesZYX (float &rfYAngle, float &rfPAngle, float &rfRAngle) const
 
void eigenSolveSymmetric (float afEigenvalue[3], Vector3 akEigenvector[3]) const
 
std::string toString () const
 

Static Public Member Functions

static Matrix3 fromColumns (const Vector3 &c0, const Vector3 &c1, const Vector3 &c2)
 
static Matrix3 fromRows (const Vector3 &r0, const Vector3 &r1, const Vector3 &r2)
 
static Matrix3 diagonal (float e00, float e11, float e22)
 
static void mul (const Matrix3 &A, const Matrix3 &B, Matrix3 &out)
 
static void transpose (const Matrix3 &A, Matrix3 &out)
 
static Matrix3 fromDiagonal (const Vector3 &d)
 
static Matrix3 fromAxisAngle (const Vector3 &rkAxis, float fRadians)
 
static Matrix3 fromUnitAxisAngle (const Vector3 &rkAxis, float fRadians)
 
static Matrix3 fromEulerAnglesXYZ (float fYAngle, float fPAngle, float fRAngle)
 
static Matrix3 fromEulerAnglesXZY (float fYAngle, float fPAngle, float fRAngle)
 
static Matrix3 fromEulerAnglesYXZ (float fYAngle, float fPAngle, float fRAngle)
 
static Matrix3 fromEulerAnglesYZX (float fYAngle, float fPAngle, float fRAngle)
 
static Matrix3 fromEulerAnglesZXY (float fYAngle, float fPAngle, float fRAngle)
 
static Matrix3 fromEulerAnglesZYX (float fYAngle, float fPAngle, float fRAngle)
 
static void tensorProduct (const Vector3 &rkU, const Vector3 &rkV, Matrix3 &rkProduct)
 
static const Matrix3zero ()
 
static const Matrix3identity ()
 

Static Public Attributes

static const float EPSILON = 1e-06f
 

Protected Member Functions

void tridiagonal (float afDiag[3], float afSubDiag[3])
 
bool qLAlgorithm (float afDiag[3], float afSubDiag[3])
 

Static Protected Member Functions

static void bidiagonalize (Matrix3 &kA, Matrix3 &kL, Matrix3 &kR)
 
static void golubKahanStep (Matrix3 &kA, Matrix3 &kL, Matrix3 &kR)
 
static float maxCubicRoot (float afCoeff[3])
 

Static Protected Attributes

static const float ms_fSvdEpsilon = 1e-04f
 
static const int ms_iSvdMaxIterations = 32
 

Private Member Functions

bool operator< (const Matrix3 &) const
 
bool operator> (const Matrix3 &) const
 
bool operator<= (const Matrix3 &) const
 
bool operator>= (const Matrix3 &) const
 

Static Private Member Functions

static void _mul (const Matrix3 &A, const Matrix3 &B, Matrix3 &out)
 
static void _transpose (const Matrix3 &A, Matrix3 &out)
 

Private Attributes

float elt [3][3]
 

Friends

Vector3 operator* (const Vector3 &rkVector, const Matrix3 &rkMatrix)
 
Matrix3 operator* (double fScalar, const Matrix3 &rkMatrix)
 
Matrix3 operator* (float fScalar, const Matrix3 &rkMatrix)
 
Matrix3 operator* (int fScalar, const Matrix3 &rkMatrix)
 

Detailed Description

A 3x3 matrix. Do not subclass. Data is unitializd when default constructed.

Constructor & Destructor Documentation

G3D::Matrix3::Matrix3 ( const Any any)

Must be in one of the following forms:

29  {
30  any.verifyName("Matrix3");
31  any.verifyType(Any::ARRAY);
32 
33  if (any.nameEquals("Matrix3::fromAxisAngle")) {
34  any.verifySize(2);
35  *this = fromAxisAngle(Vector3(any[0]), any[1].floatValue());
36  } else if (any.nameEquals("Matrix3::diagonal")) {
37  any.verifySize(3);
38  *this = diagonal(any[0], any[1], any[2]);
39  } else if (any.nameEquals("Matrix3::identity")) {
40  *this = identity();
41  } else {
42  any.verifySize(9);
43 
44  for (int r = 0; r < 3; ++r) {
45  for (int c = 0; c < 3; ++c) {
46  elt[r][c] = any[r * 3 + c];
47  }
48  }
49  }
50 }
static Matrix3 diagonal(float e00, float e11, float e22)
Definition: Matrix3.h:99
bool any(float x)
Definition: g3dmath.h:424
Definition: Any.h:187
static Matrix3 fromAxisAngle(const Vector3 &rkAxis, float fRadians)
Definition: Matrix3.cpp:1346
float elt[3][3]
Definition: Matrix3.h:41
static const Matrix3 & identity()
Definition: Matrix3.cpp:70

+ Here is the call graph for this function:

G3D::Matrix3::Matrix3 ( )
inline

Initial values are undefined for performance.

See also
Matrix3::zero, Matrix3::identity, Matrix3::fromAxisAngle, etc.
83 {}

+ Here is the caller graph for this function:

G3D::Matrix3::Matrix3 ( class BinaryInput b)
79  {
80  deserialize(b);
81 }
void deserialize(class BinaryInput &b)
Definition: Matrix3.cpp:182

+ Here is the call graph for this function:

G3D::Matrix3::Matrix3 ( const float  aafEntry[3][3])
146  {
147  memcpy(elt, aafEntry, 9*sizeof(float));
148 }
float elt[3][3]
Definition: Matrix3.h:41
G3D::Matrix3::Matrix3 ( const Matrix3 rkMatrix)
151  {
152  memcpy(elt, rkMatrix.elt, 9*sizeof(float));
153 }
float elt[3][3]
Definition: Matrix3.h:41
G3D::Matrix3::Matrix3 ( float  fEntry00,
float  fEntry01,
float  fEntry02,
float  fEntry10,
float  fEntry11,
float  fEntry12,
float  fEntry20,
float  fEntry21,
float  fEntry22 
)
159  {
160  set(fEntry00, fEntry01, fEntry02,
161  fEntry10, fEntry11, fEntry12,
162  fEntry20, fEntry21, fEntry22);
163 }
void set(float fEntry00, float fEntry01, float fEntry02, float fEntry10, float fEntry11, float fEntry12, float fEntry20, float fEntry21, float fEntry22)
Definition: Matrix3.cpp:165

+ Here is the call graph for this function:

G3D::Matrix3::Matrix3 ( const class Quat q)

Constructs a matrix from a quaternion. [Graphics] Gems II, p. 351–354 [Implementation] from Watt and Watt, pg 362

Member Function Documentation

void G3D::Matrix3::_mul ( const Matrix3 A,
const Matrix3 B,
Matrix3 out 
)
staticprivate

Multiplication where out != A and out != B

1869  {
1870  const float* ARowPtr = A.elt[0];
1871  float* outRowPtr = out.elt[0];
1872  outRowPtr[0] =
1873  ARowPtr[0] * B.elt[0][0] +
1874  ARowPtr[1] * B.elt[1][0] +
1875  ARowPtr[2] * B.elt[2][0];
1876  outRowPtr[1] =
1877  ARowPtr[0] * B.elt[0][1] +
1878  ARowPtr[1] * B.elt[1][1] +
1879  ARowPtr[2] * B.elt[2][1];
1880  outRowPtr[2] =
1881  ARowPtr[0] * B.elt[0][2] +
1882  ARowPtr[1] * B.elt[1][2] +
1883  ARowPtr[2] * B.elt[2][2];
1884 
1885  ARowPtr = A.elt[1];
1886  outRowPtr = out.elt[1];
1887 
1888  outRowPtr[0] =
1889  ARowPtr[0] * B.elt[0][0] +
1890  ARowPtr[1] * B.elt[1][0] +
1891  ARowPtr[2] * B.elt[2][0];
1892  outRowPtr[1] =
1893  ARowPtr[0] * B.elt[0][1] +
1894  ARowPtr[1] * B.elt[1][1] +
1895  ARowPtr[2] * B.elt[2][1];
1896  outRowPtr[2] =
1897  ARowPtr[0] * B.elt[0][2] +
1898  ARowPtr[1] * B.elt[1][2] +
1899  ARowPtr[2] * B.elt[2][2];
1900 
1901  ARowPtr = A.elt[2];
1902  outRowPtr = out.elt[2];
1903 
1904  outRowPtr[0] =
1905  ARowPtr[0] * B.elt[0][0] +
1906  ARowPtr[1] * B.elt[1][0] +
1907  ARowPtr[2] * B.elt[2][0];
1908  outRowPtr[1] =
1909  ARowPtr[0] * B.elt[0][1] +
1910  ARowPtr[1] * B.elt[1][1] +
1911  ARowPtr[2] * B.elt[2][1];
1912  outRowPtr[2] =
1913  ARowPtr[0] * B.elt[0][2] +
1914  ARowPtr[1] * B.elt[1][2] +
1915  ARowPtr[2] * B.elt[2][2];
1916 }

+ Here is the caller graph for this function:

void G3D::Matrix3::_transpose ( const Matrix3 A,
Matrix3 out 
)
staticprivate
1919  {
1920  out[0][0] = A.elt[0][0];
1921  out[0][1] = A.elt[1][0];
1922  out[0][2] = A.elt[2][0];
1923  out[1][0] = A.elt[0][1];
1924  out[1][1] = A.elt[1][1];
1925  out[1][2] = A.elt[2][1];
1926  out[2][0] = A.elt[0][2];
1927  out[2][1] = A.elt[1][2];
1928  out[2][2] = A.elt[2][2];
1929 }

+ Here is the caller graph for this function:

void G3D::Matrix3::bidiagonalize ( Matrix3 kA,
Matrix3 kL,
Matrix3 kR 
)
staticprotected
471  {
472  float afV[3], afW[3];
473  float fLength, fSign, fT1, fInvT1, fT2;
474  bool bIdentity;
475 
476  // map first column to (*,0,0)
477  fLength = sqrt(kA[0][0] * kA[0][0] + kA[1][0] * kA[1][0] +
478  kA[2][0] * kA[2][0]);
479 
480  if ( fLength > 0.0 ) {
481  fSign = (kA[0][0] > 0.0 ? 1.0f : -1.0f);
482  fT1 = (float)kA[0][0] + fSign * fLength;
483  fInvT1 = 1.0f / fT1;
484  afV[1] = kA[1][0] * fInvT1;
485  afV[2] = kA[2][0] * fInvT1;
486 
487  fT2 = -2.0f / (1.0f + afV[1] * afV[1] + afV[2] * afV[2]);
488  afW[0] = fT2 * (kA[0][0] + kA[1][0] * afV[1] + kA[2][0] * afV[2]);
489  afW[1] = fT2 * (kA[0][1] + kA[1][1] * afV[1] + kA[2][1] * afV[2]);
490  afW[2] = fT2 * (kA[0][2] + kA[1][2] * afV[1] + kA[2][2] * afV[2]);
491  kA[0][0] += afW[0];
492  kA[0][1] += afW[1];
493  kA[0][2] += afW[2];
494  kA[1][1] += afV[1] * afW[1];
495  kA[1][2] += afV[1] * afW[2];
496  kA[2][1] += afV[2] * afW[1];
497  kA[2][2] += afV[2] * afW[2];
498 
499  kL[0][0] = 1.0f + fT2;
500  kL[0][1] = kL[1][0] = fT2 * afV[1];
501  kL[0][2] = kL[2][0] = fT2 * afV[2];
502  kL[1][1] = 1.0f + fT2 * afV[1] * afV[1];
503  kL[1][2] = kL[2][1] = fT2 * afV[1] * afV[2];
504  kL[2][2] = 1.0f + fT2 * afV[2] * afV[2];
505  bIdentity = false;
506  } else {
507  kL = Matrix3::identity();
508  bIdentity = true;
509  }
510 
511  // map first row to (*,*,0)
512  fLength = sqrt(kA[0][1] * kA[0][1] + kA[0][2] * kA[0][2]);
513 
514  if ( fLength > 0.0 ) {
515  fSign = (kA[0][1] > 0.0 ? 1.0f : -1.0f);
516  fT1 = kA[0][1] + fSign * fLength;
517  afV[2] = kA[0][2] / fT1;
518 
519  fT2 = -2.0f / (1.0f + afV[2] * afV[2]);
520  afW[0] = fT2 * (kA[0][1] + kA[0][2] * afV[2]);
521  afW[1] = fT2 * (kA[1][1] + kA[1][2] * afV[2]);
522  afW[2] = fT2 * (kA[2][1] + kA[2][2] * afV[2]);
523  kA[0][1] += afW[0];
524  kA[1][1] += afW[1];
525  kA[1][2] += afW[1] * afV[2];
526  kA[2][1] += afW[2];
527  kA[2][2] += afW[2] * afV[2];
528 
529  kR[0][0] = 1.0f;
530  kR[0][1] = kR[1][0] = 0.0f;
531  kR[0][2] = kR[2][0] = 0.0f;
532  kR[1][1] = 1.0f + fT2;
533  kR[1][2] = kR[2][1] = fT2 * afV[2];
534  kR[2][2] = 1.0f + fT2 * afV[2] * afV[2];
535  } else {
536  kR = Matrix3::identity();
537  }
538 
539  // map second column to (*,*,0)
540  fLength = sqrt(kA[1][1] * kA[1][1] + kA[2][1] * kA[2][1]);
541 
542  if ( fLength > 0.0 ) {
543  fSign = (kA[1][1] > 0.0 ? 1.0f : -1.0f);
544  fT1 = kA[1][1] + fSign * fLength;
545  afV[2] = kA[2][1] / fT1;
546 
547  fT2 = -2.0f / (1.0f + afV[2] * afV[2]);
548  afW[1] = fT2 * (kA[1][1] + kA[2][1] * afV[2]);
549  afW[2] = fT2 * (kA[1][2] + kA[2][2] * afV[2]);
550  kA[1][1] += afW[1];
551  kA[1][2] += afW[2];
552  kA[2][2] += afV[2] * afW[2];
553 
554  float fA = 1.0f + fT2;
555  float fB = fT2 * afV[2];
556  float fC = 1.0f + fB * afV[2];
557 
558  if ( bIdentity ) {
559  kL[0][0] = 1.0;
560  kL[0][1] = kL[1][0] = 0.0;
561  kL[0][2] = kL[2][0] = 0.0;
562  kL[1][1] = fA;
563  kL[1][2] = kL[2][1] = fB;
564  kL[2][2] = fC;
565  } else {
566  for (int iRow = 0; iRow < 3; ++iRow) {
567  float fTmp0 = kL[iRow][1];
568  float fTmp1 = kL[iRow][2];
569  kL[iRow][1] = fA * fTmp0 + fB * fTmp1;
570  kL[iRow][2] = fB * fTmp0 + fC * fTmp1;
571  }
572  }
573  }
574 }
static const Matrix3 & identity()
Definition: Matrix3.cpp:70

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Vector3 G3D::Matrix3::column ( int  c) const
203  {
204  assert((0 <= iCol) && (iCol < 3));
205  return Vector3(elt[0][iCol], elt[1][iCol],
206  elt[2][iCol]);
207 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

void G3D::Matrix3::deserialize ( class BinaryInput b)
182  {
183  int r,c;
184  for (c = 0; c < 3; ++c) {
185  for (r = 0; r < 3; ++r) {
186  elt[r][c] = b.readFloat32();
187  }
188  }
189 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

float G3D::Matrix3::determinant ( ) const
453  {
454  float fCofactor00 = elt[1][1] * elt[2][2] -
455  elt[1][2] * elt[2][1];
456  float fCofactor10 = elt[1][2] * elt[2][0] -
457  elt[1][0] * elt[2][2];
458  float fCofactor20 = elt[1][0] * elt[2][1] -
459  elt[1][1] * elt[2][0];
460 
461  float fDet =
462  elt[0][0] * fCofactor00 +
463  elt[0][1] * fCofactor10 +
464  elt[0][2] * fCofactor20;
465 
466  return fDet;
467 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

static Matrix3 G3D::Matrix3::diagonal ( float  e00,
float  e11,
float  e22 
)
inlinestatic
99  {
100  return Matrix3(e00, 0, 0,
101  0, e11, 0,
102  0, 0, e22);
103  }
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

float G3D::Matrix3::diffOneNorm ( const Matrix3 y) const
1246  {
1247  float oneNorm = 0;
1248 
1249  for (int c = 0; c < 3; ++c){
1250 
1251  float f = fabs(elt[0][c] - y[0][c]) + fabs(elt[1][c] - y[1][c])
1252  + fabs(elt[2][c] - y[2][c]);
1253 
1254  if (f > oneNorm) {
1255  oneNorm = f;
1256  }
1257  }
1258  return oneNorm;
1259 }
G3D::int16 y
Definition: Vector2int16.h:38
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

void G3D::Matrix3::eigenSolveSymmetric ( float  afEigenvalue[3],
Vector3  akEigenvector[3] 
) const

eigensolver, matrix must be symmetric

1826  {
1827  Matrix3 kMatrix = *this;
1828  float afSubDiag[3];
1829  kMatrix.tridiagonal(afEigenvalue, afSubDiag);
1830  kMatrix.qLAlgorithm(afEigenvalue, afSubDiag);
1831 
1832  for (int i = 0; i < 3; ++i) {
1833  akEigenvector[i][0] = kMatrix[0][i];
1834  akEigenvector[i][1] = kMatrix[1][i];
1835  akEigenvector[i][2] = kMatrix[2][i];
1836  }
1837 
1838  // make eigenvectors form a right--handed system
1839  Vector3 kCross = akEigenvector[1].cross(akEigenvector[2]);
1840 
1841  float fDet = akEigenvector[0].dot(kCross);
1842 
1843  if ( fDet < 0.0 ) {
1844  akEigenvector[2][0] = - akEigenvector[2][0];
1845  akEigenvector[2][1] = - akEigenvector[2][1];
1846  akEigenvector[2][2] = - akEigenvector[2][2];
1847  }
1848 }
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

float G3D::Matrix3::frobeniusNorm ( ) const
1210  {
1211  return sqrtf(squaredFrobeniusNorm());
1212 }
float squaredFrobeniusNorm() const
Definition: Matrix3.cpp:1198

+ Here is the call graph for this function:

Matrix3 G3D::Matrix3::fromAxisAngle ( const Vector3 rkAxis,
float  fRadians 
)
static
See also
fromUnitAxisAngle
1346  {
1347  return fromUnitAxisAngle(_axis.direction(), fRadians);
1348 }
static Matrix3 fromUnitAxisAngle(const Vector3 &rkAxis, float fRadians)
Definition: Matrix3.cpp:1350

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static Matrix3 G3D::Matrix3::fromColumns ( const Vector3 c0,
const Vector3 c1,
const Vector3 c2 
)
inlinestatic
59  {
60  Matrix3 m;
61  for (int r = 0; r < 3; ++r) {
62  m.elt[r][0] = c0[r];
63  m.elt[r][1] = c1[r];
64  m.elt[r][2] = c2[r];
65  }
66  return m;
67  }
Matrix3()
Definition: Matrix3.h:83
static Matrix3 G3D::Matrix3::fromDiagonal ( const Vector3 d)
inlinestatic
297  {
298  return Matrix3(d.x, 0, 0,
299  0, d.y, 0,
300  0, 0, d.z);
301  }
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

Matrix3 G3D::Matrix3::fromEulerAnglesXYZ ( float  fYAngle,
float  fPAngle,
float  fRAngle 
)
static
1558  {
1559  float fCos, fSin;
1560 
1561  fCos = cosf(fYAngle);
1562  fSin = sinf(fYAngle);
1563  Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0, fSin, fCos);
1564 
1565  fCos = cosf(fPAngle);
1566  fSin = sinf(fPAngle);
1567  Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos);
1568 
1569  fCos = cosf(fRAngle);
1570  fSin = sinf(fRAngle);
1571  Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f);
1572 
1573  return kXMat * (kYMat * kZMat);
1574 }
Matrix3()
Definition: Matrix3.h:83

+ Here is the caller graph for this function:

Matrix3 G3D::Matrix3::fromEulerAnglesXZY ( float  fYAngle,
float  fPAngle,
float  fRAngle 
)
static
1578  {
1579 
1580  float fCos, fSin;
1581 
1582  fCos = cosf(fYAngle);
1583  fSin = sinf(fYAngle);
1584  Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos);
1585 
1586  fCos = cosf(fPAngle);
1587  fSin = sinf(fPAngle);
1588  Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0);
1589 
1590  fCos = cosf(fRAngle);
1591  fSin = sinf(fRAngle);
1592  Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos);
1593 
1594  return kXMat * (kZMat * kYMat);
1595 }
Matrix3()
Definition: Matrix3.h:83
Matrix3 G3D::Matrix3::fromEulerAnglesYXZ ( float  fYAngle,
float  fPAngle,
float  fRAngle 
)
static
1601  {
1602 
1603  float fCos, fSin;
1604 
1605  fCos = cos(fYAngle);
1606  fSin = sin(fYAngle);
1607  Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos);
1608 
1609  fCos = cos(fPAngle);
1610  fSin = sin(fPAngle);
1611  Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos);
1612 
1613  fCos = cos(fRAngle);
1614  fSin = sin(fRAngle);
1615  Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f);
1616 
1617  return kYMat * (kXMat * kZMat);
1618 }
Matrix3()
Definition: Matrix3.h:83

+ Here is the caller graph for this function:

Matrix3 G3D::Matrix3::fromEulerAnglesYZX ( float  fYAngle,
float  fPAngle,
float  fRAngle 
)
static
1624  {
1625 
1626  float fCos, fSin;
1627 
1628  fCos = cos(fYAngle);
1629  fSin = sin(fYAngle);
1630  Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos);
1631 
1632  fCos = cos(fPAngle);
1633  fSin = sin(fPAngle);
1634  Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f);
1635 
1636  fCos = cos(fRAngle);
1637  fSin = sin(fRAngle);
1638  Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos);
1639 
1640  return kYMat * (kZMat * kXMat);
1641 }
Matrix3()
Definition: Matrix3.h:83
Matrix3 G3D::Matrix3::fromEulerAnglesZXY ( float  fYAngle,
float  fPAngle,
float  fRAngle 
)
static
1645  {
1646  float fCos, fSin;
1647 
1648  fCos = cos(fYAngle);
1649  fSin = sin(fYAngle);
1650  Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0);
1651 
1652  fCos = cos(fPAngle);
1653  fSin = sin(fPAngle);
1654  Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos);
1655 
1656  fCos = cos(fRAngle);
1657  fSin = sin(fRAngle);
1658  Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos);
1659 
1660  return kZMat * (kXMat * kYMat);
1661 }
Matrix3()
Definition: Matrix3.h:83
Matrix3 G3D::Matrix3::fromEulerAnglesZYX ( float  fYAngle,
float  fPAngle,
float  fRAngle 
)
static
1665  {
1666  float fCos, fSin;
1667 
1668  fCos = cos(fYAngle);
1669  fSin = sin(fYAngle);
1670  Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0);
1671 
1672  fCos = cos(fPAngle);
1673  fSin = sin(fPAngle);
1674  Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos);
1675 
1676  fCos = cos(fRAngle);
1677  fSin = sin(fRAngle);
1678  Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos);
1679 
1680  return kZMat * (kYMat * kXMat);
1681 }
Matrix3()
Definition: Matrix3.h:83

+ Here is the caller graph for this function:

static Matrix3 G3D::Matrix3::fromRows ( const Vector3 r0,
const Vector3 r1,
const Vector3 r2 
)
inlinestatic
69  {
70  Matrix3 m;
71  for (int c = 0; c < 3; ++c) {
72  m.elt[0][c] = r0[c];
73  m.elt[1][c] = r1[c];
74  m.elt[2][c] = r2[c];
75  }
76  return m;
77  }
Matrix3()
Definition: Matrix3.h:83
Matrix3 G3D::Matrix3::fromUnitAxisAngle ( const Vector3 rkAxis,
float  fRadians 
)
static

Assumes that rkAxis has unit length

1350  {
1351  debugAssertM(axis.isUnit(), "Matrix3::fromUnitAxisAngle requires ||axis|| = 1");
1352 
1353  Matrix3 m;
1354  float fCos = cos(fRadians);
1355  float fSin = sin(fRadians);
1356  float fOneMinusCos = 1.0f - fCos;
1357  float fX2 = square(axis.x);
1358  float fY2 = square(axis.y);
1359  float fZ2 = square(axis.z);
1360  float fXYM = axis.x * axis.y * fOneMinusCos;
1361  float fXZM = axis.x * axis.z * fOneMinusCos;
1362  float fYZM = axis.y * axis.z * fOneMinusCos;
1363  float fXSin = axis.x * fSin;
1364  float fYSin = axis.y * fSin;
1365  float fZSin = axis.z * fSin;
1366 
1367  m.elt[0][0] = fX2 * fOneMinusCos + fCos;
1368  m.elt[0][1] = fXYM - fZSin;
1369  m.elt[0][2] = fXZM + fYSin;
1370 
1371  m.elt[1][0] = fXYM + fZSin;
1372  m.elt[1][1] = fY2 * fOneMinusCos + fCos;
1373  m.elt[1][2] = fYZM - fXSin;
1374 
1375  m.elt[2][0] = fXZM - fYSin;
1376  m.elt[2][1] = fYZM + fXSin;
1377  m.elt[2][2] = fZ2 * fOneMinusCos + fCos;
1378 
1379  return m;
1380 }
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
double square(double fValue)
Definition: g3dmath.h:698
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool G3D::Matrix3::fuzzyEq ( const Matrix3 b) const
83  {
84  for (int r = 0; r < 3; ++r) {
85  for (int c = 0; c < 3; ++c) {
86  if (! G3D::fuzzyEq(elt[r][c], b[r][c])) {
87  return false;
88  }
89  }
90  }
91  return true;
92 }
float elt[3][3]
Definition: Matrix3.h:41
bool fuzzyEq(double a, double b)
Definition: g3dmath.h:857

+ Here is the call graph for this function:

void G3D::Matrix3::golubKahanStep ( Matrix3 kA,
Matrix3 kL,
Matrix3 kR 
)
staticprotected
578  {
579  float fT11 = kA[0][1] * kA[0][1] + kA[1][1] * kA[1][1];
580  float fT22 = kA[1][2] * kA[1][2] + kA[2][2] * kA[2][2];
581  float fT12 = kA[1][1] * kA[1][2];
582  float fTrace = fT11 + fT22;
583  float fDiff = fT11 - fT22;
584  float fDiscr = sqrt(fDiff * fDiff + 4.0f * fT12 * fT12);
585  float fRoot1 = 0.5f * (fTrace + fDiscr);
586  float fRoot2 = 0.5f * (fTrace - fDiscr);
587 
588  // adjust right
589  float fY = kA[0][0] - (G3D::abs(fRoot1 - fT22) <=
590  G3D::abs(fRoot2 - fT22) ? fRoot1 : fRoot2);
591  float fZ = kA[0][1];
592  float fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
593  float fSin = fZ * fInvLength;
594  float fCos = -fY * fInvLength;
595 
596  float fTmp0 = kA[0][0];
597  float fTmp1 = kA[0][1];
598  kA[0][0] = fCos * fTmp0 - fSin * fTmp1;
599  kA[0][1] = fSin * fTmp0 + fCos * fTmp1;
600  kA[1][0] = -fSin * kA[1][1];
601  kA[1][1] *= fCos;
602 
603  int iRow;
604 
605  for (iRow = 0; iRow < 3; ++iRow) {
606  fTmp0 = kR[0][iRow];
607  fTmp1 = kR[1][iRow];
608  kR[0][iRow] = fCos * fTmp0 - fSin * fTmp1;
609  kR[1][iRow] = fSin * fTmp0 + fCos * fTmp1;
610  }
611 
612  // adjust left
613  fY = kA[0][0];
614 
615  fZ = kA[1][0];
616 
617  fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
618 
619  fSin = fZ * fInvLength;
620 
621  fCos = -fY * fInvLength;
622 
623  kA[0][0] = fCos * kA[0][0] - fSin * kA[1][0];
624 
625  fTmp0 = kA[0][1];
626 
627  fTmp1 = kA[1][1];
628 
629  kA[0][1] = fCos * fTmp0 - fSin * fTmp1;
630 
631  kA[1][1] = fSin * fTmp0 + fCos * fTmp1;
632 
633  kA[0][2] = -fSin * kA[1][2];
634 
635  kA[1][2] *= fCos;
636 
637  int iCol;
638 
639  for (iCol = 0; iCol < 3; ++iCol) {
640  fTmp0 = kL[iCol][0];
641  fTmp1 = kL[iCol][1];
642  kL[iCol][0] = fCos * fTmp0 - fSin * fTmp1;
643  kL[iCol][1] = fSin * fTmp0 + fCos * fTmp1;
644  }
645 
646  // adjust right
647  fY = kA[0][1];
648 
649  fZ = kA[0][2];
650 
651  fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
652 
653  fSin = fZ * fInvLength;
654 
655  fCos = -fY * fInvLength;
656 
657  kA[0][1] = fCos * kA[0][1] - fSin * kA[0][2];
658 
659  fTmp0 = kA[1][1];
660 
661  fTmp1 = kA[1][2];
662 
663  kA[1][1] = fCos * fTmp0 - fSin * fTmp1;
664 
665  kA[1][2] = fSin * fTmp0 + fCos * fTmp1;
666 
667  kA[2][1] = -fSin * kA[2][2];
668 
669  kA[2][2] *= fCos;
670 
671  for (iRow = 0; iRow < 3; ++iRow) {
672  fTmp0 = kR[1][iRow];
673  fTmp1 = kR[2][iRow];
674  kR[1][iRow] = fCos * fTmp0 - fSin * fTmp1;
675  kR[2][iRow] = fSin * fTmp0 + fCos * fTmp1;
676  }
677 
678  // adjust left
679  fY = kA[1][1];
680 
681  fZ = kA[2][1];
682 
683  fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
684 
685  fSin = fZ * fInvLength;
686 
687  fCos = -fY * fInvLength;
688 
689  kA[1][1] = fCos * kA[1][1] - fSin * kA[2][1];
690 
691  fTmp0 = kA[1][2];
692 
693  fTmp1 = kA[2][2];
694 
695  kA[1][2] = fCos * fTmp0 - fSin * fTmp1;
696 
697  kA[2][2] = fSin * fTmp0 + fCos * fTmp1;
698 
699  for (iCol = 0; iCol < 3; ++iCol) {
700  fTmp0 = kL[iCol][1];
701  fTmp1 = kL[iCol][2];
702  kL[iCol][1] = fCos * fTmp0 - fSin * fTmp1;
703  kL[iCol][2] = fSin * fTmp0 + fCos * fTmp1;
704  }
705 }
double abs(double fValue)
Definition: g3dmath.h:617

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

const Matrix3 & G3D::Matrix3::identity ( )
static
70  {
71  static Matrix3 m(1, 0, 0, 0, 1, 0, 0, 0, 1);
72  return m;
73 }
Matrix3()
Definition: Matrix3.h:83

+ Here is the caller graph for this function:

bool G3D::Matrix3::inverse ( Matrix3 rkInverse,
float  fTolerance = 1e-06f 
) const
404  {
405  // Invert a 3x3 using cofactors. This is about 8 times faster than
406  // the Numerical Recipes code which uses Gaussian elimination.
407 
408  rkInverse[0][0] = elt[1][1] * elt[2][2] -
409  elt[1][2] * elt[2][1];
410  rkInverse[0][1] = elt[0][2] * elt[2][1] -
411  elt[0][1] * elt[2][2];
412  rkInverse[0][2] = elt[0][1] * elt[1][2] -
413  elt[0][2] * elt[1][1];
414  rkInverse[1][0] = elt[1][2] * elt[2][0] -
415  elt[1][0] * elt[2][2];
416  rkInverse[1][1] = elt[0][0] * elt[2][2] -
417  elt[0][2] * elt[2][0];
418  rkInverse[1][2] = elt[0][2] * elt[1][0] -
419  elt[0][0] * elt[1][2];
420  rkInverse[2][0] = elt[1][0] * elt[2][1] -
421  elt[1][1] * elt[2][0];
422  rkInverse[2][1] = elt[0][1] * elt[2][0] -
423  elt[0][0] * elt[2][1];
424  rkInverse[2][2] = elt[0][0] * elt[1][1] -
425  elt[0][1] * elt[1][0];
426 
427  float fDet =
428  elt[0][0] * rkInverse[0][0] +
429  elt[0][1] * rkInverse[1][0] +
430  elt[0][2] * rkInverse[2][0];
431 
432  if ( G3D::abs(fDet) <= fTolerance )
433  return false;
434 
435  float fInvDet = 1.0f / fDet;
436 
437  for (int iRow = 0; iRow < 3; ++iRow) {
438  for (int iCol = 0; iCol < 3; ++iCol)
439  rkInverse[iRow][iCol] *= fInvDet;
440  }
441 
442  return true;
443 }
double abs(double fValue)
Definition: g3dmath.h:617
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Matrix3 G3D::Matrix3::inverse ( float  fTolerance = 1e-06f) const
446  {
447  Matrix3 kInverse = Matrix3::zero();
448  inverse(kInverse, fTolerance);
449  return kInverse;
450 }
bool inverse(Matrix3 &rkInverse, float fTolerance=1e-06f) const
Definition: Matrix3.cpp:404
static const Matrix3 & zero()
Definition: Matrix3.cpp:65
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

bool G3D::Matrix3::isOrthonormal ( ) const

Returns true if the rows and column L2 norms are 1.0 and the rows are orthogonal.

107  {
108  const Vector3& X = column(0);
109  const Vector3& Y = column(1);
110  const Vector3& Z = column(2);
111 
112  return
113  (G3D::fuzzyEq(X.dot(Y), 0.0f) &&
114  G3D::fuzzyEq(Y.dot(Z), 0.0f) &&
115  G3D::fuzzyEq(X.dot(Z), 0.0f) &&
116  G3D::fuzzyEq(X.squaredMagnitude(), 1.0f) &&
117  G3D::fuzzyEq(Y.squaredMagnitude(), 1.0f) &&
118  G3D::fuzzyEq(Z.squaredMagnitude(), 1.0f));
119 }
#define Z
Definition: CollisionDetection.cpp:2283
#define X
Definition: CollisionDetection.cpp:2281
Vector3 column(int c) const
Definition: Matrix3.cpp:203
bool fuzzyEq(double a, double b)
Definition: g3dmath.h:857
#define Y
Definition: CollisionDetection.cpp:2282

+ Here is the call graph for this function:

bool G3D::Matrix3::isRightHanded ( ) const

Returns true if column(0).cross(column(1)).dot(column(2)) > 0.

95  {
96 
97  const Vector3& X = column(0);
98  const Vector3& Y = column(1);
99  const Vector3& Z = column(2);
100 
101  const Vector3& W = X.cross(Y);
102 
103  return W.dot(Z) > 0.0f;
104 }
#define Z
Definition: CollisionDetection.cpp:2283
#define X
Definition: CollisionDetection.cpp:2281
Vector3 column(int c) const
Definition: Matrix3.cpp:203
#define Y
Definition: CollisionDetection.cpp:2282

+ Here is the call graph for this function:

float G3D::Matrix3::l1Norm ( ) const
1215  {
1216  // The one norm of a matrix is the max column sum in absolute value.
1217  float oneNorm = 0;
1218  for (int c = 0; c < 3; ++c) {
1219 
1220  float f = fabs(elt[0][c])+ fabs(elt[1][c]) + fabs(elt[2][c]);
1221 
1222  if (f > oneNorm) {
1223  oneNorm = f;
1224  }
1225  }
1226  return oneNorm;
1227 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

float G3D::Matrix3::lInfNorm ( ) const
1230  {
1231  // The infinity norm of a matrix is the max row sum in absolute value.
1232  float infNorm = 0;
1233 
1234  for (int r = 0; r < 3; ++r) {
1235 
1236  float f = fabs(elt[r][0]) + fabs(elt[r][1])+ fabs(elt[r][2]);
1237 
1238  if (f > infNorm) {
1239  infNorm = f;
1240  }
1241  }
1242  return infNorm;
1243 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

float G3D::Matrix3::maxCubicRoot ( float  afCoeff[3])
staticprotected
1106  {
1107  // Spectral norm is for A^T*A, so characteristic polynomial
1108  // P(x) = c[0]+c[1]*x+c[2]*x^2+x^3 has three positive float roots.
1109  // This yields the assertions c[0] < 0 and c[2]*c[2] >= 3*c[1].
1110 
1111  // quick out for uniform scale (triple root)
1112  const float fOneThird = 1.0f / 3.0f;
1113  const float fEpsilon = 1e-06f;
1114  float fDiscr = afCoeff[2] * afCoeff[2] - 3.0f * afCoeff[1];
1115 
1116  if ( fDiscr <= fEpsilon )
1117  return -fOneThird*afCoeff[2];
1118 
1119  // Compute an upper bound on roots of P(x). This assumes that A^T*A
1120  // has been scaled by its largest entry.
1121  float fX = 1.0f;
1122 
1123  float fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX));
1124 
1125  if ( fPoly < 0.0f ) {
1126  // uses a matrix norm to find an upper bound on maximum root
1127  fX = (float)G3D::abs(afCoeff[0]);
1128  float fTmp = 1.0f + (float)G3D::abs(afCoeff[1]);
1129 
1130  if ( fTmp > fX )
1131  fX = fTmp;
1132 
1133  fTmp = 1.0f + (float)G3D::abs(afCoeff[2]);
1134 
1135  if ( fTmp > fX )
1136  fX = fTmp;
1137  }
1138 
1139  // Newton's method to find root
1140  float fTwoC2 = 2.0f * afCoeff[2];
1141 
1142  for (int i = 0; i < 16; ++i) {
1143  fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX));
1144 
1145  if ( G3D::abs(fPoly) <= fEpsilon )
1146  return fX;
1147 
1148  float fDeriv = afCoeff[1] + fX * (fTwoC2 + 3.0f * fX);
1149 
1150  fX -= fPoly / fDeriv;
1151  }
1152 
1153  return fX;
1154 }
double abs(double fValue)
Definition: g3dmath.h:617

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void G3D::Matrix3::mul ( const Matrix3 A,
const Matrix3 B,
Matrix3 out 
)
inlinestatic

Optimized implementation of out = A * B. It is safe (but slow) to call with A, B, and out possibly pointer equal to one another.

213  {
214  if ((&out == &A) || (&out == &B)) {
215  // We need a temporary anyway, so revert to the stack method.
216  out = A * B;
217  } else {
218  // Optimized in-place multiplication.
219  _mul(A, B, out);
220  }
221  }
static void _mul(const Matrix3 &A, const Matrix3 &B, Matrix3 &out)
Definition: Matrix3.cpp:1869

+ Here is the call graph for this function:

G3D::Matrix3::operator const float * ( ) const
inline
137  {
138  return (const float*)&elt[0][0];
139  }
float elt[3][3]
Definition: Matrix3.h:41
G3D::Matrix3::operator float * ( )
inline
133  {
134  return (float*)&elt[0][0];
135  }
float elt[3][3]
Definition: Matrix3.h:41
bool G3D::Matrix3::operator!= ( const Matrix3 rkMatrix) const
245  {
246  return !operator==(rkMatrix);
247 }
bool operator==(const Matrix3 &rkMatrix) const
Definition: Matrix3.cpp:233

+ Here is the call graph for this function:

Matrix3 G3D::Matrix3::operator* ( const Matrix3 rkMatrix) const

Matrix-matrix multiply

278  {
279  Matrix3 kProd;
280 
281  for (int iRow = 0; iRow < 3; ++iRow) {
282  for (int iCol = 0; iCol < 3; ++iCol) {
283  kProd.elt[iRow][iCol] =
284  elt[iRow][0] * rkMatrix.elt[0][iCol] +
285  elt[iRow][1] * rkMatrix.elt[1][iCol] +
286  elt[iRow][2] * rkMatrix.elt[2][iCol];
287  }
288  }
289 
290  return kProd;
291 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
Vector3 G3D::Matrix3::operator* ( const Vector3 v) const
inline

matrix * vector [3x3 * 3x1 = 3x1]

170  {
171  Vector3 kProd;
172 
173  for (int r = 0; r < 3; ++r) {
174  kProd[r] =
175  elt[r][0] * v[0] +
176  elt[r][1] * v[1] +
177  elt[r][2] * v[2];
178  }
179 
180  return kProd;
181  }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3 G3D::Matrix3::operator* ( float  fScalar) const

matrix * scalar

342  {
343  Matrix3 kProd;
344 
345  for (int iRow = 0; iRow < 3; ++iRow) {
346  for (int iCol = 0; iCol < 3; ++iCol) {
347  kProd[iRow][iCol] = fScalar * elt[iRow][iCol];
348  }
349  }
350 
351  return kProd;
352 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
Matrix3 & G3D::Matrix3::operator*= ( const Matrix3 rkMatrix)
313  {
314  Matrix3 mulMat;
315  for (int iRow = 0; iRow < 3; ++iRow) {
316  for (int iCol = 0; iCol < 3; ++iCol) {
317  mulMat.elt[iRow][iCol] =
318  elt[iRow][0] * rkMatrix.elt[0][iCol] +
319  elt[iRow][1] * rkMatrix.elt[1][iCol] +
320  elt[iRow][2] * rkMatrix.elt[2][iCol];
321  }
322  }
323 
324  *this = mulMat;
325  return *this;
326 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
Matrix3 & G3D::Matrix3::operator*= ( float  k)
358  {
359 
360  for (int iRow = 0; iRow < 3; ++iRow) {
361  for (int iCol = 0; iCol < 3; ++iCol) {
362  elt[iRow][iCol] *= fScalar;
363  }
364  }
365 
366  return *this;
367 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3 G3D::Matrix3::operator+ ( const Matrix3 rkMatrix) const
250  {
251  Matrix3 kSum;
252 
253  for (int iRow = 0; iRow < 3; ++iRow) {
254  for (int iCol = 0; iCol < 3; ++iCol) {
255  kSum.elt[iRow][iCol] = elt[iRow][iCol] +
256  rkMatrix.elt[iRow][iCol];
257  }
258  }
259 
260  return kSum;
261 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
Matrix3 & G3D::Matrix3::operator+= ( const Matrix3 rkMatrix)
293  {
294  for (int iRow = 0; iRow < 3; ++iRow) {
295  for (int iCol = 0; iCol < 3; ++iCol) {
296  elt[iRow][iCol] = elt[iRow][iCol] + rkMatrix.elt[iRow][iCol];
297  }
298  }
299 
300  return *this;
301 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3 G3D::Matrix3::operator- ( const Matrix3 rkMatrix) const
264  {
265  Matrix3 kDiff;
266 
267  for (int iRow = 0; iRow < 3; ++iRow) {
268  for (int iCol = 0; iCol < 3; ++iCol) {
269  kDiff.elt[iRow][iCol] = elt[iRow][iCol] -
270  rkMatrix.elt[iRow][iCol];
271  }
272  }
273 
274  return kDiff;
275 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
Matrix3 G3D::Matrix3::operator- ( ) const
329  {
330  Matrix3 kNeg;
331 
332  for (int iRow = 0; iRow < 3; ++iRow) {
333  for (int iCol = 0; iCol < 3; ++iCol) {
334  kNeg[iRow][iCol] = -elt[iRow][iCol];
335  }
336  }
337 
338  return kNeg;
339 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
Matrix3 & G3D::Matrix3::operator-= ( const Matrix3 rkMatrix)
303  {
304  for (int iRow = 0; iRow < 3; ++iRow) {
305  for (int iCol = 0; iCol < 3; ++iCol) {
306  elt[iRow][iCol] = elt[iRow][iCol] - rkMatrix.elt[iRow][iCol];
307  }
308  }
309 
310  return *this;
311 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3 & G3D::Matrix3::operator/= ( float  k)
354  {
355  return *this *= (1.0f / fScalar);
356 }
bool G3D::Matrix3::operator< ( const Matrix3 ) const
private
bool G3D::Matrix3::operator<= ( const Matrix3 ) const
private
Matrix3& G3D::Matrix3::operator= ( const Matrix3 rkMatrix)
inline
148  {
149  memcpy(elt, rkMatrix.elt, 9 * sizeof(float));
150  return *this;
151  }
float elt[3][3]
Definition: Matrix3.h:41
bool G3D::Matrix3::operator== ( const Matrix3 rkMatrix) const
233  {
234  for (int iRow = 0; iRow < 3; ++iRow) {
235  for (int iCol = 0; iCol < 3; ++iCol) {
236  if ( elt[iRow][iCol] != rkMatrix.elt[iRow][iCol] )
237  return false;
238  }
239  }
240 
241  return true;
242 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

bool G3D::Matrix3::operator> ( const Matrix3 ) const
private
bool G3D::Matrix3::operator>= ( const Matrix3 ) const
private
float* G3D::Matrix3::operator[] ( int  iRow)
inline

Member access, allows use of construct mat[r][c]

121  {
122  debugAssert(iRow >= 0);
123  debugAssert(iRow < 3);
124  return (float*)&elt[iRow][0];
125  }
#define debugAssert(exp)
Definition: debugAssert.h:160
float elt[3][3]
Definition: Matrix3.h:41
const float* G3D::Matrix3::operator[] ( int  iRow) const
inline
127  {
128  debugAssert(iRow >= 0);
129  debugAssert(iRow < 3);
130  return (const float*)&elt[iRow][0];
131  }
#define debugAssert(exp)
Definition: debugAssert.h:160
float elt[3][3]
Definition: Matrix3.h:41
void G3D::Matrix3::orthonormalize ( )

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

838  {
839  // Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is
840  // M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2],
841  //
842  // q0 = m0/|m0|
843  // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
844  // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
845  //
846  // where |V| indicates length of vector V and A*B indicates dot
847  // product of vectors A and B.
848 
849  // compute q0
850  float fInvLength = 1.0f / sqrt(elt[0][0] * elt[0][0]
851  + elt[1][0] * elt[1][0] +
852  elt[2][0] * elt[2][0]);
853 
854  elt[0][0] *= fInvLength;
855  elt[1][0] *= fInvLength;
856  elt[2][0] *= fInvLength;
857 
858  // compute q1
859  float fDot0 =
860  elt[0][0] * elt[0][1] +
861  elt[1][0] * elt[1][1] +
862  elt[2][0] * elt[2][1];
863 
864  elt[0][1] -= fDot0 * elt[0][0];
865  elt[1][1] -= fDot0 * elt[1][0];
866  elt[2][1] -= fDot0 * elt[2][0];
867 
868  fInvLength = 1.0f / sqrt(elt[0][1] * elt[0][1] +
869  elt[1][1] * elt[1][1] +
870  elt[2][1] * elt[2][1]);
871 
872  elt[0][1] *= fInvLength;
873  elt[1][1] *= fInvLength;
874  elt[2][1] *= fInvLength;
875 
876  // compute q2
877  float fDot1 =
878  elt[0][1] * elt[0][2] +
879  elt[1][1] * elt[1][2] +
880  elt[2][1] * elt[2][2];
881 
882  fDot0 =
883  elt[0][0] * elt[0][2] +
884  elt[1][0] * elt[1][2] +
885  elt[2][0] * elt[2][2];
886 
887  elt[0][2] -= fDot0 * elt[0][0] + fDot1 * elt[0][1];
888  elt[1][2] -= fDot0 * elt[1][0] + fDot1 * elt[1][1];
889  elt[2][2] -= fDot0 * elt[2][0] + fDot1 * elt[2][1];
890 
891  fInvLength = 1.0f / sqrt(elt[0][2] * elt[0][2] +
892  elt[1][2] * elt[1][2] +
893  elt[2][2] * elt[2][2]);
894 
895  elt[0][2] *= fInvLength;
896  elt[1][2] *= fInvLength;
897  elt[2][2] *= fInvLength;
898 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

void G3D::Matrix3::polarDecomposition ( Matrix3 R,
Matrix3 S 
) const

Polar decomposition of a matrix. Based on pseudocode from Nicholas J Higham, "Computing the Polar Decomposition – with Applications Siam Journal of Science and Statistical Computing, Vol 7, No. 4, October 1986.

Decomposes A into R*S, where R is orthogonal and S is symmetric.

Ken Shoemake's "Matrix animation and polar decomposition" in Proceedings of the conference on Graphics interface '92 seems to be better known in the world of graphics, but Higham's version uses a scaling constant that can lead to faster convergence than Shoemake's when the initial matrix is far from orthogonal.

1015  {
1016  /*
1017  Polar decomposition of a matrix. Based on pseudocode from
1018  Nicholas J Higham, "Computing the Polar Decomposition -- with
1019  Applications Siam Journal of Science and Statistical Computing, Vol 7, No. 4,
1020  October 1986.
1021 
1022  Decomposes A into R*S, where R is orthogonal and S is symmetric.
1023 
1024  Ken Shoemake's "Matrix animation and polar decomposition"
1025  in Proceedings of the conference on Graphics interface '92
1026  seems to be better known in the world of graphics, but Higham's version
1027  uses a scaling constant that can lead to faster convergence than
1028  Shoemake's when the initial matrix is far from orthogonal.
1029  */
1030 
1031  Matrix3 X = *this;
1032  Matrix3 tmp = X.inverse();
1033  Matrix3 Xit = tmp.transpose();
1034  int iter = 0;
1035 
1036  const int MAX_ITERS = 100;
1037 
1038  const double eps = 50 * std::numeric_limits<float>::epsilon();
1039  const float BigEps = 50.0f * (float)eps;
1040 
1041  /* Higham suggests using OneNorm(Xit-X) < eps * OneNorm(X)
1042  * as the convergence criterion, but OneNorm(X) should quickly
1043  * settle down to something between 1 and 1.7, so just comparing
1044  * with eps seems sufficient.
1045  *--------------------------------------------------------------- */
1046 
1047  double resid = X.diffOneNorm(Xit);
1048  while (resid > eps && iter < MAX_ITERS) {
1049 
1050  tmp = X.inverse();
1051  Xit = tmp.transpose();
1052 
1053  if (resid < BigEps) {
1054  // close enough use simple iteration
1055  X += Xit;
1056  X *= 0.5f;
1057  }
1058  else {
1059  // not close to convergence, compute acceleration factor
1060  float gamma = sqrt( sqrt(
1061  (Xit.l1Norm()* Xit.lInfNorm())/(X.l1Norm()*X.lInfNorm()) ) );
1062 
1063  X *= 0.5f * gamma;
1064  tmp = Xit;
1065  tmp *= 0.5f / gamma;
1066  X += tmp;
1067  }
1068 
1069  resid = X.diffOneNorm(Xit);
1070  ++iter;
1071  }
1072 
1073  R = X;
1074  tmp = R.transpose();
1075 
1076  S = tmp * (*this);
1077 
1078  // S := (S + S^t)/2 one more time to make sure it is symmetric
1079  tmp = S.transpose();
1080 
1081  S += tmp;
1082  S *= 0.5f;
1083 
1084 #ifdef G3D_DEBUG
1085  // Check iter limit
1086  assert(iter < MAX_ITERS);
1087 
1088  // Check A = R*S
1089  tmp = R*S;
1090  resid = tmp.diffOneNorm(*this);
1091  assert(resid < eps);
1092 
1093  // Check R is orthogonal
1094  tmp = R*R.transpose();
1095  resid = tmp.diffOneNorm(Matrix3::identity());
1096  assert(resid < eps);
1097 
1098  // Check that S is symmetric
1099  tmp = S.transpose();
1100  resid = tmp.diffOneNorm(S);
1101  assert(resid < eps);
1102 #endif
1103 }
#define X
Definition: CollisionDetection.cpp:2281
double eps(double a, double b)
Definition: g3dmath.h:824
static const Matrix3 & identity()
Definition: Matrix3.cpp:70
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

void G3D::Matrix3::qDUDecomposition ( Matrix3 rkQ,
Vector3 rkD,
Vector3 rkU 
) const

orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12)

902  {
903  // Factor M = QR = QDU where Q is orthogonal, D is diagonal,
904  // and U is upper triangular with ones on its diagonal. Algorithm uses
905  // Gram-Schmidt orthogonalization (the QR algorithm).
906  //
907  // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then
908  //
909  // q0 = m0/|m0|
910  // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
911  // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
912  //
913  // where |V| indicates length of vector V and A*B indicates dot
914  // product of vectors A and B. The matrix R has entries
915  //
916  // r00 = q0*m0 r01 = q0*m1 r02 = q0*m2
917  // r10 = 0 r11 = q1*m1 r12 = q1*m2
918  // r20 = 0 r21 = 0 r22 = q2*m2
919  //
920  // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00,
921  // u02 = r02/r00, and u12 = r12/r11.
922 
923  // Q = rotation
924  // D = scaling
925  // U = shear
926 
927  // D stores the three diagonal entries r00, r11, r22
928  // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12
929 
930  // build orthogonal matrix Q
931  float fInvLength = 1.0f / sqrt(elt[0][0] * elt[0][0]
932  + elt[1][0] * elt[1][0] +
933  elt[2][0] * elt[2][0]);
934  kQ[0][0] = elt[0][0] * fInvLength;
935  kQ[1][0] = elt[1][0] * fInvLength;
936  kQ[2][0] = elt[2][0] * fInvLength;
937 
938  float fDot = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] +
939  kQ[2][0] * elt[2][1];
940  kQ[0][1] = elt[0][1] - fDot * kQ[0][0];
941  kQ[1][1] = elt[1][1] - fDot * kQ[1][0];
942  kQ[2][1] = elt[2][1] - fDot * kQ[2][0];
943  fInvLength = 1.0f / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] +
944  kQ[2][1] * kQ[2][1]);
945  kQ[0][1] *= fInvLength;
946  kQ[1][1] *= fInvLength;
947  kQ[2][1] *= fInvLength;
948 
949  fDot = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] +
950  kQ[2][0] * elt[2][2];
951  kQ[0][2] = elt[0][2] - fDot * kQ[0][0];
952  kQ[1][2] = elt[1][2] - fDot * kQ[1][0];
953  kQ[2][2] = elt[2][2] - fDot * kQ[2][0];
954  fDot = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] +
955  kQ[2][1] * elt[2][2];
956  kQ[0][2] -= fDot * kQ[0][1];
957  kQ[1][2] -= fDot * kQ[1][1];
958  kQ[2][2] -= fDot * kQ[2][1];
959  fInvLength = 1.0f / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] +
960  kQ[2][2] * kQ[2][2]);
961  kQ[0][2] *= fInvLength;
962  kQ[1][2] *= fInvLength;
963  kQ[2][2] *= fInvLength;
964 
965  // guarantee that orthogonal matrix has determinant 1 (no reflections)
966  float fDet = kQ[0][0] * kQ[1][1] * kQ[2][2] + kQ[0][1] * kQ[1][2] * kQ[2][0] +
967  kQ[0][2] * kQ[1][0] * kQ[2][1] - kQ[0][2] * kQ[1][1] * kQ[2][0] -
968  kQ[0][1] * kQ[1][0] * kQ[2][2] - kQ[0][0] * kQ[1][2] * kQ[2][1];
969 
970  if ( fDet < 0.0 ) {
971  for (int iRow = 0; iRow < 3; ++iRow)
972  for (int iCol = 0; iCol < 3; ++iCol)
973  kQ[iRow][iCol] = -kQ[iRow][iCol];
974  }
975 
976  // build "right" matrix R
977  Matrix3 kR;
978 
979  kR[0][0] = kQ[0][0] * elt[0][0] + kQ[1][0] * elt[1][0] +
980  kQ[2][0] * elt[2][0];
981 
982  kR[0][1] = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] +
983  kQ[2][0] * elt[2][1];
984 
985  kR[1][1] = kQ[0][1] * elt[0][1] + kQ[1][1] * elt[1][1] +
986  kQ[2][1] * elt[2][1];
987 
988  kR[0][2] = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] +
989  kQ[2][0] * elt[2][2];
990 
991  kR[1][2] = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] +
992  kQ[2][1] * elt[2][2];
993 
994  kR[2][2] = kQ[0][2] * elt[0][2] + kQ[1][2] * elt[1][2] +
995  kQ[2][2] * elt[2][2];
996 
997  // the scaling component
998  kD[0] = kR[0][0];
999 
1000  kD[1] = kR[1][1];
1001 
1002  kD[2] = kR[2][2];
1003 
1004  // the shear component
1005  float fInvD0 = 1.0f / kD[0];
1006 
1007  kU[0] = kR[0][1] * fInvD0;
1008 
1009  kU[1] = kR[0][2] * fInvD0;
1010 
1011  kU[2] = kR[1][2] / kD[1];
1012 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
bool G3D::Matrix3::qLAlgorithm ( float  afDiag[3],
float  afSubDiag[3] 
)
protected
1740  {
1741  // QL iteration with implicit shifting to reduce matrix from tridiagonal
1742  // to diagonal
1743 
1744  for (int i0 = 0; i0 < 3; ++i0) {
1745  const int iMaxIter = 32;
1746  int iIter;
1747 
1748  for (iIter = 0; iIter < iMaxIter; ++iIter) {
1749  int i1;
1750 
1751  for (i1 = i0; i1 <= 1; ++i1) {
1752  float fSum = float(G3D::abs(afDiag[i1]) +
1753  G3D::abs(afDiag[i1 + 1]));
1754 
1755  if ( G3D::abs(afSubDiag[i1]) + fSum == fSum )
1756  break;
1757  }
1758 
1759  if ( i1 == i0 )
1760  break;
1761 
1762  float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0f * afSubDiag[i0]);
1763 
1764  float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0f);
1765 
1766  if ( fTmp0 < 0.0 )
1767  fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 - fTmp1);
1768  else
1769  fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 + fTmp1);
1770 
1771  float fSin = 1.0;
1772 
1773  float fCos = 1.0;
1774 
1775  float fTmp2 = 0.0;
1776 
1777  for (int i2 = i1 - 1; i2 >= i0; i2--) {
1778  float fTmp3 = fSin * afSubDiag[i2];
1779  float fTmp4 = fCos * afSubDiag[i2];
1780 
1781  if (G3D::abs(fTmp3) >= G3D::abs(fTmp0)) {
1782  fCos = fTmp0 / fTmp3;
1783  fTmp1 = sqrt(fCos * fCos + 1.0f);
1784  afSubDiag[i2 + 1] = fTmp3 * fTmp1;
1785  fSin = 1.0f / fTmp1;
1786  fCos *= fSin;
1787  } else {
1788  fSin = fTmp3 / fTmp0;
1789  fTmp1 = sqrt(fSin * fSin + 1.0f);
1790  afSubDiag[i2 + 1] = fTmp0 * fTmp1;
1791  fCos = 1.0f / fTmp1;
1792  fSin *= fCos;
1793  }
1794 
1795  fTmp0 = afDiag[i2 + 1] - fTmp2;
1796  fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0f * fTmp4 * fCos;
1797  fTmp2 = fSin * fTmp1;
1798  afDiag[i2 + 1] = fTmp0 + fTmp2;
1799  fTmp0 = fCos * fTmp1 - fTmp4;
1800 
1801  for (int iRow = 0; iRow < 3; ++iRow) {
1802  fTmp3 = elt[iRow][i2 + 1];
1803  elt[iRow][i2 + 1] = fSin * elt[iRow][i2] +
1804  fCos * fTmp3;
1805  elt[iRow][i2] = fCos * elt[iRow][i2] -
1806  fSin * fTmp3;
1807  }
1808  }
1809 
1810  afDiag[i0] -= fTmp2;
1811  afSubDiag[i0] = fTmp0;
1812  afSubDiag[i1] = 0.0;
1813  }
1814 
1815  if ( iIter == iMaxIter ) {
1816  // should not get here under normal circumstances
1817  return false;
1818  }
1819  }
1820 
1821  return true;
1822 }
double abs(double fValue)
Definition: g3dmath.h:617
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

const Vector3 & G3D::Matrix3::row ( int  r) const
210  {
211  assert((0 <= iRow) && (iRow < 3));
212  return *reinterpret_cast<const Vector3*>(elt[iRow]);
213 }
float elt[3][3]
Definition: Matrix3.h:41
void G3D::Matrix3::serialize ( class BinaryOutput b) const
192  {
193  int r,c;
194  for (c = 0; c < 3; ++c) {
195  for (r = 0; r < 3; ++r) {
196  b.writeFloat32(elt[r][c]);
197  }
198  }
199 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void G3D::Matrix3::set ( float  fEntry00,
float  fEntry01,
float  fEntry02,
float  fEntry10,
float  fEntry11,
float  fEntry12,
float  fEntry20,
float  fEntry21,
float  fEntry22 
)

Sets all elements.

168  {
169 
170  elt[0][0] = fEntry00;
171  elt[0][1] = fEntry01;
172  elt[0][2] = fEntry02;
173  elt[1][0] = fEntry10;
174  elt[1][1] = fEntry11;
175  elt[1][2] = fEntry12;
176  elt[2][0] = fEntry20;
177  elt[2][1] = fEntry21;
178  elt[2][2] = fEntry22;
179 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

void G3D::Matrix3::setColumn ( int  iCol,
const Vector3 vector 
)
216  {
217  debugAssert((iCol >= 0) && (iCol < 3));
218  elt[0][iCol] = vector.x;
219  elt[1][iCol] = vector.y;
220  elt[2][iCol] = vector.z;
221 }
#define debugAssert(exp)
Definition: debugAssert.h:160
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

void G3D::Matrix3::setRow ( int  iRow,
const Vector3 vector 
)
224  {
225  debugAssert((iRow >= 0) && (iRow < 3));
226  elt[iRow][0] = vector.x;
227  elt[iRow][1] = vector.y;
228  elt[iRow][2] = vector.z;
229 }
#define debugAssert(exp)
Definition: debugAssert.h:160
float elt[3][3]
Definition: Matrix3.h:41
void G3D::Matrix3::singularValueComposition ( const Matrix3 rkL,
const Vector3 rkS,
const Matrix3 rkR 
)

singular value decomposition

816  {
817  int iRow, iCol;
818  Matrix3 kTmp;
819 
820  // product S*R
821  for (iRow = 0; iRow < 3; ++iRow) {
822  for (iCol = 0; iCol < 3; ++iCol)
823  kTmp[iRow][iCol] = kS[iRow] * kR[iRow][iCol];
824  }
825 
826  // product L*S*R
827  for (iRow = 0; iRow < 3; ++iRow) {
828  for (iCol = 0; iCol < 3; ++iCol) {
829  elt[iRow][iCol] = 0.0;
830 
831  for (int iMid = 0; iMid < 3; ++iMid)
832  elt[iRow][iCol] += kL[iRow][iMid] * kTmp[iMid][iCol];
833  }
834  }
835 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
void G3D::Matrix3::singularValueDecomposition ( Matrix3 rkL,
Vector3 rkS,
Matrix3 rkR 
) const

singular value decomposition

709  {
710  int iRow, iCol;
711 
712  Matrix3 kA = *this;
713  bidiagonalize(kA, kL, kR);
714 
715  for (int i = 0; i < ms_iSvdMaxIterations; ++i) {
716  float fTmp, fTmp0, fTmp1;
717  float fSin0, fCos0, fTan0;
718  float fSin1, fCos1, fTan1;
719 
720  bool bTest1 = (G3D::abs(kA[0][1]) <=
721  ms_fSvdEpsilon * (G3D::abs(kA[0][0]) + G3D::abs(kA[1][1])));
722  bool bTest2 = (G3D::abs(kA[1][2]) <=
723  ms_fSvdEpsilon * (G3D::abs(kA[1][1]) + G3D::abs(kA[2][2])));
724 
725  if ( bTest1 ) {
726  if ( bTest2 ) {
727  kS[0] = kA[0][0];
728  kS[1] = kA[1][1];
729  kS[2] = kA[2][2];
730  break;
731  } else {
732  // 2x2 closed form factorization
733  fTmp = (kA[1][1] * kA[1][1] - kA[2][2] * kA[2][2] +
734  kA[1][2] * kA[1][2]) / (kA[1][2] * kA[2][2]);
735  fTan0 = 0.5f * (fTmp + sqrt(fTmp * fTmp + 4.0f));
736  fCos0 = 1.0f / sqrt(1.0f + fTan0 * fTan0);
737  fSin0 = fTan0 * fCos0;
738 
739  for (iCol = 0; iCol < 3; ++iCol) {
740  fTmp0 = kL[iCol][1];
741  fTmp1 = kL[iCol][2];
742  kL[iCol][1] = fCos0 * fTmp0 - fSin0 * fTmp1;
743  kL[iCol][2] = fSin0 * fTmp0 + fCos0 * fTmp1;
744  }
745 
746  fTan1 = (kA[1][2] - kA[2][2] * fTan0) / kA[1][1];
747  fCos1 = 1.0f / sqrt(1.0f + fTan1 * fTan1);
748  fSin1 = -fTan1 * fCos1;
749 
750  for (iRow = 0; iRow < 3; ++iRow) {
751  fTmp0 = kR[1][iRow];
752  fTmp1 = kR[2][iRow];
753  kR[1][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
754  kR[2][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1;
755  }
756 
757  kS[0] = kA[0][0];
758  kS[1] = fCos0 * fCos1 * kA[1][1] -
759  fSin1 * (fCos0 * kA[1][2] - fSin0 * kA[2][2]);
760  kS[2] = fSin0 * fSin1 * kA[1][1] +
761  fCos1 * (fSin0 * kA[1][2] + fCos0 * kA[2][2]);
762  break;
763  }
764  } else {
765  if ( bTest2 ) {
766  // 2x2 closed form factorization
767  fTmp = (kA[0][0] * kA[0][0] + kA[1][1] * kA[1][1] -
768  kA[0][1] * kA[0][1]) / (kA[0][1] * kA[1][1]);
769  fTan0 = 0.5f * ( -fTmp + sqrt(fTmp * fTmp + 4.0f));
770  fCos0 = 1.0f / sqrt(1.0f + fTan0 * fTan0);
771  fSin0 = fTan0 * fCos0;
772 
773  for (iCol = 0; iCol < 3; ++iCol) {
774  fTmp0 = kL[iCol][0];
775  fTmp1 = kL[iCol][1];
776  kL[iCol][0] = fCos0 * fTmp0 - fSin0 * fTmp1;
777  kL[iCol][1] = fSin0 * fTmp0 + fCos0 * fTmp1;
778  }
779 
780  fTan1 = (kA[0][1] - kA[1][1] * fTan0) / kA[0][0];
781  fCos1 = 1.0f / sqrt(1.0f + fTan1 * fTan1);
782  fSin1 = -fTan1 * fCos1;
783 
784  for (iRow = 0; iRow < 3; ++iRow) {
785  fTmp0 = kR[0][iRow];
786  fTmp1 = kR[1][iRow];
787  kR[0][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
788  kR[1][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1;
789  }
790 
791  kS[0] = fCos0 * fCos1 * kA[0][0] -
792  fSin1 * (fCos0 * kA[0][1] - fSin0 * kA[1][1]);
793  kS[1] = fSin0 * fSin1 * kA[0][0] +
794  fCos1 * (fSin0 * kA[0][1] + fCos0 * kA[1][1]);
795  kS[2] = kA[2][2];
796  break;
797  } else {
798  golubKahanStep(kA, kL, kR);
799  }
800  }
801  }
802 
803  // positize diagonal
804  for (iRow = 0; iRow < 3; ++iRow) {
805  if ( kS[iRow] < 0.0 ) {
806  kS[iRow] = -kS[iRow];
807 
808  for (iCol = 0; iCol < 3; ++iCol)
809  kR[iRow][iCol] = -kR[iRow][iCol];
810  }
811  }
812 }
static const int ms_iSvdMaxIterations
Definition: Matrix3.h:372
static const float ms_fSvdEpsilon
Definition: Matrix3.h:371
double abs(double fValue)
Definition: g3dmath.h:617
static void golubKahanStep(Matrix3 &kA, Matrix3 &kL, Matrix3 &kR)
Definition: Matrix3.cpp:577
static void bidiagonalize(Matrix3 &kA, Matrix3 &kL, Matrix3 &kR)
Definition: Matrix3.cpp:470
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

float G3D::Matrix3::spectralNorm ( ) const

Matrix norms.

1157  {
1158  Matrix3 kP;
1159  int iRow, iCol;
1160  float fPmax = 0.0;
1161 
1162  for (iRow = 0; iRow < 3; ++iRow) {
1163  for (iCol = 0; iCol < 3; ++iCol) {
1164  kP[iRow][iCol] = 0.0;
1165 
1166  for (int iMid = 0; iMid < 3; ++iMid) {
1167  kP[iRow][iCol] +=
1168  elt[iMid][iRow] * elt[iMid][iCol];
1169  }
1170 
1171  if ( kP[iRow][iCol] > fPmax )
1172  fPmax = kP[iRow][iCol];
1173  }
1174  }
1175 
1176  float fInvPmax = 1.0f / fPmax;
1177 
1178  for (iRow = 0; iRow < 3; ++iRow) {
1179  for (iCol = 0; iCol < 3; ++iCol)
1180  kP[iRow][iCol] *= fInvPmax;
1181  }
1182 
1183  float afCoeff[3];
1184  afCoeff[0] = -(kP[0][0] * (kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1]) +
1185  kP[0][1] * (kP[2][0] * kP[1][2] - kP[1][0] * kP[2][2]) +
1186  kP[0][2] * (kP[1][0] * kP[2][1] - kP[2][0] * kP[1][1]));
1187  afCoeff[1] = kP[0][0] * kP[1][1] - kP[0][1] * kP[1][0] +
1188  kP[0][0] * kP[2][2] - kP[0][2] * kP[2][0] +
1189  kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1];
1190  afCoeff[2] = -(kP[0][0] + kP[1][1] + kP[2][2]);
1191 
1192  float fRoot = maxCubicRoot(afCoeff);
1193  float fNorm = sqrt(fPmax * fRoot);
1194  return fNorm;
1195 }
static float maxCubicRoot(float afCoeff[3])
Definition: Matrix3.cpp:1106
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83

+ Here is the call graph for this function:

float G3D::Matrix3::squaredFrobeniusNorm ( ) const
1198  {
1199  float norm2 = 0;
1200  const float* e = &elt[0][0];
1201 
1202  for (int i = 0; i < 9; ++i){
1203  norm2 += (*e) * (*e);
1204  }
1205 
1206  return norm2;
1207 }
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the caller graph for this function:

void G3D::Matrix3::tensorProduct ( const Vector3 rkU,
const Vector3 rkV,
Matrix3 rkProduct 
)
static
1852  {
1853  for (int iRow = 0; iRow < 3; ++iRow) {
1854  for (int iCol = 0; iCol < 3; ++iCol) {
1855  rkProduct[iRow][iCol] = rkU[iRow] * rkV[iCol];
1856  }
1857  }
1858 }
Any G3D::Matrix3::toAny ( ) const
53  {
54  Any any(Any::ARRAY, "Matrix3");
55  any.resize(9);
56  for (int r = 0; r < 3; ++r) {
57  for (int c = 0; c < 3; ++c) {
58  any[r * 3 + c] = elt[r][c];
59  }
60  }
61 
62  return any;
63 }
bool any(float x)
Definition: g3dmath.h:424
Definition: Any.h:187
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

void G3D::Matrix3::toAxisAngle ( Vector3 rkAxis,
float &  rfRadians 
) const

matrix must be orthonormal

1262  {
1263  //
1264  // Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
1265  // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 (Rodrigues' formula) where
1266  // I is the identity and
1267  //
1268  // +- -+
1269  // P = | 0 -z +y |
1270  // | +z 0 -x |
1271  // | -y +x 0 |
1272  // +- -+
1273  //
1274  // If A > 0, R represents a counterclockwise rotation about the axis in
1275  // the sense of looking from the tip of the axis vector towards the
1276  // origin. Some algebra will show that
1277  //
1278  // cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P
1279  //
1280  // In the event that A = pi, R-R^t = 0 which prevents us from extracting
1281  // the axis through P. Instead note that R = I+2*P^2 when A = pi, so
1282  // P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and
1283  // z^2-1. We can solve these for axis (x,y,z). Because the angle is pi,
1284  // it does not matter which sign you choose on the square roots.
1285 
1286  float fTrace = elt[0][0] + elt[1][1] + elt[2][2];
1287  float fCos = 0.5f * (fTrace - 1.0f);
1288  rfRadians = (float)G3D::aCos(fCos); // in [0,PI]
1289 
1290  if ( rfRadians > 0.0 ) {
1291  if ( rfRadians < pi() ) {
1292  rkAxis.x = elt[2][1] - elt[1][2];
1293  rkAxis.y = elt[0][2] - elt[2][0];
1294  rkAxis.z = elt[1][0] - elt[0][1];
1295  rkAxis = rkAxis.direction();
1296  } else {
1297  // angle is PI
1298  float fHalfInverse;
1299 
1300  if ( elt[0][0] >= elt[1][1] ) {
1301  // r00 >= r11
1302  if ( elt[0][0] >= elt[2][2] ) {
1303  // r00 is maximum diagonal term
1304  rkAxis.x = 0.5f * sqrt(elt[0][0] -
1305  elt[1][1] - elt[2][2] + 1.0f);
1306  fHalfInverse = 0.5f / rkAxis.x;
1307  rkAxis.y = fHalfInverse * elt[0][1];
1308  rkAxis.z = fHalfInverse * elt[0][2];
1309  } else {
1310  // r22 is maximum diagonal term
1311  rkAxis.z = 0.5f * sqrt(elt[2][2] -
1312  elt[0][0] - elt[1][1] + 1.0f);
1313  fHalfInverse = 0.5f / rkAxis.z;
1314  rkAxis.x = fHalfInverse * elt[0][2];
1315  rkAxis.y = fHalfInverse * elt[1][2];
1316  }
1317  } else {
1318  // r11 > r00
1319  if ( elt[1][1] >= elt[2][2] ) {
1320  // r11 is maximum diagonal term
1321  rkAxis.y = 0.5f * sqrt(elt[1][1] -
1322  elt[0][0] - elt[2][2] + 1.0f);
1323  fHalfInverse = 0.5f / rkAxis.y;
1324  rkAxis.x = fHalfInverse * elt[0][1];
1325  rkAxis.z = fHalfInverse * elt[1][2];
1326  } else {
1327  // r22 is maximum diagonal term
1328  rkAxis.z = 0.5f * sqrt(elt[2][2] -
1329  elt[0][0] - elt[1][1] + 1.0f);
1330  fHalfInverse = 0.5f / rkAxis.z;
1331  rkAxis.x = fHalfInverse * elt[0][2];
1332  rkAxis.y = fHalfInverse * elt[1][2];
1333  }
1334  }
1335  }
1336  } else {
1337  // The angle is 0 and the matrix is the identity. Any axis will
1338  // work, so just use the x-axis.
1339  rkAxis.x = 1.0;
1340  rkAxis.y = 0.0;
1341  rkAxis.z = 0.0;
1342  }
1343 }
double pi()
Definition: g3dmath.h:147
double aCos(double fValue)
Definition: g3dmath.h:622
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

bool G3D::Matrix3::toEulerAnglesXYZ ( float &  rfYAngle,
float &  rfPAngle,
float &  rfRAngle 
) const

The matrix must be orthonormal. The decomposition is yaw*pitch*roll where yaw is rotation about the Up vector, pitch is rotation about the right axis, and roll is rotation about the Direction axis.

1384  {
1385  // rot = cy*cz -cy*sz sy
1386  // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
1387  // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
1388 
1389  if ( elt[0][2] < 1.0f ) {
1390  if ( elt[0][2] > -1.0f ) {
1391  rfXAngle = (float) G3D::aTan2( -elt[1][2], elt[2][2]);
1392  rfYAngle = (float) G3D::aSin(elt[0][2]);
1393  rfZAngle = (float) G3D::aTan2( -elt[0][1], elt[0][0]);
1394  return true;
1395  } else {
1396  // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
1397  rfXAngle = -(float)G3D::aTan2(elt[1][0], elt[1][1]);
1398  rfYAngle = -(float)halfPi();
1399  rfZAngle = 0.0f;
1400  return false;
1401  }
1402  } else {
1403  // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
1404  rfXAngle = (float)G3D::aTan2(elt[1][0], elt[1][1]);
1405  rfYAngle = (float)halfPi();
1406  rfZAngle = 0.0f;
1407  return false;
1408  }
1409 }
double aTan2(double fY, double fX)
Definition: g3dmath.h:664
double aSin(double fValue)
Definition: g3dmath.h:646
float elt[3][3]
Definition: Matrix3.h:41
double halfPi()
Definition: g3dmath.h:155

+ Here is the call graph for this function:

bool G3D::Matrix3::toEulerAnglesXZY ( float &  rfYAngle,
float &  rfPAngle,
float &  rfRAngle 
) const
1413  {
1414  // rot = cy*cz -sz cz*sy
1415  // sx*sy+cx*cy*sz cx*cz -cy*sx+cx*sy*sz
1416  // -cx*sy+cy*sx*sz cz*sx cx*cy+sx*sy*sz
1417 
1418  if ( elt[0][1] < 1.0f ) {
1419  if ( elt[0][1] > -1.0f ) {
1420  rfXAngle = (float) G3D::aTan2(elt[2][1], elt[1][1]);
1421  rfZAngle = (float) asin( -elt[0][1]);
1422  rfYAngle = (float) G3D::aTan2(elt[0][2], elt[0][0]);
1423  return true;
1424  } else {
1425  // WARNING. Not unique. XA - YA = atan2(r20,r22)
1426  rfXAngle = (float)G3D::aTan2(elt[2][0], elt[2][2]);
1427  rfZAngle = (float)halfPi();
1428  rfYAngle = 0.0f;
1429  return false;
1430  }
1431  } else {
1432  // WARNING. Not unique. XA + YA = atan2(-r20,r22)
1433  rfXAngle = (float)G3D::aTan2( -elt[2][0], elt[2][2]);
1434  rfZAngle = -(float)halfPi();
1435  rfYAngle = 0.0f;
1436  return false;
1437  }
1438 }
double aTan2(double fY, double fX)
Definition: g3dmath.h:664
float elt[3][3]
Definition: Matrix3.h:41
double halfPi()
Definition: g3dmath.h:155

+ Here is the call graph for this function:

bool G3D::Matrix3::toEulerAnglesYXZ ( float &  rfYAngle,
float &  rfPAngle,
float &  rfRAngle 
) const
1442  {
1443  // rot = cy*cz+sx*sy*sz cz*sx*sy-cy*sz cx*sy
1444  // cx*sz cx*cz -sx
1445  // -cz*sy+cy*sx*sz cy*cz*sx+sy*sz cx*cy
1446 
1447  if ( elt[1][2] < 1.0 ) {
1448  if ( elt[1][2] > -1.0 ) {
1449  rfYAngle = (float) G3D::aTan2(elt[0][2], elt[2][2]);
1450  rfXAngle = (float) asin( -elt[1][2]);
1451  rfZAngle = (float) G3D::aTan2(elt[1][0], elt[1][1]);
1452  return true;
1453  } else {
1454  // WARNING. Not unique. YA - ZA = atan2(r01,r00)
1455  rfYAngle = (float)G3D::aTan2(elt[0][1], elt[0][0]);
1456  rfXAngle = (float)halfPi();
1457  rfZAngle = 0.0f;
1458  return false;
1459  }
1460  } else {
1461  // WARNING. Not unique. YA + ZA = atan2(-r01,r00)
1462  rfYAngle = (float)G3D::aTan2( -elt[0][1], elt[0][0]);
1463  rfXAngle = -(float)halfPi();
1464  rfZAngle = 0.0f;
1465  return false;
1466  }
1467 }
double aTan2(double fY, double fX)
Definition: g3dmath.h:664
float elt[3][3]
Definition: Matrix3.h:41
double halfPi()
Definition: g3dmath.h:155

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool G3D::Matrix3::toEulerAnglesYZX ( float &  rfYAngle,
float &  rfPAngle,
float &  rfRAngle 
) const
1471  {
1472  // rot = cy*cz sx*sy-cx*cy*sz cx*sy+cy*sx*sz
1473  // sz cx*cz -cz*sx
1474  // -cz*sy cy*sx+cx*sy*sz cx*cy-sx*sy*sz
1475 
1476  if ( elt[1][0] < 1.0 ) {
1477  if ( elt[1][0] > -1.0 ) {
1478  rfYAngle = (float) G3D::aTan2( -elt[2][0], elt[0][0]);
1479  rfZAngle = (float) asin(elt[1][0]);
1480  rfXAngle = (float) G3D::aTan2( -elt[1][2], elt[1][1]);
1481  return true;
1482  } else {
1483  // WARNING. Not unique. YA - XA = -atan2(r21,r22);
1484  rfYAngle = -(float)G3D::aTan2(elt[2][1], elt[2][2]);
1485  rfZAngle = -(float)halfPi();
1486  rfXAngle = 0.0f;
1487  return false;
1488  }
1489  } else {
1490  // WARNING. Not unique. YA + XA = atan2(r21,r22)
1491  rfYAngle = (float)G3D::aTan2(elt[2][1], elt[2][2]);
1492  rfZAngle = (float)halfPi();
1493  rfXAngle = 0.0f;
1494  return false;
1495  }
1496 }
double aTan2(double fY, double fX)
Definition: g3dmath.h:664
float elt[3][3]
Definition: Matrix3.h:41
double halfPi()
Definition: g3dmath.h:155

+ Here is the call graph for this function:

bool G3D::Matrix3::toEulerAnglesZXY ( float &  rfYAngle,
float &  rfPAngle,
float &  rfRAngle 
) const
1500  {
1501  // rot = cy*cz-sx*sy*sz -cx*sz cz*sy+cy*sx*sz
1502  // cz*sx*sy+cy*sz cx*cz -cy*cz*sx+sy*sz
1503  // -cx*sy sx cx*cy
1504 
1505  if ( elt[2][1] < 1.0 ) {
1506  if ( elt[2][1] > -1.0 ) {
1507  rfZAngle = (float) G3D::aTan2( -elt[0][1], elt[1][1]);
1508  rfXAngle = (float) asin(elt[2][1]);
1509  rfYAngle = (float) G3D::aTan2( -elt[2][0], elt[2][2]);
1510  return true;
1511  } else {
1512  // WARNING. Not unique. ZA - YA = -atan(r02,r00)
1513  rfZAngle = -(float)G3D::aTan2(elt[0][2], elt[0][0]);
1514  rfXAngle = -(float)halfPi();
1515  rfYAngle = 0.0f;
1516  return false;
1517  }
1518  } else {
1519  // WARNING. Not unique. ZA + YA = atan2(r02,r00)
1520  rfZAngle = (float)G3D::aTan2(elt[0][2], elt[0][0]);
1521  rfXAngle = (float)halfPi();
1522  rfYAngle = 0.0f;
1523  return false;
1524  }
1525 }
double aTan2(double fY, double fX)
Definition: g3dmath.h:664
float elt[3][3]
Definition: Matrix3.h:41
double halfPi()
Definition: g3dmath.h:155

+ Here is the call graph for this function:

bool G3D::Matrix3::toEulerAnglesZYX ( float &  rfYAngle,
float &  rfPAngle,
float &  rfRAngle 
) const
1529  {
1530  // rot = cy*cz cz*sx*sy-cx*sz cx*cz*sy+sx*sz
1531  // cy*sz cx*cz+sx*sy*sz -cz*sx+cx*sy*sz
1532  // -sy cy*sx cx*cy
1533 
1534  if ( elt[2][0] < 1.0 ) {
1535  if ( elt[2][0] > -1.0 ) {
1536  rfZAngle = atan2f(elt[1][0], elt[0][0]);
1537  rfYAngle = asinf(-elt[2][0]);
1538  rfXAngle = atan2f(elt[2][1], elt[2][2]);
1539  return true;
1540  } else {
1541  // WARNING. Not unique. ZA - XA = -atan2(r01,r02)
1542  rfZAngle = -(float)G3D::aTan2(elt[0][1], elt[0][2]);
1543  rfYAngle = (float)halfPi();
1544  rfXAngle = 0.0f;
1545  return false;
1546  }
1547  } else {
1548  // WARNING. Not unique. ZA + XA = atan2(-r01,-r02)
1549  rfZAngle = (float)G3D::aTan2( -elt[0][1], -elt[0][2]);
1550  rfYAngle = -(float)halfPi();
1551  rfXAngle = 0.0f;
1552  return false;
1553  }
1554 }
double aTan2(double fY, double fX)
Definition: g3dmath.h:664
float elt[3][3]
Definition: Matrix3.h:41
double halfPi()
Definition: g3dmath.h:155

+ Here is the call graph for this function:

std::string G3D::Matrix3::toString ( ) const
1932  {
1933  return G3D::format("[%g, %g, %g; %g, %g, %g; %g, %g, %g]",
1934  elt[0][0], elt[0][1], elt[0][2],
1935  elt[1][0], elt[1][1], elt[1][2],
1936  elt[2][0], elt[2][1], elt[2][2]);
1937 }
std::string __cdecl format(const char *fmt...) G3D_CHECK_PRINTF_ARGS
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

static void G3D::Matrix3::transpose ( const Matrix3 A,
Matrix3 out 
)
inlinestatic

Optimized implementation of out = A.transpose(). It is safe (but slow) to call with A and out possibly pointer equal to one another.

Note that A.transpose() * v can be computed more efficiently as v * A.

233  {
234  if (&A == &out) {
235  out = A.transpose();
236  } else {
237  _transpose(A, out);
238  }
239  }
static void _transpose(const Matrix3 &A, Matrix3 &out)
Definition: Matrix3.cpp:1919

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Matrix3 G3D::Matrix3::transpose ( ) const
391  {
392  Matrix3 kTranspose;
393 
394  for (int iRow = 0; iRow < 3; ++iRow) {
395  for (int iCol = 0; iCol < 3; ++iCol) {
396  kTranspose[iRow][iCol] = elt[iCol][iRow];
397  }
398  }
399 
400  return kTranspose;
401 }
float elt[3][3]
Definition: Matrix3.h:41
Matrix3()
Definition: Matrix3.h:83
void G3D::Matrix3::tridiagonal ( float  afDiag[3],
float  afSubDiag[3] 
)
protected
1684  {
1685  // Householder reduction T = Q^t M Q
1686  // Input:
1687  // mat, symmetric 3x3 matrix M
1688  // Output:
1689  // mat, orthogonal matrix Q
1690  // diag, diagonal entries of T
1691  // subd, subdiagonal entries of T (T is symmetric)
1692 
1693  float fA = elt[0][0];
1694  float fB = elt[0][1];
1695  float fC = elt[0][2];
1696  float fD = elt[1][1];
1697  float fE = elt[1][2];
1698  float fF = elt[2][2];
1699 
1700  afDiag[0] = fA;
1701  afSubDiag[2] = 0.0;
1702 
1703  if ( G3D::abs(fC) >= EPSILON ) {
1704  float fLength = sqrt(fB * fB + fC * fC);
1705  float fInvLength = 1.0f / fLength;
1706  fB *= fInvLength;
1707  fC *= fInvLength;
1708  float fQ = 2.0f * fB * fE + fC * (fF - fD);
1709  afDiag[1] = fD + fC * fQ;
1710  afDiag[2] = fF - fC * fQ;
1711  afSubDiag[0] = fLength;
1712  afSubDiag[1] = fE - fB * fQ;
1713  elt[0][0] = 1.0;
1714  elt[0][1] = 0.0;
1715  elt[0][2] = 0.0;
1716  elt[1][0] = 0.0;
1717  elt[1][1] = fB;
1718  elt[1][2] = fC;
1719  elt[2][0] = 0.0;
1720  elt[2][1] = fC;
1721  elt[2][2] = -fB;
1722  } else {
1723  afDiag[1] = fD;
1724  afDiag[2] = fF;
1725  afSubDiag[0] = fB;
1726  afSubDiag[1] = fE;
1727  elt[0][0] = 1.0;
1728  elt[0][1] = 0.0;
1729  elt[0][2] = 0.0;
1730  elt[1][0] = 0.0;
1731  elt[1][1] = 1.0;
1732  elt[1][2] = 0.0;
1733  elt[2][0] = 0.0;
1734  elt[2][1] = 0.0;
1735  elt[2][2] = 1.0;
1736  }
1737 }
double abs(double fValue)
Definition: g3dmath.h:617
static const float EPSILON
Definition: Matrix3.h:341
float elt[3][3]
Definition: Matrix3.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

const Matrix3 & G3D::Matrix3::zero ( )
static
65  {
66  static Matrix3 m(0, 0, 0, 0, 0, 0, 0, 0, 0);
67  return m;
68 }
Matrix3()
Definition: Matrix3.h:83

+ Here is the caller graph for this function:

Friends And Related Function Documentation

Vector3 operator* ( const Vector3 rkVector,
const Matrix3 rkMatrix 
)
friend

vector * matrix [1x3 * 3x3 = 1x3]

v * M == M.transpose() * v

386  {
387  Vector3 kProd;
388 
389  for (int r = 0; r < 3; ++r) {
390  kProd[r] =
391  rkPoint[0] * rkMatrix.elt[0][r] +
392  rkPoint[1] * rkMatrix.elt[1][r] +
393  rkPoint[2] * rkMatrix.elt[2][r];
394  }
395 
396  return kProd;
397 }
Matrix3 operator* ( double  fScalar,
const Matrix3 rkMatrix 
)
friend

scalar * matrix

370  {
371  Matrix3 kProd;
372 
373  for (int iRow = 0; iRow < 3; ++iRow) {
374  for (int iCol = 0; iCol < 3; ++iCol) {
375  kProd[iRow][iCol] = (float)fScalar * rkMatrix.elt[iRow][iCol];
376  }
377  }
378 
379  return kProd;
380 }
Matrix3()
Definition: Matrix3.h:83
Matrix3 operator* ( float  fScalar,
const Matrix3 rkMatrix 
)
friend
382  {
383  return (double)fScalar * rkMatrix;
384 }
Matrix3 operator* ( int  fScalar,
const Matrix3 rkMatrix 
)
friend
387  {
388  return (double)fScalar * rkMatrix;
389 }

Member Data Documentation

float G3D::Matrix3::elt[3][3]
private
const float G3D::Matrix3::EPSILON = 1e-06f
static
const float G3D::Matrix3::ms_fSvdEpsilon = 1e-04f
staticprotected
const int G3D::Matrix3::ms_iSvdMaxIterations = 32
staticprotected

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