#include <math.h>
#include <assert.h>
#include <maya/MIOStream.h>
#define COMPILE_OUTSIDE_MAYA
#include <AwMath.h>
#include <AwPoint.h>
#include <AwVector.h>
#include <AwMatrix.h>
#define DET2X2(a,b,c,d) (a*d-b*c)
#define DET3X3(a1,a2,a3,b1,b2,b3,c1,c2,c3) \
( a1 * DET2X2( b2, b3, c2, c3 ) \
- b1 * DET2X2( a2, a3, c2, c3 ) \
+ c1 * DET2X2( a2, a3, b2, b3 ) )
const AwMatrix AwMatrix::identity;
AwMatrix &AwMatrix::setToIdentity()
{
matrix[0][0] = 1.0;
matrix[0][1] = 0.0;
matrix[0][2] = 0.0;
matrix[0][3] = 0.0;
matrix[1][0] = 0.0;
matrix[1][1] = 1.0;
matrix[1][2] = 0.0;
matrix[1][3] = 0.0;
matrix[2][0] = 0.0;
matrix[2][1] = 0.0;
matrix[2][2] = 1.0;
matrix[2][3] = 0.0;
matrix[3][0] = 0.0;
matrix[3][1] = 0.0;
matrix[3][2] = 0.0;
matrix[3][3] = 1.0;
return *this;
}
AwMatrix AwMatrix::operator*(const AwMatrix &right) const
{
AwMatrix result;
double *a = (double *) result.matrix;
double *b = (double *) this->matrix;
double *c = (double *) right.matrix;
double i0, i1, i2, i3, i4, i5, i6, i7;
if (a == c) {
double c0, c4, c8, c12;
c0 = c[0]; c4 = c[4]; c8 = c[8]; c12 = c[12];
i0 = b[0] * c0; i1 = b[1] * c4; i2 = b[2] * c8; i3 = b[3] * c12;
i4 = b[4] * c0; i5 = b[5] * c4; i6 = b[6] * c8; i7 = b[7] * c12;
a[0] = i0 + i1 + i2 + i3;
a[4] = i4 + i5 + i6 + i7;
i0 = b[8] * c0; i1 = b[9] * c4; i2 = b[10] * c8; i3 = b[11] * c12;
i4 = b[12] * c0; i5 = b[13] * c4; i6 = b[14] * c8; i7 = b[15] * c12;
a[8] = i0 + i1 + i2 + i3;
a[12] = i4 + i5 + i6 + i7;
c0 = c[1]; c4 = c[5]; c8 = c[9]; c12 = c[13];
i0 = b[0] * c0; i1 = b[1] * c4; i2 = b[2] * c8; i3 = b[3] * c12;
i4 = b[4] * c0; i5 = b[5] * c4; i6 = b[6] * c8; i7 = b[7] * c12;
a[1] = i0 + i1 + i2 + i3;
a[5] = i4 + i5 + i6 + i7;
i0 = b[8] * c0; i1 = b[9] * c4; i2 = b[10] * c8; i3 = b[11] * c12;
i4 = b[12] * c0; i5 = b[13] * c4; i6 = b[14] * c8; i7 = b[15] * c12;
a[9] = i0 + i1 + i2 + i3;
a[13] = i4 + i5 + i6 + i7;
c0 = c[2]; c4 = c[6]; c8 = c[10]; c12 = c[14];
i0 = b[0] * c0; i1 = b[1] * c4; i2 = b[2] * c8; i3 = b[3] * c12;
i4 = b[4] * c0; i5 = b[5] * c4; i6 = b[6] * c8; i7 = b[7] * c12;
a[2] = i0 + i1 + i2 + i3;
a[6] = i4 + i5 + i6 + i7;
i0 = b[8] * c0; i1 = b[9] * c4; i2 = b[10] * c8; i3 = b[11] * c12;
i4 = b[12] * c0; i5 = b[13] * c4; i6 = b[14] * c8; i7 = b[15] * c12;
a[10] = i0 + i1 + i2 + i3;
a[14] = i4 + i5 + i6 + i7;
c0 = c[3]; c4 = c[7]; c8 = c[11]; c12 = c[15];
i0 = b[0] * c0; i1 = b[1] * c4; i2 = b[2] * c8; i3 = b[3] * c12;
i4 = b[4] * c0; i5 = b[5] * c4; i6 = b[6] * c8; i7 = b[7] * c12;
a[3] = i0 + i1 + i2 + i3;
a[7] = i4 + i5 + i6 + i7;
i0 = b[8] * c0; i1 = b[9] * c4; i2 = b[10] * c8; i3 = b[11] * c12;
i4 = b[12] * c0; i5 = b[13] * c4; i6 = b[14] * c8; i7 = b[15] * c12;
a[11] = i0 + i1 + i2 + i3;
a[15] = i4 + i5 + i6 + i7;
} else {
double b0, b1, b2, b3;
b0 = b[0]; b1 = b[1]; b2 = b[2]; b3 = b[3];
i0 = b0 * c[0]; i1 = b1 * c[4]; i2 = b2 * c[8]; i3 = b3 * c[12];
i4 = b0 * c[1]; i5 = b1 * c[5]; i6 = b2 * c[9]; i7 = b3 * c[13];
a[0] = i0 + i1 + i2 + i3;
a[1] = i4 + i5 + i6 + i7;
i0 = b0 * c[2]; i1 = b1 * c[6]; i2 = b2 * c[10]; i3 = b3 * c[14];
i4 = b0 * c[3]; i5 = b1 * c[7]; i6 = b2 * c[11]; i7 = b3 * c[15];
a[2] = i0 + i1 + i2 + i3;
a[3] = i4 + i5 + i6 + i7;
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
i0 = b0 * c[0]; i1 = b1 * c[4]; i2 = b2 * c[8]; i3 = b3 * c[12];
i4 = b0 * c[1]; i5 = b1 * c[5]; i6 = b2 * c[9]; i7 = b3 * c[13];
a[4] = i0 + i1 + i2 + i3;
a[5] = i4 + i5 + i6 + i7;
i0 = b0 * c[2]; i1 = b1 * c[6]; i2 = b2 * c[10]; i3 = b3 * c[14];
i4 = b0 * c[3]; i5 = b1 * c[7]; i6 = b2 * c[11]; i7 = b3 * c[15];
a[6] = i0 + i1 + i2 + i3;
a[7] = i4 + i5 + i6 + i7;
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
i0 = b0 * c[0]; i1 = b1 * c[4]; i2 = b2 * c[8]; i3 = b3 * c[12];
i4 = b0 * c[1]; i5 = b1 * c[5]; i6 = b2 * c[9]; i7 = b3 * c[13];
a[8] = i0 + i1 + i2 + i3;
a[9] = i4 + i5 + i6 + i7;
i0 = b0 * c[2]; i1 = b1 * c[6]; i2 = b2 * c[10]; i3 = b3 * c[14];
i4 = b0 * c[3]; i5 = b1 * c[7]; i6 = b2 * c[11]; i7 = b3 * c[15];
a[10] = i0 + i1 + i2 + i3;
a[11] = i4 + i5 + i6 + i7;
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
i0 = b0 * c[0]; i1 = b1 * c[4]; i2 = b2 * c[8]; i3 = b3 * c[12];
i4 = b0 * c[1]; i5 = b1 * c[5]; i6 = b2 * c[9]; i7 = b3 * c[13];
a[12] = i0 + i1 + i2 + i3;
a[13] = i4 + i5 + i6 + i7;
i0 = b0 * c[2]; i1 = b1 * c[6]; i2 = b2 * c[10]; i3 = b3 * c[14];
i4 = b0 * c[3]; i5 = b1 * c[7]; i6 = b2 * c[11]; i7 = b3 * c[15];
a[14] = i0 + i1 + i2 + i3;
a[15] = i4 + i5 + i6 + i7;
}
return result;
}
AwMatrix &AwMatrix::invertIt()
{
AwMatrix inv;
int i, j, k;
double factor, divisor, temp;
for (i = 0; i < 3; i++) {
int bigOne = i;
for (j = i; j < 4; j++){
if (matrix[j][i] * matrix[j][i] >
matrix[bigOne][i] * matrix[bigOne][i]) {
bigOne = j;
}
}
if (bigOne != i) {
for (j = 0; j < 4; j++) {
temp = matrix[bigOne][j];
matrix[bigOne][j] = matrix[i][j];
matrix[i][j] = temp;
temp = inv.matrix[bigOne][j];
inv.matrix[bigOne][j] = inv.matrix[i][j];
inv.matrix[i][j] = temp;
}
}
if (matrix[i][i] > 1.0e-15 || matrix[i][i] < -1.0e-15) {
for (j = i + 1; j < 4; j++) {
factor = matrix[j][i] / matrix[i][i];
for (k = 0; k < 4; k++) {
matrix[j][k] -= matrix[i][k] * factor;
inv.matrix[j][k] -= inv.matrix[i][k] * factor;
}
matrix[j][i] = 0.0;
}
}
}
for (i = 0; i < 4; i++) {
divisor = matrix[i][i];
if (divisor > 1.0e-15 || divisor < -1.0e-15) {
for (j = 0; j < 4; j++) {
matrix[i][j] = matrix[i][j] / divisor;
inv.matrix[i][j] = inv.matrix[i][j] / divisor;
}
matrix[i][i] = 1.0;
}
}
for (i = 0; i < 3; i++) {
for (j = i + 1; j < 4; j++) {
factor = matrix[i][j];
for (k = 0; k < 4; k++) {
matrix[i][k] -= matrix[j][k] * factor;
inv.matrix[i][k] -= inv.matrix[j][k] * factor;
}
matrix[i][j] = 0.0;
}
}
*this = inv;
return *this;
}
AwMatrix &AwMatrix::transposeIt()
{
int i, j;
double temp;
for (i = 0; i < 3; i++){
for (j = i + 1; j < 4; j++) {
temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
return *this;
}
bool AwMatrix::isEquivalent(const AwMatrix &otherM, double tolerance) const
{
assert(tolerance >= 0.0);
return (
fabs(matrix[0][0] - otherM.matrix[0][0]) <= tolerance
&& fabs(matrix[0][1] - otherM.matrix[0][1]) <= tolerance
&& fabs(matrix[0][2] - otherM.matrix[0][2]) <= tolerance
&& fabs(matrix[0][3] - otherM.matrix[0][3]) <= tolerance
&& fabs(matrix[1][0] - otherM.matrix[1][0]) <= tolerance
&& fabs(matrix[1][1] - otherM.matrix[1][1]) <= tolerance
&& fabs(matrix[1][2] - otherM.matrix[1][2]) <= tolerance
&& fabs(matrix[1][3] - otherM.matrix[1][3]) <= tolerance
&& fabs(matrix[2][0] - otherM.matrix[2][0]) <= tolerance
&& fabs(matrix[2][1] - otherM.matrix[2][1]) <= tolerance
&& fabs(matrix[2][2] - otherM.matrix[2][2]) <= tolerance
&& fabs(matrix[2][3] - otherM.matrix[2][3]) <= tolerance
&& fabs(matrix[3][0] - otherM.matrix[3][0]) <= tolerance
&& fabs(matrix[3][1] - otherM.matrix[3][1]) <= tolerance
&& fabs(matrix[3][2] - otherM.matrix[3][2]) <= tolerance
&& fabs(matrix[3][3] - otherM.matrix[3][3]) <= tolerance );
}
AwMatrix AwMatrix::operator*(double mult) const
{
AwMatrix temp(*this);
temp[0][0] *= mult; temp[0][1] *= mult;
temp[0][2] *= mult; temp[0][3] *= mult;
temp[1][0] *= mult; temp[1][1] *= mult;
temp[1][2] *= mult; temp[1][3] *= mult;
temp[2][0] *= mult; temp[2][1] *= mult;
temp[2][2] *= mult; temp[2][3] *= mult;
temp[3][0] *= mult; temp[3][1] *= mult;
temp[3][2] *= mult; temp[3][3] *= mult;
return temp;
}
bool AwMatrix::operator==(const AwMatrix &otherM) const
{
return (
matrix[0][0] == otherM.matrix[0][0]
&& matrix[0][1] == otherM.matrix[0][1]
&& matrix[0][2] == otherM.matrix[0][2]
&& matrix[0][3] == otherM.matrix[0][3]
&& matrix[1][0] == otherM.matrix[1][0]
&& matrix[1][1] == otherM.matrix[1][1]
&& matrix[1][2] == otherM.matrix[1][2]
&& matrix[1][3] == otherM.matrix[1][3]
&& matrix[2][0] == otherM.matrix[2][0]
&& matrix[2][1] == otherM.matrix[2][1]
&& matrix[2][2] == otherM.matrix[2][2]
&& matrix[2][3] == otherM.matrix[2][3]
&& matrix[3][0] == otherM.matrix[3][0]
&& matrix[3][1] == otherM.matrix[3][1]
&& matrix[3][2] == otherM.matrix[3][2]
&& matrix[3][3] == otherM.matrix[3][3] );
}
double AwMatrix::det3x3() const
{
return (matrix[0][0] * (matrix[1][1] * matrix[2][2] -
matrix[2][1] * matrix[1][2]) -
matrix[0][1] * (matrix[1][0] * matrix[2][2] -
matrix[2][0] * matrix[1][2]) +
matrix[0][2] * (matrix[1][0] * matrix[2][1] -
matrix[2][0] * matrix[1][1]));
}
double AwMatrix::det4x4() const
{
double a1, a2, a3, a4;
double b1, b2, b3, b4;
double c1, c2, c3, c4;
double d1, d2, d3, d4;
a1 = matrix[0][0]; b1 = matrix[0][1]; c1 = matrix[0][2]; d1 = matrix[0][3];
a2 = matrix[1][0]; b2 = matrix[1][1]; c2 = matrix[1][2]; d2 = matrix[1][3];
a3 = matrix[2][0]; b3 = matrix[2][1]; c3 = matrix[2][2]; d3 = matrix[2][3];
a4 = matrix[3][0]; b4 = matrix[3][1]; c4 = matrix[3][2]; d4 = matrix[3][3];
return (
a1 * DET3X3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
b1 * DET3X3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
c1 * DET3X3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
d1 * DET3X3(a2, a3, a4, b2, b3, b4, c2, c3, c4)
);
}
bool AwMatrix::isOrthogonal() const
{
#define rowdot(i,j) (matrix[i][0]*matrix[j][0] + \
matrix[i][1]*matrix[j][1] + \
matrix[i][2]*matrix[j][2])
#define rownorm(i) (rowdot(i,i))
double norm0 = rownorm(0);
return (
::equivalent(rownorm(1), norm0) &&
::equivalent(rownorm(2), norm0) &&
::equivalent(rowdot(0,1), 0.0) &&
::equivalent(rowdot(1,2), 0.0) &&
::equivalent(rowdot(0,2), 0.0)
);
#undef rownorm
#undef rowdot
}
ostream &operator<<(ostream &os, const AwMatrix &m)
{
os << "[";
for (int i = 0; i < 4; ++i) {
if (i) os << ", ";
os << "[";
for (int j = 0; j < 4; ++j) {
if (j) os << ", ";
os << m[i][j];
}
os << "]";
}
os << "]";
return os;
}