#include "stdafx.h"
#include "valMatrix.h"
#include "valVector2.h"
#include "valVector3.h"
#include "valQuaternion.h"

namespace FDK
{
// public:

	array<float>^ Matrix::ToArray()
	{
		array<float>^ result = gcnew array<float>( 16 );
		result[0] = M11;
		result[1] = M12;
		result[2] = M13;
		result[3] = M14;
		result[4] = M21;
		result[5] = M22;
		result[6] = M23;
		result[7] = M24;
		result[8] = M31;
		result[9] = M32;
		result[10] = M33;
		result[11] = M34;
		result[12] = M41;
		result[13] = M42;
		result[14] = M43;
		result[15] = M44;

		return result;
	}
	void Matrix::Invert()
	{
		pin_ptr<Matrix> pinnedThis = this;
		::D3DXMatrixInverse( (D3DXMATRIX*) pinnedThis, NULL, (D3DXMATRIX*) pinnedThis );
	}
	bool Matrix::Decompose( [Out] Vector3% scale, [Out] Quaternion% rotation, [Out] Vector3% translation )
	{
		Vector3 localScale, localTrans;
		Quaternion localRot;
		pin_ptr<Matrix> pinnedThis = this;

		HRESULT hr = ::D3DXMatrixDecompose( (D3DXVECTOR3*) &localScale, (D3DXQUATERNION*) &localRot, (D3DXVECTOR3*) &localTrans, (D3DXMATRIX*) pinnedThis );

		scale = localScale;
		rotation = localRot;
		translation = localTrans;

		return hr == S_OK;
	}
	float Matrix::Determinant()
	{
		float temp1 = (M33 * M44) - (M34 * M43);
		float temp2 = (M32 * M44) - (M34 * M42);
		float temp3 = (M32 * M43) - (M33 * M42);
		float temp4 = (M31 * M44) - (M34 * M41);
		float temp5 = (M31 * M43) - (M33 * M41);
		float temp6 = (M31 * M42) - (M32 * M41);
		
		return ((((M11 * (((M22 * temp1) - (M23 * temp2)) + (M24 * temp3))) - (M12 * (((M21 * temp1) - 
			(M23 * temp4)) + (M24 * temp5)))) + (M13 * (((M21 * temp2) - (M22 * temp4)) + (M24 * temp6)))) - 
			(M14 * (((M21 * temp3) - (M22 * temp5)) + (M23 * temp6))));
	}
	Matrix Matrix::Add( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = left.M11 + right.M11;
		result.M12 = left.M12 + right.M12;
		result.M13 = left.M13 + right.M13;
		result.M14 = left.M14 + right.M14;
		result.M21 = left.M21 + right.M21;
		result.M22 = left.M22 + right.M22;
		result.M23 = left.M23 + right.M23;
		result.M24 = left.M24 + right.M24;
		result.M31 = left.M31 + right.M31;
		result.M32 = left.M32 + right.M32;
		result.M33 = left.M33 + right.M33;
		result.M34 = left.M34 + right.M34;
		result.M41 = left.M41 + right.M41;
		result.M42 = left.M42 + right.M42;
		result.M43 = left.M43 + right.M43;
		result.M44 = left.M44 + right.M44;
		return result;
	}
	void Matrix::Add( Matrix% left, Matrix% right, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = left.M11 + right.M11;
		r.M12 = left.M12 + right.M12;
		r.M13 = left.M13 + right.M13;
		r.M14 = left.M14 + right.M14;
		r.M21 = left.M21 + right.M21;
		r.M22 = left.M22 + right.M22;
		r.M23 = left.M23 + right.M23;
		r.M24 = left.M24 + right.M24;
		r.M31 = left.M31 + right.M31;
		r.M32 = left.M32 + right.M32;
		r.M33 = left.M33 + right.M33;
		r.M34 = left.M34 + right.M34;
		r.M41 = left.M41 + right.M41;
		r.M42 = left.M42 + right.M42;
		r.M43 = left.M43 + right.M43;
		r.M44 = left.M44 + right.M44;

		result = r;
	}
	Matrix Matrix::Subtract( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = left.M11 - right.M11;
		result.M12 = left.M12 - right.M12;
		result.M13 = left.M13 - right.M13;
		result.M14 = left.M14 - right.M14;
		result.M21 = left.M21 - right.M21;
		result.M22 = left.M22 - right.M22;
		result.M23 = left.M23 - right.M23;
		result.M24 = left.M24 - right.M24;
		result.M31 = left.M31 - right.M31;
		result.M32 = left.M32 - right.M32;
		result.M33 = left.M33 - right.M33;
		result.M34 = left.M34 - right.M34;
		result.M41 = left.M41 - right.M41;
		result.M42 = left.M42 - right.M42;
		result.M43 = left.M43 - right.M43;
		result.M44 = left.M44 - right.M44;
		return result;
	}
	void Matrix::Subtract( Matrix% left, Matrix% right, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = left.M11 - right.M11;
		r.M12 = left.M12 - right.M12;
		r.M13 = left.M13 - right.M13;
		r.M14 = left.M14 - right.M14;
		r.M21 = left.M21 - right.M21;
		r.M22 = left.M22 - right.M22;
		r.M23 = left.M23 - right.M23;
		r.M24 = left.M24 - right.M24;
		r.M31 = left.M31 - right.M31;
		r.M32 = left.M32 - right.M32;
		r.M33 = left.M33 - right.M33;
		r.M34 = left.M34 - right.M34;
		r.M41 = left.M41 - right.M41;
		r.M42 = left.M42 - right.M42;
		r.M43 = left.M43 - right.M43;
		r.M44 = left.M44 - right.M44;

		result = r;
	}
	Matrix Matrix::Multiply( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41);
		result.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42);
		result.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43);
		result.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44);
		result.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41);
		result.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42);
		result.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43);
		result.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44);
		result.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41);
		result.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42);
		result.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43);
		result.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44);
		result.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41);
		result.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42);
		result.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43);
		result.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44);
		return result;
	}
	void Matrix::Multiply( Matrix% left, Matrix% right, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41);
		r.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42);
		r.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43);
		r.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44);
		r.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41);
		r.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42);
		r.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43);
		r.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44);
		r.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41);
		r.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42);
		r.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43);
		r.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44);
		r.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41);
		r.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42);
		r.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43);
		r.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44);
	
		result = r;
	}
	void Matrix::Multiply( Matrix* left, Matrix* right, Matrix* result, int count )
	{
		for( int i = 0; i < count; ++i )
		{
			::D3DXMatrixMultiply( 
				reinterpret_cast<D3DXMATRIX*>( &left[i] ),
				reinterpret_cast<const D3DXMATRIX*>( &right[i] ),
				reinterpret_cast<const D3DXMATRIX*>( &result[i] ) );
		}
	}
	void Matrix::Multiply( array<Matrix>^ left, array<Matrix>^ right, array<Matrix>^ result, int offset, int count )
	{
		if( left->Length != right->Length )
			throw gcnew ArgumentException( "左辺と右辺が同じサイズではありません。", "右" );
		if( right->Length != result->Length )
			throw gcnew ArgumentException( "結果配列と入力配列が同じサイズではありません。", "結果" );
				
		pin_ptr<Matrix> pinnedLeft = &left[offset];
		pin_ptr<Matrix> pinnedRight = &right[offset];
		pin_ptr<Matrix> pinnedResult = &result[offset];

		Multiply( pinnedLeft, pinnedRight, pinnedResult, count );
	}
	void Matrix::Multiply( array<Matrix>^ left, array<Matrix>^ right, array<Matrix>^ result )
	{
		Multiply( left, right, result, 0, 0 );
	}
	void Matrix::Multiply( array<Matrix>^ left, Matrix right, array<Matrix>^ result, int offset, int count )
	{
		if( left->Length != result->Length )
			throw gcnew ArgumentException( "結果配列と入力配列が同じサイズではありません。", "結果" );

		pin_ptr<Matrix> pinnedLeft = &left[offset];
		pin_ptr<Matrix> pinnedResult = &result[offset];
		for( int i = 0; i < count; ++i )
		{
			::D3DXMatrixMultiply(
				reinterpret_cast<D3DXMATRIX*>( &pinnedLeft[i] ),
				reinterpret_cast<const D3DXMATRIX*>( &right ),
				reinterpret_cast<const D3DXMATRIX*>( &pinnedResult[i] ) );
		}
	}
	void Matrix::Multiply( array<Matrix>^ left, Matrix right, array<Matrix>^ result )
	{
		Multiply( left, right, result, 0, 0 );
	}
	Matrix Matrix::Multiply( Matrix left, float right )
	{
		Matrix result;
		result.M11 = left.M11 * right;
		result.M12 = left.M12 * right;
		result.M13 = left.M13 * right;
		result.M14 = left.M14 * right;
		result.M21 = left.M21 * right;
		result.M22 = left.M22 * right;
		result.M23 = left.M23 * right;
		result.M24 = left.M24 * right;
		result.M31 = left.M31 * right;
		result.M32 = left.M32 * right;
		result.M33 = left.M33 * right;
		result.M34 = left.M34 * right;
		result.M41 = left.M41 * right;
		result.M42 = left.M42 * right;
		result.M43 = left.M43 * right;
		result.M44 = left.M44 * right;
		return result;
	}
	void Matrix::Multiply( Matrix% left, float right, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = left.M11 * right;
		r.M12 = left.M12 * right;
		r.M13 = left.M13 * right;
		r.M14 = left.M14 * right;
		r.M21 = left.M21 * right;
		r.M22 = left.M22 * right;
		r.M23 = left.M23 * right;
		r.M24 = left.M24 * right;
		r.M31 = left.M31 * right;
		r.M32 = left.M32 * right;
		r.M33 = left.M33 * right;
		r.M34 = left.M34 * right;
		r.M41 = left.M41 * right;
		r.M42 = left.M42 * right;
		r.M43 = left.M43 * right;
		r.M44 = left.M44 * right;

		result = r;
	}
	Matrix Matrix::Divide( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = left.M11 / right.M11;
		result.M12 = left.M12 / right.M12;
		result.M13 = left.M13 / right.M13;
		result.M14 = left.M14 / right.M14;
		result.M21 = left.M21 / right.M21;
		result.M22 = left.M22 / right.M22;
		result.M23 = left.M23 / right.M23;
		result.M24 = left.M24 / right.M24;
		result.M31 = left.M31 / right.M31;
		result.M32 = left.M32 / right.M32;
		result.M33 = left.M33 / right.M33;
		result.M34 = left.M34 / right.M34;
		result.M41 = left.M41 / right.M41;
		result.M42 = left.M42 / right.M42;
		result.M43 = left.M43 / right.M43;
		result.M44 = left.M44 / right.M44;
		return result;
	}
	void Matrix::Divide( Matrix% left, Matrix% right, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = left.M11 / right.M11;
		r.M12 = left.M12 / right.M12;
		r.M13 = left.M13 / right.M13;
		r.M14 = left.M14 / right.M14;
		r.M21 = left.M21 / right.M21;
		r.M22 = left.M22 / right.M22;
		r.M23 = left.M23 / right.M23;
		r.M24 = left.M24 / right.M24;
		r.M31 = left.M31 / right.M31;
		r.M32 = left.M32 / right.M32;
		r.M33 = left.M33 / right.M33;
		r.M34 = left.M34 / right.M34;
		r.M41 = left.M41 / right.M41;
		r.M42 = left.M42 / right.M42;
		r.M43 = left.M43 / right.M43;
		r.M44 = left.M44 / right.M44;

		result = r;
	}
	Matrix Matrix::Divide( Matrix left, float right )
	{
		Matrix result;
		float inv = 1.0f / right;

		result.M11 = left.M11 * inv;
		result.M12 = left.M12 * inv;
		result.M13 = left.M13 * inv;
		result.M14 = left.M14 * inv;
		result.M21 = left.M21 * inv;
		result.M22 = left.M22 * inv;
		result.M23 = left.M23 * inv;
		result.M24 = left.M24 * inv;
		result.M31 = left.M31 * inv;
		result.M32 = left.M32 * inv;
		result.M33 = left.M33 * inv;
		result.M34 = left.M34 * inv;
		result.M41 = left.M41 * inv;
		result.M42 = left.M42 * inv;
		result.M43 = left.M43 * inv;
		result.M44 = left.M44 * inv;
		return result;
	}
	void Matrix::Divide( Matrix% left, float right, [Out] Matrix% result )
	{
		float inv = 1.0f / right;

		Matrix r;
		r.M11 = left.M11 * inv;
		r.M12 = left.M12 * inv;
		r.M13 = left.M13 * inv;
		r.M14 = left.M14 * inv;
		r.M21 = left.M21 * inv;
		r.M22 = left.M22 * inv;
		r.M23 = left.M23 * inv;
		r.M24 = left.M24 * inv;
		r.M31 = left.M31 * inv;
		r.M32 = left.M32 * inv;
		r.M33 = left.M33 * inv;
		r.M34 = left.M34 * inv;
		r.M41 = left.M41 * inv;
		r.M42 = left.M42 * inv;
		r.M43 = left.M43 * inv;
		r.M44 = left.M44 * inv;

		result = r;
	}
	Matrix Matrix::Negate( Matrix matrix )
	{
		Matrix result;
		result.M11 = -matrix.M11;
		result.M12 = -matrix.M12;
		result.M13 = -matrix.M13;
		result.M14 = -matrix.M14;
		result.M21 = -matrix.M21;
		result.M22 = -matrix.M22;
		result.M23 = -matrix.M23;
		result.M24 = -matrix.M24;
		result.M31 = -matrix.M31;
		result.M32 = -matrix.M32;
		result.M33 = -matrix.M33;
		result.M34 = -matrix.M34;
		result.M41 = -matrix.M41;
		result.M42 = -matrix.M42;
		result.M43 = -matrix.M43;
		result.M44 = -matrix.M44;
		return result;
	}
	void Matrix::Negate( Matrix% matrix, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = -matrix.M11;
		r.M12 = -matrix.M12;
		r.M13 = -matrix.M13;
		r.M14 = -matrix.M14;
		r.M21 = -matrix.M21;
		r.M22 = -matrix.M22;
		r.M23 = -matrix.M23;
		r.M24 = -matrix.M24;
		r.M31 = -matrix.M31;
		r.M32 = -matrix.M32;
		r.M33 = -matrix.M33;
		r.M34 = -matrix.M34;
		r.M41 = -matrix.M41;
		r.M42 = -matrix.M42;
		r.M43 = -matrix.M43;
		r.M44 = -matrix.M44;

		result = r;
	}
	Matrix Matrix::Lerp( Matrix start, Matrix end, float amount )
	{
		Matrix result;
		result.M11 = start.M11 + ((end.M11 - start.M11) * amount);
		result.M12 = start.M12 + ((end.M12 - start.M12) * amount);
		result.M13 = start.M13 + ((end.M13 - start.M13) * amount);
		result.M14 = start.M14 + ((end.M14 - start.M14) * amount);
		result.M21 = start.M21 + ((end.M21 - start.M21) * amount);
		result.M22 = start.M22 + ((end.M22 - start.M22) * amount);
		result.M23 = start.M23 + ((end.M23 - start.M23) * amount);
		result.M24 = start.M24 + ((end.M24 - start.M24) * amount);
		result.M31 = start.M31 + ((end.M31 - start.M31) * amount);
		result.M32 = start.M32 + ((end.M32 - start.M32) * amount);
		result.M33 = start.M33 + ((end.M33 - start.M33) * amount);
		result.M34 = start.M34 + ((end.M34 - start.M34) * amount);
		result.M41 = start.M41 + ((end.M41 - start.M41) * amount);
		result.M42 = start.M42 + ((end.M42 - start.M42) * amount);
		result.M43 = start.M43 + ((end.M43 - start.M43) * amount);
		result.M44 = start.M44 + ((end.M44 - start.M44) * amount);
		return result;
	}
	void Matrix::Lerp( Matrix% start, Matrix% end, float amount, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = start.M11 + ((end.M11 - start.M11) * amount);
		r.M12 = start.M12 + ((end.M12 - start.M12) * amount);
		r.M13 = start.M13 + ((end.M13 - start.M13) * amount);
		r.M14 = start.M14 + ((end.M14 - start.M14) * amount);
		r.M21 = start.M21 + ((end.M21 - start.M21) * amount);
		r.M22 = start.M22 + ((end.M22 - start.M22) * amount);
		r.M23 = start.M23 + ((end.M23 - start.M23) * amount);
		r.M24 = start.M24 + ((end.M24 - start.M24) * amount);
		r.M31 = start.M31 + ((end.M31 - start.M31) * amount);
		r.M32 = start.M32 + ((end.M32 - start.M32) * amount);
		r.M33 = start.M33 + ((end.M33 - start.M33) * amount);
		r.M34 = start.M34 + ((end.M34 - start.M34) * amount);
		r.M41 = start.M41 + ((end.M41 - start.M41) * amount);
		r.M42 = start.M42 + ((end.M42 - start.M42) * amount);
		r.M43 = start.M43 + ((end.M43 - start.M43) * amount);
		r.M44 = start.M44 + ((end.M44 - start.M44) * amount);

		result = r;
	}
	Matrix Matrix::Billboard( Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector )
	{
		Matrix result;
		Vector3 difference = objectPosition - cameraPosition;
		Vector3 crossed;
		Vector3 final;

		float lengthSq = difference.LengthSquared();
		if (lengthSq < 0.0001f)
			difference = -cameraForwardVector;
		else
			difference *= static_cast<float>( 1.0f / Math::Sqrt( lengthSq ) );

		Vector3::Cross( cameraUpVector, difference, crossed );
		crossed.Normalize();
		Vector3::Cross( difference, crossed, final );

		result.M11 = crossed.X;
		result.M12 = crossed.Y;
		result.M13 = crossed.Z;
		result.M14 = 0.0f;
		result.M21 = final.X;
		result.M22 = final.Y;
		result.M23 = final.Z;
		result.M24 = 0.0f;
		result.M31 = difference.X;
		result.M32 = difference.Y;
		result.M33 = difference.Z;
		result.M34 = 0.0f;
		result.M41 = objectPosition.X;
		result.M42 = objectPosition.Y;
		result.M43 = objectPosition.Z;
		result.M44 = 1.0f;

		return result;
	}
	void Matrix::Billboard( Vector3% objectPosition, Vector3% cameraPosition, Vector3% cameraUpVector, Vector3% cameraForwardVector, [Out] Matrix% result )
	{
		Vector3 difference = objectPosition - cameraPosition;
		Vector3 crossed;
		Vector3 final;

		float lengthSq = difference.LengthSquared();
		if (lengthSq < 0.0001f)
			difference = -cameraForwardVector;
		else
			difference *= static_cast<float>( 1.0f / Math::Sqrt( lengthSq ) );

		Vector3::Cross( cameraUpVector, difference, crossed );
		crossed.Normalize();
		Vector3::Cross( difference, crossed, final );

		result.M11 = crossed.X;
		result.M12 = crossed.Y;
		result.M13 = crossed.Z;
		result.M14 = 0.0f;
		result.M21 = final.X;
		result.M22 = final.Y;
		result.M23 = final.Z;
		result.M24 = 0.0f;
		result.M31 = difference.X;
		result.M32 = difference.Y;
		result.M33 = difference.Z;
		result.M34 = 0.0f;
		result.M41 = objectPosition.X;
		result.M42 = objectPosition.Y;
		result.M43 = objectPosition.Z;
		result.M44 = 1.0f;
	}
	Matrix Matrix::RotationX( float angle )
	{
		Matrix result;
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );

		result.M11 = 1.0f;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = cos;
		result.M23 = sin;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = -sin;
		result.M33 = cos;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;

		return result;
	}
	void Matrix::RotationX( float angle, [Out] Matrix% result )
	{
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );

		result.M11 = 1.0f;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = cos;
		result.M23 = sin;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = -sin;
		result.M33 = cos;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
	}
	Matrix Matrix::RotationY( float angle )
	{
		Matrix result;
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );

		result.M11 = cos;
		result.M12 = 0.0f;
		result.M13 = -sin;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = 1.0f;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = sin;
		result.M32 = 0.0f;
		result.M33 = cos;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;

		return result;
	}
	void Matrix::RotationY( float angle, [Out] Matrix% result )
	{
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );

		result.M11 = cos;
		result.M12 = 0.0f;
		result.M13 = -sin;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = 1.0f;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = sin;
		result.M32 = 0.0f;
		result.M33 = cos;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
	}
	Matrix Matrix::RotationZ( float angle )
	{
		Matrix result;
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );

		result.M11 = cos;
		result.M12 = sin;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = -sin;
		result.M22 = cos;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = 1.0f;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;

		return result;
	}
	void Matrix::RotationZ( float angle, [Out] Matrix% result )
	{
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );

		result.M11 = cos;
		result.M12 = sin;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = -sin;
		result.M22 = cos;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = 1.0f;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
	}
	Matrix Matrix::RotationAxis( Vector3 axis, float angle )
	{
		if( axis.LengthSquared() != 1.0f )
			axis.Normalize();

		Matrix result;
		float x = axis.X;
		float y = axis.Y;
		float z = axis.Z;
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );
		float xx = x * x;
		float yy = y * y;
		float zz = z * z;
		float xy = x * y;
		float xz = x * z;
		float yz = y * z;

		result.M11 = xx + (cos * (1.0f - xx));
		result.M12 = (xy - (cos * xy)) + (sin * z);
		result.M13 = (xz - (cos * xz)) - (sin * y);
		result.M14 = 0.0f;
		result.M21 = (xy - (cos * xy)) - (sin * z);
		result.M22 = yy + (cos * (1.0f - yy));
		result.M23 = (yz - (cos * yz)) + (sin * x);
		result.M24 = 0.0f;
		result.M31 = (xz - (cos * xz)) + (sin * y);
		result.M32 = (yz - (cos * yz)) - (sin * x);
		result.M33 = zz + (cos * (1.0f - zz));
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;

		return result;
	}
	void Matrix::RotationAxis( Vector3% axis, float angle, [Out] Matrix% result )
	{
		if( axis.LengthSquared() != 1.0f )
			axis.Normalize();

		float x = axis.X;
		float y = axis.Y;
		float z = axis.Z;
		float cos = static_cast<float>( Math::Cos( static_cast<double>( angle ) ) );
		float sin = static_cast<float>( Math::Sin( static_cast<double>( angle ) ) );
		float xx = x * x;
		float yy = y * y;
		float zz = z * z;
		float xy = x * y;
		float xz = x * z;
		float yz = y * z;

		result.M11 = xx + (cos * (1.0f - xx));
		result.M12 = (xy - (cos * xy)) + (sin * z);
		result.M13 = (xz - (cos * xz)) - (sin * y);
		result.M14 = 0.0f;
		result.M21 = (xy - (cos * xy)) - (sin * z);
		result.M22 = yy + (cos * (1.0f - yy));
		result.M23 = (yz - (cos * yz)) + (sin * x);
		result.M24 = 0.0f;
		result.M31 = (xz - (cos * xz)) + (sin * y);
		result.M32 = (yz - (cos * yz)) - (sin * x);
		result.M33 = zz + (cos * (1.0f - zz));
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
	}
	Matrix Matrix::RotationQuaternion( Quaternion quaternion )
	{
		Matrix result;

		float xx = quaternion.X * quaternion.X;
		float yy = quaternion.Y * quaternion.Y;
		float zz = quaternion.Z * quaternion.Z;
		float xy = quaternion.X * quaternion.Y;
		float zw = quaternion.Z * quaternion.W;
		float zx = quaternion.Z * quaternion.X;
		float yw = quaternion.Y * quaternion.W;
		float yz = quaternion.Y * quaternion.Z;
		float xw = quaternion.X * quaternion.W;
		result.M11 = 1.0f - (2.0f * (yy + zz));
		result.M12 = 2.0f * (xy + zw);
		result.M13 = 2.0f * (zx - yw);
		result.M14 = 0.0f;
		result.M21 = 2.0f * (xy - zw);
		result.M22 = 1.0f - (2.0f * (zz + xx));
		result.M23 = 2.0f * (yz + xw);
		result.M24 = 0.0f;
		result.M31 = 2.0f * (zx + yw);
		result.M32 = 2.0f * (yz - xw);
		result.M33 = 1.0f - (2.0f * (yy + xx));
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;

		return result;
	}
	void Matrix::RotationQuaternion( Quaternion% rotation, [Out] Matrix% result )
	{
		float xx = rotation.X * rotation.X;
		float yy = rotation.Y * rotation.Y;
		float zz = rotation.Z * rotation.Z;
		float xy = rotation.X * rotation.Y;
		float zw = rotation.Z * rotation.W;
		float zx = rotation.Z * rotation.X;
		float yw = rotation.Y * rotation.W;
		float yz = rotation.Y * rotation.Z;
		float xw = rotation.X * rotation.W;
		result.M11 = 1.0f - (2.0f * (yy + zz));
		result.M12 = 2.0f * (xy + zw);
		result.M13 = 2.0f * (zx - yw);
		result.M14 = 0.0f;
		result.M21 = 2.0f * (xy - zw);
		result.M22 = 1.0f - (2.0f * (zz + xx));
		result.M23 = 2.0f * (yz + xw);
		result.M24 = 0.0f;
		result.M31 = 2.0f * (zx + yw);
		result.M32 = 2.0f * (yz - xw);
		result.M33 = 1.0f - (2.0f * (yy + xx));
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
	}
	Matrix Matrix::RotationYawPitchRoll( float yaw, float pitch, float roll )
	{
		Matrix result;
		Quaternion quaternion;
		Quaternion::RotationYawPitchRoll( yaw, pitch, roll, quaternion );
		Matrix::RotationQuaternion( quaternion, result );
		return result;
	}
	void Matrix::RotationYawPitchRoll( float yaw, float pitch, float roll, [Out] Matrix% result )
	{
		Quaternion quaternion;
		Quaternion::RotationYawPitchRoll( yaw, pitch, roll, quaternion );
		Matrix::RotationQuaternion( quaternion, result );
	}
	Matrix Matrix::LookAtLH( Vector3 eye, Vector3 target, Vector3 up )
	{
		Matrix result;
		::D3DXMatrixLookAtLH( (D3DXMATRIX*) &result, (D3DXVECTOR3*) &eye, (D3DXVECTOR3*) &target, (D3DXVECTOR3*) &up );
		return result;
	}
	void Matrix::LookAtLH( Vector3% eye, Vector3% target, Vector3% up, [Out] Matrix% result )
	{
		pin_ptr<Vector3> pinEye = &eye;
		pin_ptr<Vector3> pinTarget = &target;
		pin_ptr<Vector3> pinUp = &up;
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixLookAtLH( (D3DXMATRIX*) pinResult, (D3DXVECTOR3*) pinEye, (D3DXVECTOR3*) pinTarget, (D3DXVECTOR3*) pinUp );
	}
	Matrix Matrix::LookAtRH( Vector3 eye, Vector3 target, Vector3 up )
	{
		Matrix result;
		::D3DXMatrixLookAtRH( (D3DXMATRIX*) &result, (D3DXVECTOR3*) &eye, (D3DXVECTOR3*) &target, (D3DXVECTOR3*) &up );
		return result;
	}
	void Matrix::LookAtRH( Vector3% eye, Vector3% target, Vector3% up, [Out] Matrix% result )
	{
		pin_ptr<Vector3> pinEye = &eye;
		pin_ptr<Vector3> pinTarget = &target;
		pin_ptr<Vector3> pinUp = &up;
		pin_ptr<Matrix> pinResult = &result;
		D3DXMatrixLookAtRH( (D3DXMATRIX*) pinResult, (D3DXVECTOR3*) pinEye, (D3DXVECTOR3*) pinTarget, (D3DXVECTOR3*) pinUp );
	}
	Matrix Matrix::OrthoLH( float width, float height, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixOrthoLH( (D3DXMATRIX*) &result, width, height, znear, zfar );
		return result;
	}
	void Matrix::OrthoLH( float width, float height, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixOrthoLH( (D3DXMATRIX*) pinResult, width, height, znear, zfar );
	}
	Matrix Matrix::OrthoRH( float width, float height, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixOrthoRH( (D3DXMATRIX*) &result, width, height, znear, zfar );
		return result;
	}
	void Matrix::OrthoRH( float width, float height, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixOrthoRH( (D3DXMATRIX*) pinResult, width, height, znear, zfar );
	}
	Matrix Matrix::OrthoOffCenterLH( float left, float right, float bottom, float top, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixOrthoOffCenterLH( (D3DXMATRIX*) &result, left, right, bottom, top, znear, zfar );
		return result;
	}
	void Matrix::OrthoOffCenterLH( float left, float right, float bottom, float top, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixOrthoOffCenterLH( (D3DXMATRIX*) pinResult, left, right, bottom, top, znear, zfar );
	}
	Matrix Matrix::OrthoOffCenterRH( float left, float right, float bottom, float top, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixOrthoOffCenterRH( (D3DXMATRIX*) &result, left, right, bottom, top, znear, zfar );
		return result;
	}
	void Matrix::OrthoOffCenterRH( float left, float right, float bottom, float top, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixOrthoOffCenterRH( (D3DXMATRIX*) pinResult, left, right, bottom, top, znear, zfar );
	}
	Matrix Matrix::PerspectiveLH( float width, float height, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixPerspectiveLH( (D3DXMATRIX*) &result, width, height, znear, zfar );
		return result;
	}
	void Matrix::PerspectiveLH( float width, float height, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixPerspectiveLH( (D3DXMATRIX*) pinResult, width, height, znear, zfar );
	}
	Matrix Matrix::PerspectiveRH( float width, float height, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixPerspectiveRH( (D3DXMATRIX*) &result, width, height, znear, zfar );
		return result;
	}
	void Matrix::PerspectiveRH( float width, float height, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixPerspectiveRH( (D3DXMATRIX*) pinResult, width, height, znear, zfar );
	}
	Matrix Matrix::PerspectiveFovLH( float fov, float aspect, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixPerspectiveFovLH( (D3DXMATRIX*) &result, fov, aspect, znear, zfar );
		return result;
	}
	void Matrix::PerspectiveFovLH( float fov, float aspect, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixPerspectiveFovLH( (D3DXMATRIX*) pinResult, fov, aspect, znear, zfar );
	}
	Matrix Matrix::PerspectiveFovRH( float fov, float aspect, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixPerspectiveFovRH( (D3DXMATRIX*) &result, fov, aspect, znear, zfar );
		return result;
	}
	void Matrix::PerspectiveFovRH( float fov, float aspect, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixPerspectiveFovRH( (D3DXMATRIX*) pinResult, fov, aspect, znear, zfar );
	}
	Matrix Matrix::PerspectiveOffCenterLH( float left, float right, float bottom, float top, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixPerspectiveOffCenterLH( (D3DXMATRIX*) &result, left, right, bottom, top, znear, zfar );
		return result;
	}
	void Matrix::PerspectiveOffCenterLH( float left, float right, float bottom, float top, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixPerspectiveOffCenterLH( (D3DXMATRIX*) pinResult, left, right, bottom, top, znear, zfar );
	}
	Matrix Matrix::PerspectiveOffCenterRH( float left, float right, float bottom, float top, float znear, float zfar )
	{
		Matrix result;
		::D3DXMatrixPerspectiveOffCenterRH( (D3DXMATRIX*) &result, left, right, bottom, top, znear, zfar );
		return result;
	}
	void Matrix::PerspectiveOffCenterRH( float left, float right, float bottom, float top, float znear, float zfar, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixPerspectiveOffCenterRH( (D3DXMATRIX*) pinResult, left, right, bottom, top, znear, zfar );
	}
	Matrix Matrix::Scaling( float x, float y, float z )
	{
		Matrix result;
		result.M11 = x;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = y;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = z;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
		return result;
	}
	void Matrix::Scaling( float x, float y, float z, [Out] Matrix% result )
	{
		result.M11 = x;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = y;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = z;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
	}
	Matrix Matrix::Scaling( Vector3 scale )
	{
		Matrix result;
		result.M11 = scale.X;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = scale.Y;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = scale.Z;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
		return result;
	}
	void Matrix::Scaling( Vector3% scale, [Out] Matrix% result )
	{
		result.M11 = scale.X;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = scale.Y;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = scale.Z;
		result.M34 = 0.0f;
		result.M41 = 0.0f;
		result.M42 = 0.0f;
		result.M43 = 0.0f;
		result.M44 = 1.0f;
	}
	Matrix Matrix::Translation( float x, float y, float z )
	{
		Matrix result;
		result.M11 = 1.0f;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = 1.0f;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = 1.0f;
		result.M34 = 0.0f;
		result.M41 = x;
		result.M42 = y;
		result.M43 = z;
		result.M44 = 1.0f;
		return result;
	}
	void Matrix::Translation( float x, float y, float z, [Out] Matrix% result )
	{
		result.M11 = 1.0f;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = 1.0f;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = 1.0f;
		result.M34 = 0.0f;
		result.M41 = x;
		result.M42 = y;
		result.M43 = z;
		result.M44 = 1.0f;
	}
	Matrix Matrix::Translation( Vector3 amount )
	{
		Matrix result;
		result.M11 = 1.0f;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = 1.0f;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = 1.0f;
		result.M34 = 0.0f;
		result.M41 = amount.X;
		result.M42 = amount.Y;
		result.M43 = amount.Z;
		result.M44 = 1.0f;
		return result;
	}
	void Matrix::Translation( Vector3% amount, [Out] Matrix% result )
	{
		result.M11 = 1.0f;
		result.M12 = 0.0f;
		result.M13 = 0.0f;
		result.M14 = 0.0f;
		result.M21 = 0.0f;
		result.M22 = 1.0f;
		result.M23 = 0.0f;
		result.M24 = 0.0f;
		result.M31 = 0.0f;
		result.M32 = 0.0f;
		result.M33 = 1.0f;
		result.M34 = 0.0f;
		result.M41 = amount.X;
		result.M42 = amount.Y;
		result.M43 = amount.Z;
		result.M44 = 1.0f;
	}
	Matrix Matrix::Invert( Matrix matrix )
	{
		Matrix result;
		::D3DXMatrixInverse( (D3DXMATRIX*) &result, NULL, (D3DXMATRIX*) &matrix );
		return result;
	}
	void Matrix::Invert( Matrix% matrix, [Out] Matrix% result )
	{
		pin_ptr<Matrix> pinMatrix = &matrix;
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixInverse( (D3DXMATRIX*) pinResult, NULL, (D3DXMATRIX*) pinMatrix );
	}
	Matrix Matrix::Transpose( Matrix mat )
	{
		Matrix result;
		result.M11 = mat.M11;
		result.M12 = mat.M21;
		result.M13 = mat.M31;
		result.M14 = mat.M41;
		result.M21 = mat.M12;
		result.M22 = mat.M22;
		result.M23 = mat.M32;
		result.M24 = mat.M42;
		result.M31 = mat.M13;
		result.M32 = mat.M23;
		result.M33 = mat.M33;
		result.M34 = mat.M43;
		result.M41 = mat.M14;
		result.M42 = mat.M24;
		result.M43 = mat.M34;
		result.M44 = mat.M44;
		return result;
	}
	void Matrix::Transpose( Matrix% mat, [Out] Matrix% result )
	{
		Matrix r;
		r.M11 = mat.M11;
		r.M12 = mat.M21;
		r.M13 = mat.M31;
		r.M14 = mat.M41;
		r.M21 = mat.M12;
		r.M22 = mat.M22;
		r.M23 = mat.M32;
		r.M24 = mat.M42;
		r.M31 = mat.M13;
		r.M32 = mat.M23;
		r.M33 = mat.M33;
		r.M34 = mat.M43;
		r.M41 = mat.M14;
		r.M42 = mat.M24;
		r.M43 = mat.M34;
		r.M44 = mat.M44;

		result = r;
	}
	Matrix Matrix::AffineTransformation( float scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation )
	{
		Matrix result;
		::D3DXMatrixAffineTransformation( (D3DXMATRIX*) &result, scaling, (D3DXVECTOR3*) &rotationCenter, (D3DXQUATERNION*) &rotation, (D3DXVECTOR3*) &translation );
		return result;
	}
	void Matrix::AffineTransformation( float scaling, Vector3% rotationCenter, Quaternion% rotation, Vector3% translation, [Out] Matrix% result )
	{
		pin_ptr<Vector3> pinRotationCenter = &rotationCenter;
		pin_ptr<Quaternion> pinRotation = &rotation;
		pin_ptr<Vector3> pinTranslation = &translation;
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixAffineTransformation( (D3DXMATRIX*) pinResult, scaling, (D3DXVECTOR3*) pinRotationCenter, (D3DXQUATERNION*) pinRotation, (D3DXVECTOR3*) pinTranslation );
	}
	Matrix Matrix::AffineTransformation2D( float scaling, Vector2 rotationCenter, float rotation, Vector2 translation )
	{
		Matrix result;
		::D3DXMatrixAffineTransformation2D( (D3DXMATRIX*) &result, scaling, (D3DXVECTOR2*) &rotationCenter, rotation, (D3DXVECTOR2*) &translation );
		return result;
	}
	void Matrix::AffineTransformation2D( float scaling, Vector2% rotationCenter, float rotation, Vector2% translation, [Out] Matrix% result )
	{
		pin_ptr<Vector2> pinRotationCenter = &rotationCenter;
		pin_ptr<Vector2> pinTranslation = &translation;
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixAffineTransformation2D( (D3DXMATRIX*) pinResult, scaling, (D3DXVECTOR2*) pinRotationCenter, rotation, (D3DXVECTOR2*) pinTranslation );
	}
	Matrix Matrix::Transformation( Vector3 scalingCenter, Quaternion scalingRotation, Vector3 scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation )
	{
		Matrix result;
		::D3DXMatrixTransformation( (D3DXMATRIX*) &result, (D3DXVECTOR3*) &scalingCenter, (D3DXQUATERNION*) &scalingRotation, (D3DXVECTOR3*) &scaling, (D3DXVECTOR3*) &rotationCenter, (D3DXQUATERNION*) &rotation, (D3DXVECTOR3*) &translation );
		return result;
	}
	void Matrix::Transformation( Vector3% scalingCenter, Quaternion% scalingRotation, Vector3% scaling, Vector3% rotationCenter, Quaternion% rotation, Vector3% translation, [Out] Matrix% result )
	{
		pin_ptr<Vector3> pinScalingCenter = &scalingCenter;
		pin_ptr<Quaternion> pinScalingRotation = &scalingRotation;
		pin_ptr<Vector3> pinScaling = &scaling;
		pin_ptr<Vector3> pinRotationCenter = &rotationCenter;
		pin_ptr<Quaternion> pinRotation = &rotation;
		pin_ptr<Vector3> pinTranslation = &translation;
		pin_ptr<Matrix> pinResult = &result;
		::D3DXMatrixTransformation( (D3DXMATRIX*) pinResult, (D3DXVECTOR3*) pinScalingCenter, (D3DXQUATERNION*) pinScalingRotation, (D3DXVECTOR3*) pinScaling, (D3DXVECTOR3*) pinRotationCenter, (D3DXQUATERNION*) pinRotation, (D3DXVECTOR3*) pinTranslation );
	}
	Matrix Matrix::Transformation2D( Vector2 scalingCenter, float scalingRotation, Vector2 scaling, Vector2 rotationCenter, float rotation, Vector2 translation )
	{
		Matrix result;
		::D3DXMatrixTransformation2D( (D3DXMATRIX*) &result, (D3DXVECTOR2*) &scalingCenter, scalingRotation, (D3DXVECTOR2*) &scaling, (D3DXVECTOR2*) &rotationCenter, rotation, (D3DXVECTOR2*) &translation );
		return result;
	}
	void Matrix::Transformation2D( Vector2% scalingCenter, float scalingRotation, Vector2% scaling, Vector2% rotationCenter, float rotation, Vector2% translation, [Out] Matrix% result )
	{
		pin_ptr<Vector2> pinScalingCenter = &scalingCenter;
		pin_ptr<Vector2> pinScaling = &scaling;
		pin_ptr<Vector2> pinRotationCenter = &rotationCenter;
		pin_ptr<Vector2> pinTranslation = &translation;
		pin_ptr<Matrix> pinResult = &result;
		D3DXMatrixTransformation2D( (D3DXMATRIX*) pinResult, (D3DXVECTOR2*) pinScalingCenter, scalingRotation, (D3DXVECTOR2*) pinScaling, (D3DXVECTOR2*) pinRotationCenter, rotation, (D3DXVECTOR2*) pinTranslation );
	}
	Matrix Matrix::operator - ( Matrix matrix )
	{
		Matrix result;
		result.M11 = -matrix.M11;
		result.M12 = -matrix.M12;
		result.M13 = -matrix.M13;
		result.M14 = -matrix.M14;
		result.M21 = -matrix.M21;
		result.M22 = -matrix.M22;
		result.M23 = -matrix.M23;
		result.M24 = -matrix.M24;
		result.M31 = -matrix.M31;
		result.M32 = -matrix.M32;
		result.M33 = -matrix.M33;
		result.M34 = -matrix.M34;
		result.M41 = -matrix.M41;
		result.M42 = -matrix.M42;
		result.M43 = -matrix.M43;
		result.M44 = -matrix.M44;
		return result;
	}
	Matrix Matrix::operator + ( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = left.M11 + right.M11;
		result.M12 = left.M12 + right.M12;
		result.M13 = left.M13 + right.M13;
		result.M14 = left.M14 + right.M14;
		result.M21 = left.M21 + right.M21;
		result.M22 = left.M22 + right.M22;
		result.M23 = left.M23 + right.M23;
		result.M24 = left.M24 + right.M24;
		result.M31 = left.M31 + right.M31;
		result.M32 = left.M32 + right.M32;
		result.M33 = left.M33 + right.M33;
		result.M34 = left.M34 + right.M34;
		result.M41 = left.M41 + right.M41;
		result.M42 = left.M42 + right.M42;
		result.M43 = left.M43 + right.M43;
		result.M44 = left.M44 + right.M44;
		return result;
	}
	Matrix Matrix::operator - ( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = left.M11 - right.M11;
		result.M12 = left.M12 - right.M12;
		result.M13 = left.M13 - right.M13;
		result.M14 = left.M14 - right.M14;
		result.M21 = left.M21 - right.M21;
		result.M22 = left.M22 - right.M22;
		result.M23 = left.M23 - right.M23;
		result.M24 = left.M24 - right.M24;
		result.M31 = left.M31 - right.M31;
		result.M32 = left.M32 - right.M32;
		result.M33 = left.M33 - right.M33;
		result.M34 = left.M34 - right.M34;
		result.M41 = left.M41 - right.M41;
		result.M42 = left.M42 - right.M42;
		result.M43 = left.M43 - right.M43;
		result.M44 = left.M44 - right.M44;
		return result;
	}
	Matrix Matrix::operator / ( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = left.M11 / right.M11;
		result.M12 = left.M12 / right.M12;
		result.M13 = left.M13 / right.M13;
		result.M14 = left.M14 / right.M14;
		result.M21 = left.M21 / right.M21;
		result.M22 = left.M22 / right.M22;
		result.M23 = left.M23 / right.M23;
		result.M24 = left.M24 / right.M24;
		result.M31 = left.M31 / right.M31;
		result.M32 = left.M32 / right.M32;
		result.M33 = left.M33 / right.M33;
		result.M34 = left.M34 / right.M34;
		result.M41 = left.M41 / right.M41;
		result.M42 = left.M42 / right.M42;
		result.M43 = left.M43 / right.M43;
		result.M44 = left.M44 / right.M44;
		return result;
	}
	Matrix Matrix::operator / ( Matrix left, float right )
	{
		Matrix result;
		result.M11 = left.M11 / right;
		result.M12 = left.M12 / right;
		result.M13 = left.M13 / right;
		result.M14 = left.M14 / right;
		result.M21 = left.M21 / right;
		result.M22 = left.M22 / right;
		result.M23 = left.M23 / right;
		result.M24 = left.M24 / right;
		result.M31 = left.M31 / right;
		result.M32 = left.M32 / right;
		result.M33 = left.M33 / right;
		result.M34 = left.M34 / right;
		result.M41 = left.M41 / right;
		result.M42 = left.M42 / right;
		result.M43 = left.M43 / right;
		result.M44 = left.M44 / right;
		return result;
	}
	Matrix Matrix::operator * ( Matrix left, Matrix right )
	{
		Matrix result;
		result.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41);
		result.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42);
		result.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43);
		result.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44);
		result.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41);
		result.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42);
		result.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43);
		result.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44);
		result.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41);
		result.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42);
		result.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43);
		result.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44);
		result.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41);
		result.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42);
		result.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43);
		result.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44);
		return result;
	}
	Matrix Matrix::operator * ( Matrix left, float right )
	{
		Matrix result;
		result.M11 = left.M11 * right;
		result.M12 = left.M12 * right;
		result.M13 = left.M13 * right;
		result.M14 = left.M14 * right;
		result.M21 = left.M21 * right;
		result.M22 = left.M22 * right;
		result.M23 = left.M23 * right;
		result.M24 = left.M24 * right;
		result.M31 = left.M31 * right;
		result.M32 = left.M32 * right;
		result.M33 = left.M33 * right;
		result.M34 = left.M34 * right;
		result.M41 = left.M41 * right;
		result.M42 = left.M42 * right;
		result.M43 = left.M43 * right;
		result.M44 = left.M44 * right;
		return result;
	}
	Matrix Matrix::operator * ( float left, Matrix right )
	{
		return right * left;
	}
	bool Matrix::operator == ( Matrix left, Matrix right )
	{
		return Matrix::Equals( left, right );
	}
	bool Matrix::operator != ( Matrix left, Matrix right )
	{
		return !Matrix::Equals( left, right );
	}
	System::String^ Matrix::ToString()
	{
		return String::Format( CultureInfo::CurrentCulture, "[[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]]",
			M11.ToString(CultureInfo::CurrentCulture), M12.ToString(CultureInfo::CurrentCulture), M13.ToString(CultureInfo::CurrentCulture), M14.ToString(CultureInfo::CurrentCulture),
			M21.ToString(CultureInfo::CurrentCulture), M22.ToString(CultureInfo::CurrentCulture), M23.ToString(CultureInfo::CurrentCulture), M24.ToString(CultureInfo::CurrentCulture),
			M31.ToString(CultureInfo::CurrentCulture), M32.ToString(CultureInfo::CurrentCulture), M33.ToString(CultureInfo::CurrentCulture), M34.ToString(CultureInfo::CurrentCulture),
			M41.ToString(CultureInfo::CurrentCulture), M42.ToString(CultureInfo::CurrentCulture), M43.ToString(CultureInfo::CurrentCulture), M44.ToString(CultureInfo::CurrentCulture) );
	}
	int Matrix::GetHashCode()
	{
		return M11.GetHashCode() + M12.GetHashCode() + M13.GetHashCode() + M14.GetHashCode() +
				M21.GetHashCode() + M22.GetHashCode() + M23.GetHashCode() + M24.GetHashCode() +
				M31.GetHashCode() + M32.GetHashCode() + M33.GetHashCode() + M34.GetHashCode() +
				M41.GetHashCode() + M42.GetHashCode() + M43.GetHashCode() + M44.GetHashCode();
	}
	bool Matrix::Equals( System::Object^ obj )
	{
		if( obj == nullptr )
			return false;

		if( obj->GetType() != GetType() )
			return false;

		return Equals( safe_cast<Matrix>( obj ) );
	}
	bool Matrix::Equals( Matrix value )
	{
		return ( M11 == value.M11 && M12 == value.M12 && M13 == value.M13 && M14 == value.M14 &&
					M21 == value.M21 && M22 == value.M22 && M23 == value.M23 && M24 == value.M24 &&
					M31 == value.M31 && M32 == value.M32 && M33 == value.M33 && M34 == value.M34 &&
					M41 == value.M41 && M42 == value.M42 && M43 == value.M43 && M44 == value.M44 );
	}
	bool Matrix::Equals( Matrix% value1, Matrix% value2 )
	{
		return ( value1.M11 == value2.M11 && value1.M12 == value2.M12 && value1.M13 == value2.M13 && value1.M14 == value2.M14 &&
					value1.M21 == value2.M21 && value1.M22 == value2.M22 && value1.M23 == value2.M23 && value1.M24 == value2.M24 &&
					value1.M31 == value2.M31 && value1.M32 == value2.M32 && value1.M33 == value2.M33 && value1.M34 == value2.M34 &&
					value1.M41 == value2.M41 && value1.M42 == value2.M42 && value1.M43 == value2.M43 && value1.M44 == value2.M44 );
	}
}