Advertisement

Evaluate my matrix/vector classes?

Started by December 26, 2000 01:16 PM
0 comments, last by GSG9 24 years ago
I''m simply looking for some feedback on my vector and matrix classes...Optimizations, errors, etc. Here they are: Vector:
  
#define PI 3.141592654
#define DEGTORAD(angle) (PI/180*(angle))
#define RADTODEG(angle) (180/PI*(angle))

class Vector
{
private:
	union {
		struct {
			double _x, _y, _z;
		};
		struct {
			double _vVector[3];
		};
	};

public:
	Vector(void) : _x(0), _y(0), _z(0) {};

	Vector(const double x, const double y, const double z) : _x(x), _y(y), _z(z) {};

	Vector(const double* pVector) : _x(pVector[0]), _y(pVector[1]), _z(pVector[2]) {};

	Vector(const Vector& aVector) : _x(aVector._x), _y(aVector._y), _z(aVector._z) {};	

	inline const Vector& operator = (const Vector& aVector)
	{
		_x = aVector._x;
		_y = aVector._y;
		_z = aVector._z;
		return *this;
	}

	inline const bool operator == (const Vector& aVector) const
	{
		return (_x == aVector._x && _y == aVector._y && _z == aVector._z);
	}

	inline const bool operator != (const Vector& aVector) const
	{
		return !(_x == aVector._x && _y == aVector._y && _z == aVector._z);
	}

	inline const double length(void) const
	{
		return sqrt(_x*_x + _y*_y + _z*_z);
	}

	inline void normalize(void)
	{
		double dLength = sqrt(_x*_x + _y*_y + _z*_z);

		_x = _x / dLength;
		_y = _y / dLength;
		_z = _z / dLength;
	}

	inline const Vector operator + (const Vector& aVector) const
	{
		return Vector(_x + aVector._x, _y + aVector._y, _z + aVector._z);
	}

	inline const Vector operator - (const Vector& aVector) const
	{
		return Vector(_x - aVector._x, _y - aVector._y, _z - aVector._z);
	}

	inline const Vector operator * (const Vector& aVector) const
	{
		return Vector(_x * aVector._x, _y * aVector._y, _z * aVector._z);
	}

	inline const Vector operator * (const double dScalar) const
	{
		return Vector(_x * dScalar, _y * dScalar, _z * dScalar);
	}

	inline const Vector operator / (const Vector& aVector) const
	{
		return Vector(_x / aVector._x, _y / aVector._y, _z / aVector._z);
	}

	inline const Vector operator / (const double dScalar) const
	{
		return Vector(_x / dScalar, _y / dScalar, _z / dScalar);
	}
	
	inline const double operator [] (const int nElement) const {return _vVector[nElement];};
	inline const void operator () (const int nElement, double dValue) {_vVector[nElement] = dValue;};

	inline const double* vector(void) const {return _vVector;};
	inline const void vector(const double* pVector) {memcpy(_vVector, pVector, sizeof(double)*3);};	

	inline const Vector unit(void) const
	{
		double dLength = sqrt(_x*_x + _y*_y + _z*_z);

		return Vector(_x/dLength, _y/dLength, _z/dLength);
	}

	inline friend const double DotProduct(const Vector& aVectorA, const Vector& aVectorB)
	{
		return (aVectorA._x*aVectorB._x + aVectorA._y*aVectorB._y + aVectorA._z*aVectorB._z);
	}

	inline friend const Vector Projection(const Vector& aVectorA, const Vector& aVectorB)
	{
		double dCosine = DotProduct(aVectorA.unit(), aVectorB.unit());
		double dLength = aVectorA.length() * dCosine;
		return Vector(aVectorB.unit() * dLength);
	}

	inline friend const Vector CrossProduct(const Vector& aVectorA, const Vector& aVectorB)
	{
		return Vector(aVectorA._y*aVectorB._z-aVectorB._y*aVectorA._z, aVectorA._z*aVectorB._x-aVectorB._z*aVectorA._x, aVectorA._x*aVectorB._y-aVectorB._x*aVectorA._y);
	}

