/************************************************************************
 * Matrix3D<T_FLOAT> (Matrix3DD : Matrix3D<double>)
 *
 * 移動や回転など３次元らしいメンバを追加。
 *
 ************************************************************************/

#ifndef ATS_MATRIX3D_H
#define ATS_MATRIX3D_H

#include "ats_MatrixXxX.h"
#include "ats_Point.h"

namespace ats
{
	template <class T_FLOAT>
	class Matrix3D : public Matrix<4,4,T_FLOAT>
	{
	private:
		static const int DIM;

	public:
		Matrix3D()
		{
			Initialize();
		}

		Matrix3D(const bool init) 
		: Matrix<4,4,T_FLOAT>(false) // 基底クラスは何もしない
		{
			if(init){
				Initialize();
			}
		}

		Matrix3D(const Matrix3D<T_FLOAT>& a) 
		: Matrix<4,4,T_FLOAT>(a)
		{
		}

		Matrix3D(const T_FLOAT a[4][4]) 
		: Matrix<4,4,T_FLOAT>(a)
		{
		}

		virtual ~Matrix3D() 
		{
		}

		virtual void Initialize() 
		{
			for(int i=0; i < DIM; i++){
				for(int j=0; j < DIM; j++){
					m_matrix[i][j] = 0;
				}
				m_matrix[i][i] = 1;
			}
		}

		virtual Matrix3D<T_FLOAT>& Rotate(T_FLOAT x,T_FLOAT y,T_FLOAT z) 
		{
			using namespace std;
			T_FLOAT sinx = sin(x), cosx = cos(x);
			T_FLOAT siny = sin(y), cosy = cos(y);
			T_FLOAT sinz = sin(z), cosz = cos(z);

			T_FLOAT tmpx[4][4] = {{     1,     0,     0,  0 },
								  {     0,  cosx,  sinx,  0 },
								  {     0, -sinx,  cosx,  0 },
								  {     0,     0,     0,  1 }};

			T_FLOAT tmpy[4][4] = {{  cosy,     0, -siny,  0 },
								  {     0,     1,     0,  0 },
								  {  siny,     0,  cosy,  0 },
								  {     0,     0,     0,  1 }};

			T_FLOAT tmpz[4][4] = {{  cosz,  sinz,     0,  0 },
								  { -sinz,  cosz,     0,  0 },
								  {     0,     0,     1,  0 },
								  {     0,     0,     0,  1 }};

			Matrix3D<T_FLOAT> rx(tmpx), ry(tmpy), rz(tmpz);
			*this *= rz * rx * ry;
			return *this;
		}

		virtual Matrix3D<T_FLOAT>& RotateX(T_FLOAT a) 
		{
			T_FLOAT sinx = sin(a), cosx = cos(a);
			T_FLOAT tmpx[4][4] = {{     1,     0,     0,  0 },
								  {     0,  cosx,  sinx,  0 },
								  {     0, -sinx,  cosx,  0 },
								  {     0,     0,     0,  1 }};
			*this *= tmpx;
			return *this;
		}

		virtual Matrix3D<T_FLOAT>& RotateY(T_FLOAT a) 
		{
			T_FLOAT siny = sin(a), cosy = cos(a);

			T_FLOAT tmpy[4][4] = {{  cosy,     0, -siny,  0 },
								  {     0,     1,     0,  0 },
								  {  siny,     0,  cosy,  0 },
								  {     0,     0,     0,  1 }};
			*this *= tmpy;
			return *this;
		}

		virtual Matrix3D<T_FLOAT>& RotateZ(T_FLOAT a) 
		{
			T_FLOAT sinz = sin(a), cosz = cos(a);

			T_FLOAT tmpz[4][4] = {{  cosz,  sinz,    0,  0 },
								  { -sinz,  cosz,    0,  0 },
								  {     0,     0,    1,  0 },
								  {     0,     0,    0,  1 }};
			*this *= tmpz;
			return *this;
		}

		virtual Matrix3D<T_FLOAT>& RevRotate(T_FLOAT x,T_FLOAT y,T_FLOAT z) 
		{
			using namespace std;
			T_FLOAT sinx = sin(x), cosx = cos(x);
			T_FLOAT siny = sin(y), cosy = cos(y);
			T_FLOAT sinz = sin(z), cosz = cos(z);

			T_FLOAT tmpx[4][4] = {{ 1,0,0,0 },
								  { 0,cosx,sinx,0 },
								  { 0,-sinx,cosx,0 },
								  { 0,0,0,1 }};
			T_FLOAT tmpy[4][4] = {{ cosy,0,-siny,0 },
								  { 0,1,0,0 },
								  { siny,0,cosy,0 },
								  { 0,0,0,1 }};
			T_FLOAT tmpz[4][4] = {{ cosz,sinz,0,0 },
								  { -sinz,cosz,0,0 },
								  { 0,0,1,0 },
								  { 0,0,0,1 }};

			Matrix3D<T_FLOAT> rx(tmpx), ry(tmpy), rz(tmpz);
			*this *= ry * rx * rz;
			return *this;
		}

		virtual Matrix3D<T_FLOAT>& Translate(T_FLOAT x, T_FLOAT y, T_FLOAT z) 
		{
			/* 4*4は保証されている */
			T_FLOAT tmp[4][4] = {{ 1,0,0,0 },
								 { 0,1,0,0 },
								 { 0,0,1,0 },
								 { x,y,z,1 }};
			*this *= tmp;
			return *this;
		}

	};

	typedef Matrix3D<double> Matrix3DD;
	typedef Matrix3D< float> Matrix3DF;

	template <class T_FLOAT>
	const int Matrix3D<T_FLOAT>::DIM = 4;
}

#endif // #ifndef ATS_MATRIX3D_H

