/*------------------------------------------------------------------
			Maths Library
			-------------

	Header for C++ interface to basic geometry related maths
	functions

	(C) Silicon Dream Ltd 1994

  ------------------------------------------------------------------

Changes:						Date:
* Created file						19/08/94
*/

#ifndef CPPMATHS
#define CPPMATHS

extern "C"
{
#include <maths.h>
}

/*
	Four new classes are defined by this header:

		Vec	A three element cartesian vector
		Polar	A three element polar vector
		LVec	A four element cartesian vector
		Mat	A 4x4 matrix

	The following operations are permitted on these types:

	Vector operations:	Description:
	------------------	------------
	Vec vec(x, y, z)	Initialise a vector up to three values
	Vec vecA(vecB)		Initialise a vector with another vector
	Vec vec(lvec)		Initialise a vector with a long vector (loses last component)
	((Vec) lvec)		Convert a long vector to a vector (loses last component)
	Vec vec(pol)		Initialise a vector with a polar vector (conversion performed)
	((Vec) pol)             Convert a polar vector to a vector (conversion performed)
	vecA+vecB		Add two vectors
	vecA-vecB		Subtract a vector from another
	vec*f			Multiply a vector by a scalar
	vec*mat			Multiply a vector by a matrix
	vec/f			Divide a vector by a scalar
	vecA+=vecB		Add two vectors (overwrite original)
	vecA-=vecB		Subtract a vector from another (overwrite original)
	vec*=f			Multiply a vector by a scalar (overwrite original)
	vec*=mat		Multiply a vector by a matrix (overwrite original)
	vec/=f			Divide a vector by a scalar (overwrite original)
	-vec			Returns the vector inverted
	vecA==vecB		Are two vectors equal?
	vecA!=vecB		Are two vectors not equal?
	vec.Set(x, y, z)	Set a vector's components
	vec.SetX(x)		Set a vector's x component
	vec.SetY(y)		Set a vector's y component
	vec.SetZ(z)		Set a vector's z component
	vec.X()			Get x component
	vec.Y()			Get y component
	vec.Z()			Get z component
	vec.Len()		Get length of vector
	vecA.Dot(vecB)		Get dot product of two vectors
	vecA.Cross(vecB)	Get cross product of two vectors
	vec.AddrVec()		Gets address of Vector member (WARNING: Use only to interface to non C++ code)

	Long vector operations:	Description:
	-----------------------	------------
	LVec lvec(x, y, z, w)	Initialise a long vector with up to four values
	LVec lvecA(lvecB)	Initialise a long vector with another long vector
	LVec lvec(vec)		Initialise a long vector with a vector (last component becomes 1.0)
	((LVec) vec)		Convert a long vector to a vector (last component becomes 1.0)
	lvec*mat		Multiply a long vector with a matrix
	lvec*=mat		Multiply a long vector with a matrix (overwrite original)
	lvecA==lvecB		Are two long vectors equal?
	lvecA!=lvecB		Are two long vectors not equal?
	lvec.Set(x, y, z, w)	Set a long vector's components
	lvec.SetX(x)		Set a long vector's x component
	lvec.SetY(y)		Set a long vector's y component
	lvec.SetZ(z)		Set a long vector's z component
	lvec.SetW(w)		Set a long vector's w component
	lvec.X()		Get x component
	lvec.Y()		Get y component
	lvec.Z()		Get z component
	lvec.W()		Get w component (homogeneous coordinate)
	lvec.AddrLVec()		Gets address of LongVec member (WARNING: Use only to interface to non C++ code)

	Polar operations:	Description:
	-----------------	------------
	Polar pol(t, p, r)	Initialise a polar with up to three values
	Polar polA(polB)	Initialise a polar with another polar
	Polar pol(vec)		Initialise a polar with a vector (conversion performed)
	((Polar) vec)		Convert a vector to a polar (conversion performed)
	polA==polB		Are two polars equal?
	polA!=polB		Are two polars not equal?
	pol.Set(t, p, r)	Set a polar's components
	vec.SetTheta(t)		Set a vector's theta component
	vec.SetPhi(p)		Set a vector's phi component
	vec.SetRho(r)		Set a vector's rho component
	pol.Theta()		Get theta component
	pol.Phi()		Get phi component
	pol.Rho()		Get rho component
	pol.AddrVec()		Gets address of Vector member (WARNING: Use only to interface to non C++ code)

	Matrix operations:	Description:
	------------------	------------
	Mat mat			Initialise a matrix with the identity matrix
	Mat matA(matB)		Initialise a matrix with another matrix
	Mat mat(XROT, a)	Initialise a matrix with a rotation or scale value (or leave it unset)
	Mat mat(TRANSL, vec)	Initialise a matrix with a translation value (or leave it unset)
	Mat mat(vecPos, vecDir, vecUp) Initialise a matrix by defining a new coordinate system
	matA*matB		Multiply two matricies
	matA*=matB		Multiply two matricies (overwrite original)
	matA==matB		Are two matricies equal?
	matA!=matB		Are two matricies not equal?
	-mat			Compute inverse of matrix (ie. when multiplied by this gives identity)
	mat.Set(f1,..f16)	Sets elements of a matrix
	mat.MoveParent(vec)	Moves coor sys defined by matrix relative to its parent
	mat.MoveChild(vec)		Moves coor sys defined by matrix relative to itself
	mat.ScaleParent(x, y, z) Scale coor sys defined by matrix relative to its parent
	mat.ScaleChild(x, y, z)	Scale coor sys defined by matrix relative to its own origin
	mat.XRotParent(a)	Rotates coor sys defined by matrix about parents x axis
	mat.XRotChild(a)	Rotates coor sys defined by matrix about its own x axis
	mat.YRotParent(a)	Rotates coor sys defined by matrix about parents y axis
	mat.YRotChild(a)	Rotates coor sys defined by matrix about its own y axis
	mat.ZRotParent(a)	Rotates coor sys defined by matrix about parents z axis
	mat.ZRotChild(a)	Rotates coor sys defined by matrix about its own z axis
	mat.ReverseX()		Reverses direction of x axis of coor sys defined by matrix
	mat.ReverseY()		Reverses direction of y axis of coor sys defined by matrix
	mat.ReverseZ()		Reverses direction of z axis of coor sys defined by matrix
	mat.AddrMat()		Gets address of Matrix member (WARNING: Use only to interface to non C++ code)
*/