	inline friend const double ScalarTripleProduct(const Vector& aVectorA, const Vector& aVectorB, const Vector& aVectorC)
	{
		return DotProduct((CrossProduct(aVectorA, aVectorB)), aVectorC);
	}
};
[/source]
And Matrix, ignore the coutMatrix function though:
[source]
class Matrix  
{
private:
	union
	{
		struct {
			double _mMatrix16[16];
		};
		struct {
			double _m00,_m10,_m20,_m30;
			double _m01,_m11,_m21,_m31;
			double _m02,_m12,_m22,_m32;
			double _m03,_m13,_m23,_m33;
		};
	};

public:
	Matrix(void) : _m00(1),_m01(0),_m02(0),_m03(0),
				   _m10(0),_m11(1),_m12(0),_m13(0),
				   _m20(0),_m21(0),_m22(1),_m23(0),
				   _m30(0),_m31(0),_m32(0),_m33(1)
	{};

	Matrix(const double m00, const double m01, const double m02, const double m03,
		   const double m10, const double m11, const double m12, const double m13,
		   const double m20, const double m21, const double m22, const double m23,
		   const double m30, const double m31, const double m32, const double m33)
		 : _m00(m00), _m01(m01), _m02(m02), _m03(m03),
		   _m10(m10), _m11(m11), _m12(m12), _m13(m13),
		   _m20(m20), _m21(m21), _m22(m22), _m23(m23),
		   _m30(m30), _m31(m31), _m32(m32), _m33(m33)
	{};

	Matrix(const double* pMatrix) : _m00(pMatrix[0]), _m01(pMatrix[1]), _m02(pMatrix[2]), _m03(pMatrix[3]),
		                            _m10(pMatrix[4]), _m11(pMatrix[5]), _m12(pMatrix[6]), _m13(pMatrix[7]),
									_m20(pMatrix[8]), _m21(pMatrix[9]), _m22(pMatrix[10]),_m23(pMatrix[11]),
									_m30(pMatrix[12]),_m31(pMatrix[13]),_m32(pMatrix[14]),_m33(pMatrix[15])
	{};

	Matrix(const Matrix& aMatrix) : _m00(aMatrix._m00), _m01(aMatrix._m01), _m02(aMatrix._m02), _m03(aMatrix._m03),
									_m10(aMatrix._m10), _m11(aMatrix._m11), _m12(aMatrix._m12), _m13(aMatrix._m13),
									_m20(aMatrix._m20), _m21(aMatrix._m21), _m22(aMatrix._m22), _m23(aMatrix._m23),
									_m30(aMatrix._m30), _m31(aMatrix._m31), _m32(aMatrix._m32), _m33(aMatrix._m33)
	{};

	const Matrix& operator = (const Matrix& aMatrix)
	{
		_m00 = aMatrix._m00;
		_m01 = aMatrix._m01;
		_m02 = aMatrix._m02;
		_m03 = aMatrix._m03;
		_m10 = aMatrix._m10;
		_m11 = aMatrix._m11;
		_m12 = aMatrix._m12;
		_m13 = aMatrix._m13;
		_m20 = aMatrix._m20;
		_m21 = aMatrix._m21;
		_m22 = aMatrix._m22;
		_m23 = aMatrix._m23;
		_m30 = aMatrix._m30;
		_m31 = aMatrix._m31;
		_m32 = aMatrix._m32;
		_m33 = aMatrix._m33;

		return *this;
	}

	const bool operator == (const Matrix& aMatrix) const
	{
		return (_m00==aMatrix._m00,_m01==aMatrix._m01,_m02==aMatrix._m02,_m03==aMatrix._m03,
				_m10==aMatrix._m10,_m11==aMatrix._m11,_m12==aMatrix._m12,_m13==aMatrix._m13,
				_m20==aMatrix._m20,_m21==aMatrix._m21,_m22==aMatrix._m22,_m23==aMatrix._m23,
				_m30==aMatrix._m30,_m31==aMatrix._m31,_m32==aMatrix._m32,_m33==aMatrix._m33);
	}

	const bool operator != (const Matrix& aMatrix) const
	{
		return !(_m00==aMatrix._m00,_m01==aMatrix._m01,_m02==aMatrix._m02,_m03==aMatrix._m03,
				 _m10==aMatrix._m10,_m11==aMatrix._m11,_m12==aMatrix._m12,_m13==aMatrix._m13,
				 _m20==aMatrix._m20,_m21==aMatrix._m21,_m22==aMatrix._m22,_m23==aMatrix._m23,
				 _m30==aMatrix._m30,_m31==aMatrix._m31,_m32==aMatrix._m32,_m33==aMatrix._m33);
	}

