
#ifndef _CG_MATRIX_H
#define _CG_MATRIX_H

#include "cgPlane.h"
#include "cgQuaternion.h"
#include "cgVector2.h"
#include "cgVector3.h"
#include "cgVector4.h"
#include "cgViewport.h"

namespace gravity
{

	class cgMatrix
	{
	public:
		float m11, m12, m13, m14;
		float m21, m22, m23, m24;
		float m31, m32, m33, m34;
		float m41, m42, m43, m44;

		cgMatrix();
		cgMatrix( const float * );
		cgMatrix( float m11, float m12, float m13, float m14,
			float m21, float m22, float m23, float m24,
			float m31, float m32, float m33, float m34,
			float m41, float m42, float m43, float m44 );

		operator float* ();
		operator const float* () const;

		void operator = ( const cgMatrix& );
		void operator = ( float );

		cgMatrix& operator += ( const cgMatrix& );
		cgMatrix& operator -= ( const cgMatrix& );
		cgMatrix& operator *= ( const cgMatrix& );
		cgMatrix& operator *= ( float );
		cgMatrix& operator /= ( float );

		cgMatrix operator + () const;
		cgMatrix operator - () const;

		cgMatrix operator + ( const cgMatrix& ) const;
		cgMatrix operator - ( const cgMatrix& ) const;
		cgMatrix operator * ( const cgMatrix& ) const;
		cgMatrix operator * ( float ) const;
		cgMatrix operator / ( float ) const;

		friend cgMatrix operator * ( float, const cgMatrix& );

		bool operator == ( const cgMatrix& ) const;
		bool operator != ( const cgMatrix& ) const;

		void	affineTransformation	( float scaling, const cgVector3 *rotationCenter, const cgQuaternion *rotation, const cgVector3 *translation );
		void	affineTransformation2D	( float scaling, const cgVector2 *rotationCenter, float rotation, cgVector2 *translation );
		bool	decompose				( cgVector3 *pOutScale, cgQuaternion *pOutRotation, cgVector3 *pOutTranslation );
		float	determinant				(  );
		void	identity				(  );
		void	inverse					( float determinant, const cgMatrix *m );
		bool	isIdentity				(  );
		void	lookAtLH				( const cgVector3 *eye, const cgVector3 *center, const cgVector3 *up );
		void	lookAtRH				( const cgVector3 *eye, const cgVector3 *center, const cgVector3 *up );
		void	multiply				( const cgMatrix *m );
		void	multiplyTranspose		( const cgMatrix *m );
		void	orthoLH					( float w, float h, float zn, float zf );
		void	orthoOffCenterLH		( float l, float r, float b, float t, float zn, float zf );
		void	orthoOffCenterRH		( float l, float r, float b, float t, float zn, float zf );
		void	orthoRH					( float w, float h, float zn, float zf );
		void	perspectiveFovLH		( float fovy, float aspect, float zn, float zf );
		void	perspectiveFovRH		( float fovy, float aspect, float zn, float zf );
		void	perspectiveLH			( float w, float h, float zn, float zf );
		void	perspectiveOffCenterLH	( float l, float r, float b, float t, float zn, float zf );
		void	perspectiveOffCenterRH	( float l, float r, float b, float t, float zn, float zf );
		void	perspectiveRH			( float w, float h, float zn, float zf );
		void	reflect					( const cgPlane *p );
		void	rotationAxis			( const cgVector3 *v, float angle );
		void	rotationQuaternion		( const cgQuaternion *q );
		void	rotationX				( float angle );
		void	rotationY				( float angle );
		void	rotationYawPitchRoll	( float yaw, float pitch, float roll );
		void	rotationZ				( float angle );
		void	scaling					( float sx, float sy, float sz );
		void	shadow					( const cgVector4 *light, const cgPlane *p );
		void	transformation			( const cgVector3 *scalingCenter, const cgQuaternion *scalingRotation, const cgVector3 *scaling, const cgVector3 *rotationCenter, const cgQuaternion *rotation, const cgVector3 *translation );
		void	transformation2D		( const cgVector2 *scalingCenter, float scalingRotation, const cgVector2* scaling, const cgVector2* rotationCenter, float rotation, const cgVector2* translation );
		void	translation				( float x, float y, float z );
		void	transpose				(  );
	};

}

#endif // _CG_MATRIX_H