class _cppdyn Vec			// vec
	{
	friend class _cppdyn LVec;
	friend class _cppdyn Polar;
	friend class _cppdyn Mat;
	public:
		Vec (float fX=0.0, float fY=0.0, float fZ=0.0);
		Vec (Vec const &vecOther);
		Vec (LVec const &lvec);
		Vec (Polar const &pol);
		Vec operator+ (Vec const &vecOther) const;
		Vec operator- (Vec const &vecOther) const;
		Vec operator* (float f) const;
		Vec operator* (Mat const &mat) const;
		Vec operator/ (float f) const;
		Vec &operator+= (Vec const &vecOther);
		Vec &operator-= (Vec const &vecOther);
		Vec &operator*= (float f);
		Vec &operator*= (Mat const &mat);
		Vec &operator/= (float f);
		Vec operator- () const;
		bool operator== (Vec const &vecOther) const;
		bool operator!= (Vec const &vecOther) const;
		Vec &Set (float fX, float fY, float fZ);
		Vec &SetX (float fX);
		Vec &SetY (float fY);
		Vec &SetZ (float fZ);
		float X () const;
		float Y () const;
		float Z () const;
		float Len () const;
		float Dot (Vec const &vecOther) const;
		Vec Cross (Vec const &vecOther) const;
		Vector *AddrVec ();
	private:
		Vector		vec;
	};

class _cppdyn LVec 				// lvec
	{
	friend class _cppdyn Vec;
	public:
		LVec (float fX=0.0, float fY=0.0, float fZ=0.0, float fW=1.0);
		LVec (LVec const &lvecOther);
		LVec (Vec const &vec);
		LVec operator* (Mat const &mat) const;
		LVec &operator*= (Mat const &mat);
		bool operator== (LVec const &lvecOther) const;
		bool operator!= (LVec const &lvecOther) const;
		LVec &Set (float fX, float fY, float fZ, float fW);
		LVec &SetX (float fX);
		LVec &SetY (float fY);
		LVec &SetZ (float fZ);
		LVec &SetW (float fW);
		float X () const;
		float Y () const;
		float Z () const;
		float W () const;
		LongVec *AddrLVec ();
	private:
		LongVec		lvec;
	};

class _cppdyn Polar 				// pol
	{
	friend class _cppdyn Vec;
	public:
		Polar (float fX=0.0, float fY=0.0, float fZ=0.0);
		Polar (Polar const &polOther);
		Polar (Vec const &vecOther);
		bool operator== (Polar const &polOther) const;
		bool operator!= (Polar const &polOther) const;
		Polar &Set (float fTheta, float fPhi, float fRho);
		Polar &SetTheta (float fTheta);
		Polar &SetPhi (float fPhi);
		Polar &SetRho (float fRho);
		float Theta () const;
		float Phi () const;
		float Rho () const;
		Vector *AddrVec ();
	private:
		Vector		vec;
	};

enum	MatType {XROT, YROT, ZROT, SCALE, TRANSL, UNSET};

class _cppdyn Mat 				// mat
	{
	friend class _cppdyn Vec;
	friend class _cppdyn LVec;
	public:
		Mat ();
		Mat (Mat const &matOther);
		Mat (MatType mt, float f1=1.0, float f2=1.0, float f3=1.0);
		Mat (MatType mt, const Vec &vec);
		Mat (Vec const &vecOrg, Vec const &vecAxZ, Vec const &vecAxY);
		Mat operator* (Mat const &matOther) const;
		Mat &operator*= (Mat const &matOther);
		bool operator== (Mat const &matOther) const;
		bool operator!= (Mat const &matOther) const;
		Mat operator- () const;
		Mat &Set (float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14, float f15, float f16);
		Mat &MoveParent (Vec const &vec);
		Mat &MoveChild (Vec const &vec);
		Mat &ScaleParent (float fX, float fY, float fZ);
		Mat &ScaleChild (float fX, float fY, float fZ);
		Mat &XRotParent (float fAng);
		Mat &XRotChild (float fAng);
		Mat &YRotParent (float fAng);
		Mat &YRotChild (float fAng);
		Mat &ZRotParent (float fAng);
		Mat &ZRotChild (float fAng);
		Mat &ReverseX ();
		Mat &ReverseY ();
		Mat &ReverseZ ();
		Matrix *AddrMat ();
	private:
		Matrix		mat;
	};

#endif			// Do not include this file twice