	const Matrix operator + (const Matrix& aMatrix) const
	{
		return Matrix(_m00+aMatrix._m00, _m01+aMatrix._m01, _m02+aMatrix._m02, _m03+aMatrix._m03,
					  _m10+aMatrix._m10, _m11+aMatrix._m11, _m12+aMatrix._m12, _m13+aMatrix._m13,
					  _m20+aMatrix._m20, _m21+aMatrix._m21, _m22+aMatrix._m22, _m23+aMatrix._m23,
					  _m30+aMatrix._m30, _m31+aMatrix._m31, _m32+aMatrix._m32, _m33+aMatrix._m33);
	}

	const Matrix operator - (const Matrix& aMatrix) const
	{
		return Matrix(_m00-aMatrix._m00, _m01-aMatrix._m01, _m02-aMatrix._m02, _m03-aMatrix._m03,
					  _m10-aMatrix._m10, _m11-aMatrix._m11, _m12-aMatrix._m12, _m13-aMatrix._m13,
					  _m20-aMatrix._m20, _m21-aMatrix._m21, _m22-aMatrix._m22, _m23-aMatrix._m23,
					  _m30-aMatrix._m30, _m31-aMatrix._m31, _m32-aMatrix._m32, _m33-aMatrix._m33);
	}

	const Matrix operator * (const Matrix& aMatrix) const
	{
		return Matrix(_m00*aMatrix._m00+_m01*aMatrix._m10+_m02*aMatrix._m20+_m03*aMatrix._m30,
					  _m00*aMatrix._m01+_m01*aMatrix._m11+_m02*aMatrix._m21+_m03*aMatrix._m31,
					  _m00*aMatrix._m02+_m01*aMatrix._m12+_m02*aMatrix._m22+_m03*aMatrix._m32,
					  _m00*aMatrix._m03+_m01*aMatrix._m13+_m02*aMatrix._m23+_m03*aMatrix._m33,

					  _m10*aMatrix._m00+_m11*aMatrix._m10+_m12*aMatrix._m20+_m13*aMatrix._m30,
					  _m10*aMatrix._m01+_m11*aMatrix._m11+_m12*aMatrix._m21+_m13*aMatrix._m31,
					  _m10*aMatrix._m02+_m11*aMatrix._m12+_m12*aMatrix._m22+_m13*aMatrix._m32,
					  _m10*aMatrix._m03+_m11*aMatrix._m13+_m12*aMatrix._m23+_m13*aMatrix._m33,

					  _m20*aMatrix._m00+_m21*aMatrix._m10+_m22*aMatrix._m20+_m23*aMatrix._m30,
					  _m20*aMatrix._m01+_m21*aMatrix._m11+_m22*aMatrix._m21+_m23*aMatrix._m31,
					  _m20*aMatrix._m02+_m21*aMatrix._m12+_m22*aMatrix._m22+_m23*aMatrix._m32,
					  _m20*aMatrix._m03+_m21*aMatrix._m13+_m22*aMatrix._m23+_m23*aMatrix._m33,

					  _m30*aMatrix._m00+_m31*aMatrix._m10+_m32*aMatrix._m20+_m33*aMatrix._m30,
					  _m30*aMatrix._m01+_m31*aMatrix._m11+_m32*aMatrix._m21+_m33*aMatrix._m31,
					  _m30*aMatrix._m02+_m31*aMatrix._m12+_m32*aMatrix._m22+_m33*aMatrix._m32,
					  _m30*aMatrix._m03+_m31*aMatrix._m13+_m32*aMatrix._m23+_m33*aMatrix._m33);
	}

	const Matrix operator * (const double dScalar) const
	{
		return Matrix(_m00*dScalar, _m01*dScalar, _m02*dScalar, _m03*dScalar,
					  _m10*dScalar, _m11*dScalar, _m12*dScalar, _m13*dScalar,
					  _m20*dScalar, _m21*dScalar, _m22*dScalar, _m23*dScalar,
					  _m30*dScalar, _m31*dScalar, _m32*dScalar, _m33*dScalar);
	}

	const double operator [] (const int nElement) const {return _mMatrix16[nElement];};
	const void operator () (const int nElement, double dValue) {_mMatrix16[nElement] = dValue;};

	const double* matrix(void) const {return _mMatrix16;};
	const void matrix(const double* pMatrix) {memcpy(_mMatrix16,pMatrix, sizeof(double)*16);};

