/***************************************************************************************
***** CLASS MATRIX4D IMPLEMENTATION *****
****************************************************************************************
** Author: Peter Stuart
** Email: chester@selway.umt.edu
** Date: 3/7/98
** Description: This class implements a 4x4 matrix and all of the operation you could
** ever want with one (well, maybe not ALL). Operations include: matrix cross product,
** minor, determinant, cofactor, transpose, inverse matrix, and loads of operators
** for multiplying matrices by other base types. Also part of the class are methods
** for creating transformation matrices, such as translation, rotation, scaling, and
** 3D shearing.
**
** NOTE: The matrices, vectors, and points use homogeneous coordinates
**
***************************************************************************************/
#include "Matrix4D.hpp"
/* Constructors ************
** Default values for private variables:
** matrix[i][j] = 0.0
*/
Matrix4D::Matrix4D()
{
matrix[0][0] = 0.0;
matrix[0][1] = 0.0;
matrix[0][2] = 0.0;
matrix[0][3] = 0.0;
matrix[1][0] = 0.0;
matrix[1][1] = 0.0;
matrix[1][2] = 0.0;
matrix[1][3] = 0.0;
matrix[2][0] = 0.0;
matrix[2][1] = 0.0;
matrix[2][2] = 0.0;
matrix[2][3] = 0.0;
matrix[3][0] = 0.0;
matrix[3][1] = 0.0;
matrix[3][2] = 0.0;
matrix[3][3] = 0.0;
}
Matrix4D::Matrix4D(const double mat[4][4])
{
matrix[0][0] = mat[0][0];
matrix[0][1] = mat[0][1];
matrix[0][2] = mat[0][2];
matrix[0][3] = mat[0][3];
matrix[1][0] = mat[1][0];
matrix[1][1] = mat[1][1];
matrix[1][2] = mat[1][2];
matrix[1][3] = mat[1][3];
matrix[2][0] = mat[2][0];
matrix[2][1] = mat[2][1];
matrix[2][2] = mat[2][2];
matrix[2][3] = mat[2][3];
matrix[3][0] = mat[3][0];
matrix[3][1] = mat[3][1];
matrix[3][2] = mat[3][2];
matrix[3][3] = mat[3][3];
}
// Destructor
Matrix4D::~Matrix4D (void)
{
;
}
// Copy Constructor
Matrix4D::Matrix4D(const Matrix4D& mat)
{
matrix[0][0] = mat.matrix[0][0];
matrix[0][1] = mat.matrix[0][1];
matrix[0][2] = mat.matrix[0][2];
matrix[0][3] = mat.matrix[0][3];
matrix[1][0] = mat.matrix[1][0];
matrix[1][1] = mat.matrix[1][1];
matrix[1][2] = mat.matrix[1][2];
matrix[1][3] = mat.matrix[1][3];
matrix[2][0] = mat.matrix[2][0];
matrix[2][1] = mat.matrix[2][1];
matrix[2][2] = mat.matrix[2][2];
matrix[2][3] = mat.matrix[2][3];
matrix[3][0] = mat.matrix[3][0];
matrix[3][1] = mat.matrix[3][1];
matrix[3][2] = mat.matrix[3][2];
matrix[3][3] = mat.matrix[3][3];
}
// BASIC MATRIX OPERATIONS //////////////////////////////////////
// Matrix Cross product
Matrix4D Matrix4D::cross(const Matrix4D& mat) const
{
Matrix4D temp; // returning matrix
temp.matrix[0][0] = (matrix[0][0] * mat.matrix[0][0])
+ (matrix[0][1] * mat.matrix[1][0])
+ (matrix[0][2] * mat.matrix[2][0])
+ (matrix[0][3] * mat.matrix[3][0]);
temp.matrix[0][1] = (matrix[0][0] * mat.matrix[0][1])
+ (matrix[0][1] * mat.matrix[1][1])
+ (matrix[0][2] * mat.matrix[2][1])
+ (matrix[0][3] * mat.matrix[3][1]);
temp.matrix[0][2] = (matrix[0][0] * mat.matrix[0][2])
+ (matrix[0][1] * mat.matrix[1][2])
+ (matrix[0][2] * mat.matrix[2][2])
+ (matrix[0][3] * mat.matrix[3][2]);
temp.matrix[0][3] = (matrix[0][0] * mat.matrix[0][3])
+ (matrix[0][1] * mat.matrix[1][3])
+ (matrix[0][2] * mat.matrix[2][3])
+ (matrix[0][3] * mat.matrix[3][3]);
temp.matrix[1][0] = (matrix[1][0] * mat.matrix[0][0])
+ (matrix[1][1] * mat.matrix[1][0])
+ (matrix[1][2] * mat.matrix[2][0])
+ (matrix[1][3] * mat.matrix[3][0]);
temp.matrix[1][1] = (matrix[1][0] * mat.matrix[0][1])
+ (matrix[1][1] * mat.matrix[1][1])
+ (matrix[1][2] * mat.matrix[2][1])
+ (matrix[1][3] * mat.matrix[3][1]);
temp.matrix[1][2] = (matrix[1][0] * mat.matrix[0][2])
+ (matrix[1][1] * mat.matrix[1][2])
+ (matrix[1][2] * mat.matrix[2][2])
+ (matrix[1][3] * mat.matrix[3][2]);
temp.matrix[1][3] = (matrix[1][0] * mat.matrix[0][3])
+ (matrix[1][1] * mat.matrix[1][3])
+ (matrix[1][2] * mat.matrix[2][3])
+ (matrix[1][3] * mat.matrix[3][3]);
temp.matrix[2][0] = (matrix[2][0] * mat.matrix[0][0])
+ (matrix[2][1] * mat.matrix[1][0])
+ (matrix[2][2] * mat.matrix[2][0])
+ (matrix[2][3] * mat.matrix[3][0]);
temp.matrix[2][1] = (matrix[2][0] * mat.matrix[0][1])
+ (matrix[2][1] * mat.matrix[1][1])
+ (matrix[2][2] * mat.matrix[2][1])
+ (matrix[2][3] * mat.matrix[3][1]);
temp.matrix[2][2] = (matrix[2][0] * mat.matrix[0][2])
+ (matrix[2][1] * mat.matrix[1][2])
+ (matrix[2][2] * mat.matrix[2][2])
+ (matrix[2][3] * mat.matrix[3][2]);
temp.matrix[2][3] = (matrix[2][0] * mat.matrix[0][3])
+ (matrix[2][1] * mat.matrix[1][3])
+ (matrix[2][2] * mat.matrix[2][3])
+ (matrix[2][3] * mat.matrix[3][3]);
temp.matrix[3][0] = (matrix[3][0] * mat.matrix[0][0])
+ (matrix[3][1] * mat.matrix[1][0])
+ (matrix[3][2] * mat.matrix[2][0])
+ (matrix[3][3] * mat.matrix[3][0]);
temp.matrix[3][1] = (matrix[3][0] * mat.matrix[0][1])
+ (matrix[3][1] * mat.matrix[1][1])
+ (matrix[3][2] * mat.matrix[2][1])
+ (matrix[3][3] * mat.matrix[3][1]);
temp.matrix[3][2] = (matrix[3][0] * mat.matrix[0][2])
+ (matrix[3][1] * mat.matrix[1][2])
+ (matrix[3][2] * mat.matrix[2][2])
+ (matrix[3][3] * mat.matrix[3][2]);
temp.matrix[3][3] = (matrix[3][0] * mat.matrix[0][3])
+ (matrix[3][1] * mat.matrix[1][3])
+ (matrix[3][2] * mat.matrix[2][3])
+ (matrix[3][3] * mat.matrix[3][3]);
return temp;
}
// Minor of row, col
double Matrix4D::minor(const int row, const int col) const
{
double mat3x3[3][3]; // 3x3 matrix of elements in the determinant
int rowPos=0, colPos=0; // present row and column
int i, j; // index variables
// create 3x3 matrix
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if ((i!=row) && (j!=col))
{
mat3x3[rowPos][colPos] = matrix[i][j];
colPos++;
if (colPos > 2)
{
colPos = 0;
rowPos++;
}
}
}
}
return det3x3(mat3x3);
}
// Determinant of 4x4 matrix
double Matrix4D::determinant()
{
double val = 0.0; // returning double
// use Laplace development to find determinant
val += matrix[0][0] * minor(0, 0);
val -= matrix[0][1] * minor(0, 1);
val += matrix[0][2] * minor(0, 2);
val -= matrix[0][3] * minor(0, 3);
return val;
}
// Cofactor matrix - C[i][j] = signed minor of matrix[i][j]
Matrix4D Matrix4D::cofactor()
{
Matrix4D temp; // returning matrix
temp.matrix[0][0] = minor(0, 0);
temp.matrix[0][1] = -minor(0, 1);
temp.matrix[0][2] = minor(0, 2);
temp.matrix[0][3] = -minor(0, 3);
temp.matrix[1][0] = -minor(1, 0);
temp.matrix[1][1] = minor(1, 1);
temp.matrix[1][2] = -minor(1, 2);
temp.matrix[1][3] = minor(1, 3);
temp.matrix[2][0] = minor(2, 0);
temp.matrix[2][1] = -minor(2, 1);
temp.matrix[2][2] = minor(2, 2);
temp.matrix[2][3] = -minor(2, 3);
temp.matrix[3][0] = -minor(3, 0);
temp.matrix[3][1] = minor(3, 1);
temp.matrix[3][2] = -minor(3, 2);
temp.matrix[3][3] = minor(3, 3);
return temp;
}
// Transpose of 4x4 matrix - T[i][j] = matrix[j][i]
Matrix4D Matrix4D::transpose()
{
Matrix4D temp; // returning matrix
temp.matrix[0][0] = matrix[0][0];
temp.matrix[0][1] = matrix[1][0];
temp.matrix[0][2] = matrix[2][0];
temp.matrix[0][3] = matrix[3][0];
temp.matrix[1][0] = matrix[0][1];
temp.matrix[1][1] = matrix[1][1];
temp.matrix[1][2] = matrix[2][1];
temp.matrix[1][3] = matrix[3][1];
temp.matrix[2][0] = matrix[0][2];
temp.matrix[2][1] = matrix[1][2];
temp.matrix[2][2] = matrix[2][2];
temp.matrix[2][3] = matrix[3][2];
temp.matrix[3][0] = matrix[0][3];
temp.matrix[3][1] = matrix[1][3];
temp.matrix[3][2] = matrix[2][3];
temp.matrix[3][3] = matrix[3][3];
return temp;
}
// Inverse matrix - using cofactors
Matrix4D Matrix4D::inverse()
{
return cofactor().transpose() / determinant();
}
// MATRIX TRANSFORMATIONS /////////////////////////////////////////////////
// Translation matrix
// |1 0 0 0|
// |0 1 0 0|
// |0 0 1 0|
// |x y z 1|
Matrix4D translate (const double x, const double y, const double z)
{
Matrix4D temp; // returning matrix
temp = temp.identity();
temp.matrix[3][0] = x;
temp.matrix[3][1] = y;
temp.matrix[3][2] = z;
return temp;
}
// Rotation matrix
// z-axis :
// | cosz sinz 0 0 |
// | -sinz cosz 0 0 |
// | 0 0 1 0 |
// | 0 0 0 1 |
// x-axis:
// | 1 0 0 0 |
// | 0 cosx sinx 0 |
// | 0 -sinx cosx 0 |
// | 0 0 0 1 |
// y-axis:
// | cosy 0 -siny 0 |
// | 0 1 0 0 |
// | siny 0 cosy 0 |
// | 0 0 0 1 |
// The other rotation matrices are just combinations of these three
Matrix4D rotate (const double x, const double y, const double z)
{
Matrix4D temp; // returning matrix
temp = temp.identity();
if (y == 0.0 && z == 0.0)
{
// rotation around x-axis
temp.matrix[1][1] = cos(x);
temp.matrix[1][2] = sin(x);
temp.matrix[2][1] = -sin(x);
temp.matrix[2][2] = cos(x);
}
else if (z == 0.0 && x == 0.0)
{
// rotation around y-axis
temp.matrix[0][0] = cos(y);
temp.matrix[2][0] = -sin(y);
temp.matrix[0][2] = sin(y);
temp.matrix[2][2] = cos(y);
}
else if (x == 0.0 && y == 0.0)
{
// rotation around z-axis
temp.matrix[0][0] = cos(z);
temp.matrix[1][0] = -sin(z);
temp.matrix[0][1] = sin(z);
temp.matrix[1][1] = cos(z);
}
else if (z == 0.0)
{
// rotation around x and y axes
temp.matrix[0][0] = cos(y);
temp.matrix[0][2] = -sin(y);
temp.matrix[1][0] = sin(x)*sin(y);
temp.matrix[1][1] = cos(x);
temp.matrix[1][2] = sin(x)*cos(y);
temp.matrix[2][0] = cos(x)*sin(y);
temp.matrix[2][1] = -sin(x);
temp.matrix[2][2] = cos(x)*cos(y);
}
else if (x == 0.0)
{
// rotation around y and z axes
temp.matrix[0][0] = cos(y)*cos(z);
temp.matrix[0][1] = cos(y)*sin(z);
temp.matrix[0][2] = -sin(y);
temp.matrix[1][0] = -sin(z);
temp.matrix[1][1] = cos(z);
temp.matrix[2][0] = sin(y)*cos(z);
temp.matrix[2][1] = sin(y)*sin(z);
temp.matrix[2][2] = cos(z);
}
else if (y == 0.0)
{
// rotation around x and z axes
temp.matrix[0][0] = cos(z);
temp.matrix[0][1] = sin(z);
temp.matrix[1][0] = -cos(x)*sin(z);
temp.matrix[1][1] = cos(x)*cos(z);
temp.matrix[1][2] = sin(x);
temp.matrix[2][0] = sin(x)*sin(z);
temp.matrix[2][1] = -sin(x)*cos(z);
temp.matrix[2][2] = cos(x);
}
else
{
// rotation around all axes
temp.matrix[0][0] = cos(y)*cos(z);
temp.matrix[0][1] = cos(y)*sin(z);
temp.matrix[0][2] = -sin(y);
temp.matrix[1][0] = -cos(x)*sin(z) + sin(x)*sin(y)*cos(z);
temp.matrix[1][1] = cos(x)*cos(z) + sin(x)*sin(y)*sin(z);
temp.matrix[1][2] = sin(x)*cos(y);
temp.matrix[2][0] = sin(x)*sin(z) + cos(x)*sin(y)*cos(z);
temp.matrix[2][1] = -sin(x)*cos(z) + cos(x)*sin(y)*sin(z);
temp.matrix[2][2] = cos(x)*cos(y);
}
return temp;
}
// Scaling matrix
// | x 0 0 0 |
// | 0 y 0 0 |
// | 0 0 z 0 |
// | 0 0 0 1 |
Matrix4D scale (const double x, const double y, const double z)
{
Matrix4D temp; // returning matrix
temp = temp.identity();
temp.matrix[0][0] = x;
temp.matrix[1][1] = y;
temp.matrix[2][2] = z;
return temp;
}
// Shear in the XY plane
// | 1 0 0 0 |
// | 0 1 0 0 |
// | x y 1 0 |
// | 0 0 0 1 |
Matrix4D shearXY(const double shx, const double shy)
{
Matrix4D temp; // returning matrix
temp = temp.identity();
temp.matrix[2][0] = shx;
temp.matrix[2][1] = shy;
return temp;
}
// Shear in the XZ plane
// | 1 0 0 0 |
// | x 1 y 0 |
// | 0 0 1 0 |
// | 0 0 0 1 |
Matrix4D shearXZ(const double shx, const double shz)
{
Matrix4D temp; // returning matrix
temp = temp.identity();
temp.matrix[1][0] = shx;
temp.matrix[1][2] = shz;
return temp;
}
// Shear in the YZ plane
// | 1 y z 0 |
// | 0 1 0 0 |
// | 0 0 1 0 |
// | 0 0 0 1 |
Matrix4D shearYZ(const double shy, const double shz)
{
Matrix4D temp; // returning matrix
temp = temp.identity();
temp.matrix[0][1] = shy;
temp.matrix[0][2] = shz;
return temp;
}
// ELEMENTARY OPERATORS
// Assignment operator
Matrix4D& Matrix4D::operator = (const Matrix4D& mat)
{
if (this == &mat)
return *this;
matrix[0][0] = mat.matrix[0][0];
matrix[0][1] = mat.matrix[0][1];
matrix[0][2] = mat.matrix[0][2];
matrix[0][3] = mat.matrix[0][3];
matrix[1][0] = mat.matrix[1][0];
matrix[1][1] = mat.matrix[1][1];
matrix[1][2] = mat.matrix[1][2];
matrix[1][3] = mat.matrix[1][3];
matrix[2][0] = mat.matrix[2][0];
matrix[2][1] = mat.matrix[2][1];
matrix[2][2] = mat.matrix[2][2];
matrix[2][3] = mat.matrix[2][3];
matrix[3][0] = mat.matrix[3][0];
matrix[3][1] = mat.matrix[3][1];
matrix[3][2] = mat.matrix[3][2];
matrix[3][3] = mat.matrix[3][3];
return (*this);
}
// add two matrices
Matrix4D operator + (const Matrix4D& mat1, const Matrix4D& mat2)
{
Matrix4D temp;
temp.matrix[0][0] = mat1.matrix[0][0] + mat2.matrix[0][0];
temp.matrix[0][1] = mat1.matrix[0][1] + mat2.matrix[0][1];
temp.matrix[0][2] = mat1.matrix[0][2] + mat2.matrix[0][2];
temp.matrix[0][3] = mat1.matrix[0][3] + mat2.matrix[0][3];
temp.matrix[1][0] = mat1.matrix[1][0] + mat2.matrix[1][0];
temp.matrix[1][1] = mat1.matrix[1][1] + mat2.matrix[1][1];
temp.matrix[1][2] = mat1.matrix[1][2] + mat2.matrix[1][2];
temp.matrix[1][3] = mat1.matrix[1][3] + mat2.matrix[1][3];
temp.matrix[2][0] = mat1.matrix[2][0] + mat2.matrix[2][0];
temp.matrix[2][1] = mat1.matrix[2][1] + mat2.matrix[2][1];
temp.matrix[2][2] = mat1.matrix[2][2] + mat2.matrix[2][2];
temp.matrix[2][3] = mat1.matrix[2][3] + mat2.matrix[2][3];
temp.matrix[3][0] = mat1.matrix[3][0] + mat2.matrix[3][0];
temp.matrix[3][1] = mat1.matrix[3][1] + mat2.matrix[3][1];
temp.matrix[3][2] = mat1.matrix[3][2] + mat2.matrix[3][2];
temp.matrix[3][3] = mat1.matrix[3][3] + mat2.matrix[3][3];
return temp;
}
// subtract two matrices
Matrix4D operator - (const Matrix4D& mat1, const Matrix4D& mat2)
{
Matrix4D temp;
temp.matrix[0][0] = mat1.matrix[0][0] - mat2.matrix[0][0];
temp.matrix[0][1] = mat1.matrix[0][1] - mat2.matrix[0][1];
temp.matrix[0][2] = mat1.matrix[0][2] - mat2.matrix[0][2];
temp.matrix[0][3] = mat1.matrix[0][3] - mat2.matrix[0][3];
temp.matrix[1][0] = mat1.matrix[1][0] - mat2.matrix[1][0];
temp.matrix[1][1] = mat1.matrix[1][1] - mat2.matrix[1][1];
temp.matrix[1][2] = mat1.matrix[1][2] - mat2.matrix[1][2];
temp.matrix[1][3] = mat1.matrix[1][3] - mat2.matrix[1][3];
temp.matrix[2][0] = mat1.matrix[2][0] - mat2.matrix[2][0];
temp.matrix[2][1] = mat1.matrix[2][1] - mat2.matrix[2][1];
temp.matrix[2][2] = mat1.matrix[2][2] - mat2.matrix[2][2];
temp.matrix[2][3] = mat1.matrix[2][3] - mat2.matrix[2][3];
temp.matrix[3][0] = mat1.matrix[3][0] - mat2.matrix[3][0];
temp.matrix[3][1] = mat1.matrix[3][1] - mat2.matrix[3][1];
temp.matrix[3][2] = mat1.matrix[3][2] - mat2.matrix[3][2];
temp.matrix[3][3] = mat1.matrix[3][3] - mat2.matrix[3][3];
return temp;
}
// cross product of two matrices
Matrix4D operator * (const Matrix4D& mat1, const Matrix4D& mat2)
{
Matrix4D temp;
temp.matrix[0][0] = (mat1.matrix[0][0] * mat2.matrix[0][0])
+ (mat1.matrix[0][1] * mat2.matrix[1][0])
+ (mat1.matrix[0][2] * mat2.matrix[2][0])
+ (mat1.matrix[0][3] * mat2.matrix[3][0]);
temp.matrix[0][1] = (mat1.matrix[0][0] * mat2.matrix[0][1])
+ (mat1.matrix[0][1] * mat2.matrix[1][1])
+ (mat1.matrix[0][2] * mat2.matrix[2][1])
+ (mat1.matrix[0][3] * mat2.matrix[3][1]);
temp.matrix[0][2] = (mat1.matrix[0][0] * mat2.matrix[0][2])
+ (mat1.matrix[0][1] * mat2.matrix[1][2])
+ (mat1.matrix[0][2] * mat2.matrix[2][2])
+ (mat1.matrix[0][3] * mat2.matrix[3][2]);
temp.matrix[0][3] = (mat1.matrix[0][0] * mat2.matrix[0][3])
+ (mat1.matrix[0][1] * mat2.matrix[1][3])
+ (mat1.matrix[0][2] * mat2.matrix[2][3])
+ (mat1.matrix[0][3] * mat2.matrix[3][3]);
temp.matrix[1][0] = (mat1.matrix[1][0] * mat2.matrix[0][0])
+ (mat1.matrix[1][1] * mat2.matrix[1][0])
+ (mat1.matrix[1][2] * mat2.matrix[2][0])
+ (mat1.matrix[1][3] * mat2.matrix[3][0]);
temp.matrix[1][1] = (mat1.matrix[1][0] * mat2.matrix[0][1])
+ (mat1.matrix[1][1] * mat2.matrix[1][1])
+ (mat1.matrix[1][2] * mat2.matrix[2][1])
+ (mat1.matrix[1][3] * mat2.matrix[3][1]);
temp.matrix[1][2] = (mat1.matrix[1][0] * mat2.matrix[0][2])
+ (mat1.matrix[1][1] * mat2.matrix[1][2])
+ (mat1.matrix[1][2] * mat2.matrix[2][2])
+ (mat1.matrix[1][3] * mat2.matrix[3][2]);
temp.matrix[1][3] = (mat1.matrix[1][0] * mat2.matrix[0][3])
+ (mat1.matrix[1][1] * mat2.matrix[1][3])
+ (mat1.matrix[1][2] * mat2.matrix[2][3])
+ (mat1.matrix[1][3] * mat2.matrix[3][3]);
temp.matrix[2][0] = (mat1.matrix[2][0] * mat2.matrix[0][0])
+ (mat1.matrix[2][1] * mat2.matrix[1][0])
+ (mat1.matrix[2][2] * mat2.matrix[2][0])
+ (mat1.matrix[2][3] * mat2.matrix[3][0]);
temp.matrix[2][1] = (mat1.matrix[2][0] * mat2.matrix[0][1])
+ (mat1.matrix[2][1] * mat2.matrix[1][1])
+ (mat1.matrix[2][2] * mat2.matrix[2][1])
+ (mat1.matrix[2][3] * mat2.matrix[3][1]);
temp.matrix[2][2] = (mat1.matrix[2][0] * mat2.matrix[0][2])
+ (mat1.matrix[2][1] * mat2.matrix[1][2])
+ (mat1.matrix[2][2] * mat2.matrix[2][2])
+ (mat1.matrix[2][3] * mat2.matrix[3][2]);
temp.matrix[2][3] = (mat1.matrix[2][0] * mat2.matrix[0][3])
+ (mat1.matrix[2][1] * mat2.matrix[1][3])
+ (mat1.matrix[2][2] * mat2.matrix[2][3])
+ (mat1.matrix[2][3] * mat2.matrix[3][3]);
temp.matrix[3][0] = (mat1.matrix[3][0] * mat2.matrix[0][0])
+ (mat1.matrix[3][1] * mat2.matrix[1][0])
+ (mat1.matrix[3][2] * mat2.matrix[2][0])
+ (mat1.matrix[3][3] * mat2.matrix[3][0]);
temp.matrix[3][1] = (mat1.matrix[3][0] * mat2.matrix[0][1])
+ (mat1.matrix[3][1] * mat2.matrix[1][1])
+ (mat1.matrix[3][2] * mat2.matrix[2][1])
+ (mat1.matrix[3][3] * mat2.matrix[3][1]);
temp.matrix[3][2] = (mat1.matrix[3][0] * mat2.matrix[0][2])
+ (mat1.matrix[3][1] * mat2.matrix[1][2])
+ (mat1.matrix[3][2] * mat2.matrix[2][2])
+ (mat1.matrix[3][3] * mat2.matrix[3][2]);
temp.matrix[3][3] = (mat1.matrix[3][0] * mat2.matrix[0][3])
+ (mat1.matrix[3][1] * mat2.matrix[1][3])
+ (mat1.matrix[3][2] * mat2.matrix[2][3])
+ (mat1.matrix[3][3] * mat2.matrix[3][3]);
return temp;
}
// multiply matrix by scalar value
Matrix4D operator * (const Matrix4D& mat, const double val)
{
Matrix4D temp;
temp.matrix[0][0] = mat.matrix[0][0] * val;
temp.matrix[0][1] = mat.matrix[0][1] * val;
temp.matrix[0][2] = mat.matrix[0][2] * val;
temp.matrix[0][3] = mat.matrix[0][3] * val;
temp.matrix[1][0] = mat.matrix[1][0] * val;
temp.matrix[1][1] = mat.matrix[1][1] * val;
temp.matrix[1][2] = mat.matrix[1][2] * val;
temp.matrix[1][3] = mat.matrix[1][3] * val;
temp.matrix[2][0] = mat.matrix[2][0] * val;
temp.matrix[2][1] = mat.matrix[2][1] * val;
temp.matrix[2][2] = mat.matrix[2][2] * val;
temp.matrix[2][3] = mat.matrix[2][3] * val;
temp.matrix[3][0] = mat.matrix[3][0] * val;
temp.matrix[3][1] = mat.matrix[3][1] * val;
temp.matrix[3][2] = mat.matrix[3][2] * val;
temp.matrix[3][3] = mat.matrix[3][3] * val;
return temp;
}
// multiply matrix by scalar value
Matrix4D operator * (const double val, const Matrix4D& mat)
{
Matrix4D temp;
temp.matrix[0][0] = mat.matrix[0][0] * val;
temp.matrix[0][1] = mat.matrix[0][1] * val;
temp.matrix[0][2] = mat.matrix[0][2] * val;
temp.matrix[0][3] = mat.matrix[0][3] * val;
temp.matrix[1][0] = mat.matrix[1][0] * val;
temp.matrix[1][1] = mat.matrix[1][1] * val;
temp.matrix[1][2] = mat.matrix[1][2] * val;
temp.matrix[1][3] = mat.matrix[1][3] * val;
temp.matrix[2][0] = mat.matrix[2][0] * val;
temp.matrix[2][1] = mat.matrix[2][1] * val;
temp.matrix[2][2] = mat.matrix[2][2] * val;
temp.matrix[2][3] = mat.matrix[2][3] * val;
temp.matrix[3][0] = mat.matrix[3][0] * val;
temp.matrix[3][1] = mat.matrix[3][1] * val;
temp.matrix[3][2] = mat.matrix[3][2] * val;
temp.matrix[3][3] = mat.matrix[3][3] * val;
return temp;
}
// cross product of vector and matrix
Vector operator * (const Matrix4D& mat, const Vector& vec)
{
double x, y, z, w;
x = mat.matrix[0][0]*vec.x() + mat.matrix[1][0]*vec.y()
+ mat.matrix[2][0]*vec.z() + mat.matrix[3][0]*vec.w();
y = mat.matrix[0][1]*vec.x() + mat.matrix[1][1]*vec.y()
+ mat.matrix[2][1]*vec.z() + mat.matrix[3][1]*vec.w();
z = mat.matrix[0][2]*vec.x() + mat.matrix[1][2]*vec.y()
+ mat.matrix[2][2]*vec.z() + mat.matrix[3][2]*vec.w();
w = mat.matrix[0][3]*vec.x() + mat.matrix[1][3]*vec.y()
+ mat.matrix[2][3]*vec.z() + mat.matrix[3][3]*vec.w();
// normalize w component
return Vector(x/w, y/w, z/w, 1.0);
}
// cross product of vector and matrix
Vector operator * (const Vector& vec, const Matrix4D& mat)
{
double x, y, z, w;
x = mat.matrix[0][0]*vec.x() + mat.matrix[1][0]*vec.y()
+ mat.matrix[2][0]*vec.z() + mat.matrix[3][0]*vec.w();
y = mat.matrix[0][1]*vec.x() + mat.matrix[1][1]*vec.y()
+ mat.matrix[2][1]*vec.z() + mat.matrix[3][1]*vec.w();
z = mat.matrix[0][2]*vec.x() + mat.matrix[1][2]*vec.y()
+ mat.matrix[2][2]*vec.z() + mat.matrix[3][2]*vec.w();
w = mat.matrix[0][3]*vec.x() + mat.matrix[1][3]*vec.y()
+ mat.matrix[2][3]*vec.z() + mat.matrix[3][3]*vec.w();
// normalize w component
return Vector(x/w, y/w, z/w, 1.0);
}
// cross product of point and matrix
Point operator * (const Matrix4D& mat, const Point& pt)
{
double x, y, z, w;
x = mat.matrix[0][0]*pt.x() + mat.matrix[1][0]*pt.y()
+ mat.matrix[2][0]*pt.z() + mat.matrix[3][0];
y = mat.matrix[0][1]*pt.x() + mat.matrix[1][1]*pt.y()
+ mat.matrix[2][1]*pt.z() + mat.matrix[3][1];
z = mat.matrix[0][2]*pt.x() + mat.matrix[1][2]*pt.y()
+ mat.matrix[2][2]*pt.z() + mat.matrix[3][2];
w = mat.matrix[0][3]*pt.x() + mat.matrix[1][3]*pt.y()
+ mat.matrix[2][3]*pt.z() + mat.matrix[3][3];
// normalize w component
return Point(x/w, y/w, z/w);
}
// cross product of point and matrix
Point operator * (const Point& pt, const Matrix4D& mat)
{
double x, y, z, w;
x = mat.matrix[0][0]*pt.x() + mat.matrix[1][0]*pt.y()
+ mat.matrix[2][0]*pt.z() + mat.matrix[3][0];
y = mat.matrix[0][1]*pt.x() + mat.matrix[1][1]*pt.y()
+ mat.matrix[2][1]*pt.z() + mat.matrix[3][1];
z = mat.matrix[0][2]*pt.x() + mat.matrix[1][2]*pt.y()
+ mat.matrix[2][2]*pt.z() + mat.matrix[3][2];
w = mat.matrix[0][3]*pt.x() + mat.matrix[1][3]*pt.y()
+ mat.matrix[2][3]*pt.z() + mat.matrix[3][3];
// normalize w component
return Point(x/w, y/w, z/w);
}
// divide matrix by scalar value
Matrix4D operator / (const Matrix4D& mat, const double value)
{
double val = value;
// avoid divide by zero
if (val == 0.0)
val = 0.00000001;
Matrix4D temp; // returning matrix
temp.matrix[0][0] = mat.matrix[0][0] / val;
temp.matrix[0][1] = mat.matrix[0][1] / val;
temp.matrix[0][2] = mat.matrix[0][2] / val;
temp.matrix[0][3] = mat.matrix[0][3] / val;
temp.matrix[1][0] = mat.matrix[1][0] / val;
temp.matrix[1][1] = mat.matrix[1][1] / val;
temp.matrix[1][2] = mat.matrix[1][2] / val;
temp.matrix[1][3] = mat.matrix[1][3] / val;
temp.matrix[2][0] = mat.matrix[2][0] / val;
temp.matrix[2][1] = mat.matrix[2][1] / val;
temp.matrix[2][2] = mat.matrix[2][2] / val;
temp.matrix[2][3] = mat.matrix[2][3] / val;
temp.matrix[3][0] = mat.matrix[3][0] / val;
temp.matrix[3][1] = mat.matrix[3][1] / val;
temp.matrix[3][2] = mat.matrix[3][2] / val;
temp.matrix[3][3] = mat.matrix[3][3] / val;
return temp;
}
// assignment of addition of matrix to itself
Matrix4D& Matrix4D::operator += (const Matrix4D& mat)
{
matrix[0][0] += mat.matrix[0][0];
matrix[0][1] += mat.matrix[0][1];
matrix[0][2] += mat.matrix[0][2];
matrix[0][3] += mat.matrix[0][3];
matrix[1][0] += mat.matrix[1][0];
matrix[1][1] += mat.matrix[1][1];
matrix[1][2] += mat.matrix[1][2];
matrix[1][3] += mat.matrix[1][3];
matrix[2][0] += mat.matrix[2][0];
matrix[2][1] += mat.matrix[2][1];
matrix[2][2] += mat.matrix[2][2];
matrix[2][3] += mat.matrix[2][3];
matrix[3][0] += mat.matrix[3][0];
matrix[3][1] += mat.matrix[3][1];
matrix[3][2] += mat.matrix[3][2];
matrix[3][3] += mat.matrix[3][3];
return *this;
}
// assignment of subtraction of matrix from itself
Matrix4D& Matrix4D::operator -= (const Matrix4D& mat)
{
matrix[0][0] -= mat.matrix[0][0];
matrix[0][1] -= mat.matrix[0][1];
matrix[0][2] -= mat.matrix[0][2];
matrix[0][3] -= mat.matrix[0][3];
matrix[1][0] -= mat.matrix[1][0];
matrix[1][1] -= mat.matrix[1][1];
matrix[1][2] -= mat.matrix[1][2];
matrix[1][3] -= mat.matrix[1][3];
matrix[2][0] -= mat.matrix[2][0];
matrix[2][1] -= mat.matrix[2][1];
matrix[2][2] -= mat.matrix[2][2];
matrix[2][3] -= mat.matrix[2][3];
matrix[3][0] -= mat.matrix[3][0];
matrix[3][1] -= mat.matrix[3][1];
matrix[3][2] -= mat.matrix[3][2];
matrix[3][3] -= mat.matrix[3][3];
return *this;
}
// assignment of matrix multiplied by scalar
Matrix4D& Matrix4D::operator *= (const double val)
{
matrix[0][0] *= val;
matrix[0][1] *= val;
matrix[0][2] *= val;
matrix[0][3] *= val;
matrix[1][0] *= val;
matrix[1][1] *= val;
matrix[1][2] *= val;
matrix[1][3] *= val;
matrix[2][0] *= val;
matrix[2][1] *= val;
matrix[2][2] *= val;
matrix[2][3] *= val;
matrix[3][0] *= val;
matrix[3][1] *= val;
matrix[3][2] *= val;
matrix[3][3] *= val;
return *this;
}
// assignment of matrix divided by scalar
Matrix4D& Matrix4D::operator /= (const double val)
{
matrix[0][0] /= val;
matrix[0][1] /= val;
matrix[0][2] /= val;
matrix[0][3] /= val;
matrix[1][0] /= val;
matrix[1][1] /= val;
matrix[1][2] /= val;
matrix[1][3] /= val;
matrix[2][0] /= val;
matrix[2][1] /= val;
matrix[2][2] /= val;
matrix[2][3] /= val;
matrix[3][0] /= val;
matrix[3][1] /= val;
matrix[3][2] /= val;
matrix[3][3] /= val;
return *this;
}
// Relational operators
int operator == (const Matrix4D& mat1, const Matrix4D& mat2)
{
int i, j;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (mat1.matrix[i][j] != mat2.matrix[i][j])
return FALSE;
}
}
return TRUE;
}
int operator != (const Matrix4D& mat1, const Matrix4D& mat2)
{
int i, j;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (mat1.matrix[i][j] != mat2.matrix[i][j])
return TRUE;
}
}
return FALSE;
}
// output stream
ostream& operator << (ostream& co, const Matrix4D& mat)
{
int i, j;
for (i=0; i<4; i++)
{
co << '|';
for (j=0; j<4; j++)
{
co << mat.matrix[i][j] << ' ';
}
co << '|' << '\n';
}
return co;
}
               (
geocities.com/collegepark)