	void transpose(void)
	{
		Matrix tempMatrix(*this);
		                      _m01=tempMatrix._m10; _m02=tempMatrix._m20; _m03=tempMatrix._m30;
		_m10=tempMatrix._m01;                       _m12=tempMatrix._m21; _m13=tempMatrix._m31;
		_m20=tempMatrix._m02; _m21=tempMatrix._m12;                       _m23=tempMatrix._m32;
		_m30=tempMatrix._m03; _m31=tempMatrix._m13; _m32=tempMatrix._m23;
	}
// Matrix Inverse NOT SET!!

//	void inverse(void)

//	{

//		

//	}

friend void coutMatrix(const Matrix& M)
{
	cout << M._m00 << " " << M._m01 << " " << M._m02 << " " << M._m03 << endl;
	cout << M._m10 << " " << M._m11 << " " << M._m12 << " " << M._m13 << endl;
	cout << M._m20 << " " << M._m21 << " " << M._m22 << " " << M._m23 << endl;
	cout << M._m30 << " " << M._m31 << " " << M._m32 << " " << M._m33 << endl;
}
};

const Matrix XRotation(const double dAngle)
{
	double dCos = cos(dAngle);
	double dSin = sin(dAngle);

	return Matrix(1,    0,     0, 0,
				  0, dCos, -dSin, 0,
				  0, dSin,  dCos, 0,
				  0,    0,     0, 1);
}

const Matrix YRotation(const double dAngle)
{
	double dCos = cos(dAngle);
	double dSin = sin(dAngle);

	return Matrix( dCos, 0, dSin, 0,
					  0, 1,    0, 0,
				  -dSin, 0, dCos, 0,
					  0, 0,    0, 1);
}

const Matrix ZRotation(const double dAngle)
{
	double dCos = cos(dAngle);
	double dSin = sin(dAngle);

	return Matrix(dCos, -dSin, 0, 0,
				  dSin,  dCos, 0, 0,
					 0,     0, 1, 0,
					 0,     0, 0, 1);
}

const Matrix AxisRotation(const double xRot, const double yRot, const double zRot)
{
	double dCosX = cos(xRot);
	double dCosY = cos(yRot);
	double dCosZ = cos(zRot);
	double dSinX = sin(xRot);
	double dSinY = sin(yRot);
	double dSinZ = sin(zRot);

	return Matrix(                  dCosY*dCosZ,                   dCosY*dSinZ,      -dSinY, 0,
				  dSinX*dSinY*dCosZ-dCosX*dSinZ, dSinX*dSinY*dSinZ+dCosX*dCosZ, dSinX*dCosY, 0,
				  dCosX*dSinY*dCosZ+dSinX*dSinZ, dCosX*dSinY*dSinZ-dSinX*dCosZ, dCosX*dCosY, 0,
					                          0,                             0,           0, 1);
}

const Matrix VectorRotation(const double Vx, const double Vy, const double Vz, const double dAngle)
{
	double dCos = cos(dAngle);
	double dSin = sin(dAngle);

	return Matrix(  Vx*Vx+(1-Vx*Vx)*dCos, Vx*Vy*(1-dCos)-Vz*dSin, Vx*Vz*(1-dCos)+Vy*dSin, 0,
				  Vx*Vy*(1-dCos)+Vz*dSin,   Vy*Vy+(1-Vy*Vy)*dCos, Vy*Vz*(1-dCos)-Vx*dSin, 0,
				  Vx*Vz*(1-dCos)-Vy*dSin, Vy*Vz*(1-dCos)+Vx*dSin,   Vz*Vz+(1-Vz*Vz)*dCos, 0,
					                   0,                      0,                      0, 1);
}

const Matrix Translation(const double Tx, const double Ty, const double Tz)
{
	return Matrix(1, 0, 0, Tx,
				  0, 1, 0, Ty,
				  0, 0, 1, Tz,
				  0, 0, 0,  1);
}

const Matrix Scale(const double Sx, const double Sy, const double Sz)
{
	return Matrix(Sx,  0,  0, 0,
				   0, Sy,  0, 0,
				   0,  0, Sz, 0,
				   0,  0,  0, 1);
}
  
Thanks for looking these over, ciao!
The projection on the vector is more complex than it needs to be. You can get the projection by just taking the dot product of the vector being projected with the unit vector of the one being projected onto. I think I would also make the functions such as XRotation static member functions just to keep everything together. Also people generally use names such as Matrix4 to distinguish it from a generic implementation handling any arbitrary number of dimensions such as you would find in many math packages.
Keys to success: Ability, ambition and opportunity.

This topic is closed to new replies.

Advertisement