/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/


		#include "script_squirrel/cobject/matrix_decl.h"
		#include "script_squirrel/cobject/vector_decl.h"
		#include "math/matrix4.h"
		#include "math/matrix3.h"
		#include "math/quaternion.h"
		#include "nstring/nstring.h"
		#include "log/log.h"

		using namespace GS;


#ifndef	_T
#define _T
#endif

_DECL_CLASS(Matrix4)
_IMPL_NATIVE_CONSTRUCTION(Matrix4, Matrix4)

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, constructor)
	Matrix4 temp;
	int nparams = sa.GetParamCount();

	switch (nparams)
	{
		case 1:	temp.Set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);	break;
		case 5:
		{
			_GetTypedParam(_u, 2, Vector4, Vector);
			_GetTypedParam(_v, 3, Vector4, Vector);
			_GetTypedParam(_w, 4, Vector4, Vector);
			_GetTypedParam(_x, 5, Vector4, Vector);

			if	(_u && _v && _w && _x)
			{	temp.Set(_u->x, _u->y, _u->z, _u->w, _v->x, _v->y, _v->z, _v->w, _w->x, _w->y, _w->z, _w->w, _x->x, _x->y, _x->z, _x->w);	}
			else
				return sa.ThrowError("Matrix4() invalid parameters");
		}
		break;

		case 17:
			temp.Set(
						sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5),
						sa.GetFloat(6), sa.GetFloat(7), sa.GetFloat(8), sa.GetFloat(9),
						sa.GetFloat(10), sa.GetFloat(11), sa.GetFloat(12), sa.GetFloat(13),
						sa.GetFloat(14), sa.GetFloat(15), sa.GetFloat(16), sa.GetFloat(17)
					);
			break;

		default:
			return sa.ThrowError("Matrix4() wrong parameter count");
	}
	return construct_Matrix4(v, new Matrix4(temp));
_END_IMPL

//------------------------------------------------------------------------------
// The string class is used to speed up comparison as it uses a hash-based early
// rejection.
static	String	uc_m00("m00"), uc_m10("m10"), uc_m20("m20"), uc_m30("m30"),
				uc_m01("m01"), uc_m11("m11"), uc_m21("m21"), uc_m31("m31"),
				uc_m02("m02"), uc_m12("m12"), uc_m22("m22"), uc_m32("m32"),
				uc_m03("m03"), uc_m13("m13"), uc_m23("m23"), uc_m33("m33");

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, _set)
	_GetSelf(Matrix4, Matrix4);

	switch (sa.GetType(2))
	{
		case OT_STRING:
		{
			String idx(sa.GetString(2));

			if	(idx == uc_m00)	return sa.Return(self->m[0][0] = sa.GetFloat(3));
			if	(idx == uc_m10)	return sa.Return(self->m[1][0] = sa.GetFloat(3));
			if	(idx == uc_m20)	return sa.Return(self->m[2][0] = sa.GetFloat(3));
			if	(idx == uc_m30)	return sa.Return(self->m[3][0] = sa.GetFloat(3));
			if	(idx == uc_m01)	return sa.Return(self->m[0][1] = sa.GetFloat(3));
			if	(idx == uc_m11)	return sa.Return(self->m[1][1] = sa.GetFloat(3));
			if	(idx == uc_m21)	return sa.Return(self->m[2][1] = sa.GetFloat(3));
			if	(idx == uc_m31)	return sa.Return(self->m[3][1] = sa.GetFloat(3));
			if	(idx == uc_m02)	return sa.Return(self->m[0][2] = sa.GetFloat(3));
			if	(idx == uc_m12)	return sa.Return(self->m[1][2] = sa.GetFloat(3));
			if	(idx == uc_m22)	return sa.Return(self->m[2][2] = sa.GetFloat(3));
			if	(idx == uc_m32)	return sa.Return(self->m[3][2] = sa.GetFloat(3));
			if	(idx == uc_m03)	return sa.Return(self->m[0][3] = sa.GetFloat(3));
			if	(idx == uc_m13)	return sa.Return(self->m[1][3] = sa.GetFloat(3));
			if	(idx == uc_m23)	return sa.Return(self->m[2][3] = sa.GetFloat(3));
			if	(idx == uc_m33)	return sa.Return(self->m[3][3] = sa.GetFloat(3));
		}
		break;
	}
	return SQ_ERROR;
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, _get)
	_GetSelf(Matrix4, Matrix4);

	switch (sa.GetType(2))
	{
		case OT_STRING:
		{
			String idx(sa.GetString(2));

			if	(idx == uc_m00)	return sa.Return(self->m[0][0]);
			if	(idx == uc_m10)	return sa.Return(self->m[1][0]);
			if	(idx == uc_m20)	return sa.Return(self->m[2][0]);
			if	(idx == uc_m30)	return sa.Return(self->m[3][0]);
			if	(idx == uc_m01)	return sa.Return(self->m[0][1]);
			if	(idx == uc_m11)	return sa.Return(self->m[1][1]);
			if	(idx == uc_m21)	return sa.Return(self->m[2][1]);
			if	(idx == uc_m31)	return sa.Return(self->m[3][1]);
			if	(idx == uc_m02)	return sa.Return(self->m[0][2]);
			if	(idx == uc_m12)	return sa.Return(self->m[1][2]);
			if	(idx == uc_m22)	return sa.Return(self->m[2][2]);
			if	(idx == uc_m32)	return sa.Return(self->m[3][2]);
			if	(idx == uc_m03)	return sa.Return(self->m[0][3]);
			if	(idx == uc_m13)	return sa.Return(self->m[1][3]);
			if	(idx == uc_m23)	return sa.Return(self->m[2][3]);
			if	(idx == uc_m33)	return sa.Return(self->m[3][3]);
		}
		break;
	}
	return SQ_ERROR;
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, GetRow)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(sa.GetInt(2))));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, SetRow)
	_GetSelf(Matrix4, Matrix4);
	_GetTypedParam(row, 3, Vector4, Vector)
	self->SetRow(sa.GetInt(2), *row);
	return 0;
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, GetColumn)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetColumn(sa.GetInt(2))));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, SetColumn)
	_GetSelf(Matrix4, Matrix4);
	_GetTypedParam(col, 3, Vector4, Vector)
	self->SetColumn(sa.GetInt(2), *col);
	return 0;
_END_IMPL

_MEMBER_FUNCTION_IMPL(Matrix4, GetFront)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(2)));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, GetBack)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(2).Reversed()));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, GetUp)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(1)));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, GetDown)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(1).Reversed()));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, GetRight)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(0)));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, GetLeft)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(0).Reversed()));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix4, GetPosition)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(3)));
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, _mul)
	_GetSelf(Matrix4, Matrix4);
	_GetTypedParam(mtx, 2, Matrix4, Matrix4)
	_SA_RETURN_OBJECT(new_Matrix4(v, *self * *mtx));
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, AsMatrix3)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Matrix3(v, Matrix3::FromMatrix4(*self)));
_END_IMPL
//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, GetInverseMatrix)
	_GetSelf(Matrix4, Matrix4);
	_SA_RETURN_OBJECT(new_Matrix4(v, self->InversedFast()));
_END_IMPL
//-----------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix4, Print)
	_GetSelf(Matrix4, Matrix4);
	const char	*label = "Matrix";
	if	(sa.GetParamCount() == 2)
		label = sa.GetString(2);
	__LOG__ << "Dumping matrix '" << label << "':\n";
	for (int n = 0; n < 4; ++n)
	{
		Vector4 v = self->GetRow(n);
		__LOG__ << "Row " << n << ": { " << v.x << ", " << v.y << ", " << v.z << ", " << v.w << "}\n";
	}
	return 0;
_END_IMPL

_MEMBER_FUNCTION_IMPL(Matrix4, RotationFromMatrix3)
	_GetSelf(Matrix4, Matrix4);
	_GetTypedParam(mtx, 2, Matrix3, Matrix3)
	self->m[0][0] = mtx->m[0][0]; self->m[1][0] = mtx->m[1][0]; self->m[2][0] = mtx->m[2][0];
	self->m[0][1] = mtx->m[0][1]; self->m[1][1] = mtx->m[1][1]; self->m[2][1] = mtx->m[2][1];
	self->m[0][2] = mtx->m[0][2]; self->m[1][2] = mtx->m[1][2]; self->m[2][2] = mtx->m[2][2];
	return 0;
_END_IMPL

//------------------------------------------------------------------------------
/*#
	Topic: Matrix
	Type: Matrix3
	Type: Matrix4
#*/

/*#
	Section: MatrixGeneric
	Desc: Global functions
#*/
	/*#
		Func: Matrix3
		Proto: Matrix3:float m00...m33
		Desc: Create a new 3x3 matrix.
		Example:
// Construct a default unity matrix.
local a = Matrix3()
// Vector based constructor.
local b = Matrix3(v0, v1, v2)
// Float based constructor.
local c = Matrix3(m00, m10, m20, m01, m11, m21, m02, m12, m22)
	#*/
	/*#
		Func: Matrix4
		Proto: Matrix4:float m00...m44
		Desc: Create a new 4x4 matrix.
		Example:
// Construct a default unity matrix.
local a = Matrix4()
// Vector based constructor.
local b = Matrix4(v0, v1, v2, v3)
// Float based constructor.
local c = Matrix3(m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33)
	#*/
	/*#
		Func: RotationMatrixX
		Proto: Matrix3:float angle
		Desc: Create a 3x3 rotation matrix around the X axis, angle is in degree.
		Example: local m = RotationMatrixX(Deg(45))
	#*/
	/*#
		Func: RotationMatrixY
		Proto: Matrix3:float angle
		Desc: Create a 3x3 rotation matrix around the Y axis, angle is in degree.
		Example: local m = RotationMatrixY(Deg(45))
	#*/
	/*#
		Func: RotationMatrixZ
		Proto: Matrix3:float angle
		Desc: Create a 3x3 rotation matrix around the Z axis, angle is in degree.
		Example: local m = RotationMatrixZ(Deg(45))
	#*/
	/*#
		Func: MatrixToEuler
		Proto: Vector:Matrix3,RotationOrder
		Desc: Convert a world space matrix to Euler angles.
	#*/
	/*#
		Func: EulerFromDirection
		Proto: Vector:Vector direction
		Desc: Convert a world space direction vector to an Euler angle triplet (x, y, z).
	#*/
	/*#
		Func: EulerFromDirectionAndUp
		Proto: Vector:Vector direction,Vector up
		Desc: Convert a world space direction and up vectors to an Euler angle triplet (x, y, z).
	#*/
	/*#
		Func: RotationMatrixFromDirection
		Proto: Matrix3:Vector direction
		Desc: Convert a world space direction vector to a 3x3 rotation matrix.
	#*/
	/*#
		Func: RotationMatrixFromDirectionAndUp
		Proto: Matrix3:Vector direction,Vector up
		Desc: Convert a world space direction and up vectors to a 3x3 rotation matrix.
	#*/
	/*#
		Func: TransformationMatrix
		Proto: Matrix4:Vector position,Vector euler,Vector scale,Vector pivot
		Desc: Create a position, rotation, scale, offset 4x4 matrix.<br>The offset is applied first, scale second, rotation third and finally position is applied.
	#*/

/*#
	Section: Matrix4Generic
	Desc: Matrix 4x4
#*/
_BEGIN_CLASS(Matrix4)
_MEMBER_FUNCTION(Matrix4, constructor, -1, _T(". n|x n|x n|x n|x nnnn nnnn"))
_MEMBER_FUNCTION(Matrix4, _get, 2, _T("xs"))
_MEMBER_FUNCTION(Matrix4, _set, 3, _T("xsn"))
_MEMBER_FUNCTION(Matrix4, _mul, 2, _T("xx"))

	/*#
		Func: GetRow
		Proto: Vector:int index
		Desc: Return a matrix row as a vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetRow, 2, _T("xi"))
	/*#
		Func: SetRow
		Proto: void:int index, Vector row
		Desc: Set a matrix row from a vector.
	#*/
_MEMBER_FUNCTION(Matrix4, SetRow, 3, _T("xix"))
	/*#
		Func: GetColumn
		Proto: Vector:int index
		Desc: Return a matrix column as a vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetColumn, 2, _T("xi"))
	/*#
		Func: SetColumn
		Proto: void:int index, Vector column
		Desc: Set a matrix column from a vector.
	#*/
_MEMBER_FUNCTION(Matrix4, SetColumn, 3, _T("xix"))
	/*#
		Func: AsMatrix3
		Proto: Matrix3:
		Desc: Return matrix as a 3x3 matrix.
	#*/
_MEMBER_FUNCTION(Matrix4, AsMatrix3, 1, _T("x"))
/*#
		Func: GetInverseMatrix
		Proto: Matrix4:
		Desc: Return inverse matrix.
	#*/
_MEMBER_FUNCTION(Matrix4, GetInverseMatrix, 1, _T("x"))
	/*#
		Func: Print
		Proto: void:
		Desc: Output matrix content to the engine log.
	#*/
_MEMBER_FUNCTION(Matrix4, Print, -1, _T("x"))
	/*#
		Func: RotationFromMatrix3
		Proto: void:Matrix3 orientation
		Desc: Set the rotation part of a 4x4 transformation matrix from a 3x3 matrix.
	#*/
_MEMBER_FUNCTION(Matrix4, RotationFromMatrix3, 2, _T("xx"))

/*#
	Section: Matrix4Component
	Desc: Transformation matrix component
#*/

	/*#
		Func: GetFront
		Proto: Vector:
		Desc: Return the transformation matrix front axis vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetFront, 1, _T("x"))
	/*#
		Func: GetBack
		Proto: Vector:
		Desc: Return the transformation matrix down axis vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetBack, 1, _T("x"))
	/*#
		Func: GetRight
		Proto: Vector:
		Desc: Return the transformation matrix right axis vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetRight, 1, _T("x"))
	/*#
		Func: GetLeft
		Proto: Vector:
		Desc: Return the transformation matrix left axis vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetLeft, 1, _T("x"))
	/*#
		Func: GetUp
		Proto: Vector:
		Desc: Return the transformation matrix up axis vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetUp, 1, _T("x"))
	/*#
		Func: GetDown
		Proto: Vector:
		Desc: Return the transformation matrix down axis vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetDown, 1, _T("x"))
	/*#
		Func: GetPosition
		Proto: Vector:
		Desc: Return the transformation matrix position vector.
	#*/
_MEMBER_FUNCTION(Matrix4, GetPosition, 1, _T("x"))

_END_CLASS(Matrix4)

//------------------------------------------------------------------------------
_DECL_CLASS(Matrix3);
_IMPL_NATIVE_CONSTRUCTION(Matrix3, Matrix3);

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix3, constructor)
	Matrix3	temp, *newv = NULL;
	int nparams = sa.GetParamCount();

	switch (nparams)
	{
		case 1:	temp.Set(1, 0, 0, 0, 1, 0, 0, 0, 1);	break;
		case 4:
		{
			_GetTypedParam(_u, 2, Vector4, Vector);
			_GetTypedParam(_v, 3, Vector4, Vector);
			_GetTypedParam(_w, 4, Vector4, Vector);

			if	(_u && _v && _w)
			{	temp.Set(*_u, *_v, *_w);	}
			else
				return sa.ThrowError("Matrix3() invalid parameters");
		}
		break;

		case 10:
			temp.Set(
						sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4),
						sa.GetFloat(5), sa.GetFloat(6), sa.GetFloat(7),
						sa.GetFloat(8), sa.GetFloat(9), sa.GetFloat(10)
					);
			break;

		default:
			return sa.ThrowError("Matrix3() wrong parameter count");
	}

	newv = new Matrix3(temp);
	return construct_Matrix3(v, newv);
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix3, _set)
	_GetSelf(Matrix3, Matrix3);

	switch (sa.GetType(2))
	{
		case OT_STRING:
		{
			String idx(sa.GetString(2));

			if	(idx == uc_m00)	return sa.Return(self->m[0][0] = sa.GetFloat(3));
			if	(idx == uc_m10)	return sa.Return(self->m[1][0] = sa.GetFloat(3));
			if	(idx == uc_m20)	return sa.Return(self->m[2][0] = sa.GetFloat(3));
			if	(idx == uc_m01)	return sa.Return(self->m[0][1] = sa.GetFloat(3));
			if	(idx == uc_m11)	return sa.Return(self->m[1][1] = sa.GetFloat(3));
			if	(idx == uc_m21)	return sa.Return(self->m[2][1] = sa.GetFloat(3));
			if	(idx == uc_m02)	return sa.Return(self->m[0][2] = sa.GetFloat(3));
			if	(idx == uc_m12)	return sa.Return(self->m[1][2] = sa.GetFloat(3));
			if	(idx == uc_m22)	return sa.Return(self->m[2][2] = sa.GetFloat(3));
		}
		break;
	}
	return SQ_ERROR;
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix3, _get)
	_GetSelf(Matrix3, Matrix3);

	switch (sa.GetType(2))
	{
		case OT_STRING:
		{
			String idx(sa.GetString(2));

			if	(idx == uc_m00)	return sa.Return(self->m[0][0]);
			if	(idx == uc_m10)	return sa.Return(self->m[1][0]);
			if	(idx == uc_m20)	return sa.Return(self->m[2][0]);
			if	(idx == uc_m01)	return sa.Return(self->m[0][1]);
			if	(idx == uc_m11)	return sa.Return(self->m[1][1]);
			if	(idx == uc_m21)	return sa.Return(self->m[2][1]);
			if	(idx == uc_m02)	return sa.Return(self->m[0][2]);
			if	(idx == uc_m12)	return sa.Return(self->m[1][2]);
			if	(idx == uc_m22)	return sa.Return(self->m[2][2]);
		}
		break;
	}
	return SQ_ERROR;
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix3, GetRow)
	_GetSelf(Matrix3, Matrix3);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(sa.GetInt(2))));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix3, SetRow)
	_GetSelf(Matrix3, Matrix3);
	_GetTypedParam(row, 3, Vector4, Vector)
	self->SetRow(sa.GetInt(2), *row);
	return 0;
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix3, GetColumn)
	_GetSelf(Matrix3, Matrix3);
	_SA_RETURN_OBJECT(new_Vector(v, self->GetColumn(sa.GetInt(2))));
_END_IMPL
_MEMBER_FUNCTION_IMPL(Matrix3, SetColumn)
	_GetSelf(Matrix3, Matrix3);
	_GetTypedParam(col, 3, Vector4, Vector)
	self->SetColumn(sa.GetInt(2), *col);
	return 0;
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix3, _mul)
	_GetSelf(Matrix3, Matrix3);
	_GetTypedParam(mtx, 2, Matrix3, Matrix3)
	_SA_RETURN_OBJECT(new_Matrix3(v, *self * *mtx));
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix3, AsMatrix4)
	_GetSelf(Matrix3, Matrix3);
	_SA_RETURN_OBJECT(new_Matrix4(v, Matrix4::FromMatrix3(*self)));
_END_IMPL

//------------------------------------------------------------------------------
_MEMBER_FUNCTION_IMPL(Matrix3, FromOrthonormalBasis)
//	_CHECK_SELF(Matrix3, Matrix3);
	_GetTypedParam(_w, 2, Vector4, Vector)
	Vector4 *_v = NULL;
	switch (sa.GetParamCount())
	{
		case 2:
			break;
		case 3:
		{	_GetTypedParam(__v, 3, Vector4, Vector)
			_v = __v;		}	break;
		default:
			return sa.ThrowError("Matrix3::FromOrthonormalBasis() wrong parameter count");
	}
	_SA_RETURN_OBJECT(new_Matrix3(v, Matrix3::FromOrthonormalBasis(*_w, _v)));
_END_IMPL

_MEMBER_FUNCTION_IMPL(Matrix3, SlerpTo)
	_GetSelf(Matrix3, Matrix3);
	_GetTypedParam(to, 3, Matrix3, Matrix3)
	float t = sa.GetFloat(2);
	Matrix3 out = Quaternion::Slerp(t, Quaternion::FromMatrix3(*self), Quaternion::FromMatrix3(*to)).AsMatrix3();
	_SA_RETURN_OBJECT(new_Matrix3(v, out))
_END_IMPL

_MEMBER_FUNCTION_IMPL(Matrix3, AsEuler)
	_GetSelf(Matrix3, Matrix3);
	Math::rOrder rorder = Math::rOrder_Default;
	if	(sa.GetParamCount() == 2)
		rorder = (Math::rOrder)sa.GetInt(2);
	_SA_RETURN_OBJECT(new_Vector(v, self->AsEuler(rorder)));
_END_IMPL

//------------------------------------------------------------------------------
/*#
	Section: Matrix3Generic
	Desc: Matrix 3x3
#*/
_BEGIN_CLASS(Matrix3)
_MEMBER_FUNCTION(Matrix3, constructor, -1, _T(". n|x n|x n|x nnn nnn"))
_MEMBER_FUNCTION(Matrix3, _get, 2, _T("xs"))
_MEMBER_FUNCTION(Matrix3, _set, 3, _T("xsn"))
_MEMBER_FUNCTION(Matrix3, _mul, 2, _T("xx"))
	/*#
		Func: GetRow
		Proto: Vector:int index
		Desc: Return a matrix row as a vector.
	#*/
_MEMBER_FUNCTION(Matrix3, GetRow, 2, _T("xi"))
	/*#
		Func: SetRow
		Proto: void:int index, Vector row
		Desc: Set a matrix row from a vector.
	#*/
_MEMBER_FUNCTION(Matrix3, SetRow, 3, _T("xix"))
	/*#
		Func: GetColumn
		Proto: Vector:int index
		Desc: Return a matrix column as a vector.
	#*/
_MEMBER_FUNCTION(Matrix3, GetColumn, 2, _T("xi"))
	/*#
		Func: SetColumn
		Proto: void:int index, Vector column
		Desc: Set a matrix column from a vector.
	#*/
_MEMBER_FUNCTION(Matrix3, SetColumn, 3, _T("xix"))
	/*#
		Func: AsMatrix4
		Proto: Matrix4:
		Desc: Return matrix as a 4x4 matrix.
	#*/
_MEMBER_FUNCTION(Matrix3, AsMatrix4, 1, _T("x"))
	/*#
		Func: FromOrthonormalBasis
		Proto: Matrix3:Vector u,[Vector v]
		Desc: Build an orientation matrix from one or two basis vectors.
	#*/
_MEMBER_FUNCTION(Matrix3, FromOrthonormalBasis, -2, _T(".xx"))
	/*#
		Func: SlerpTo
		Proto: Matrix3:float t,Matrix3 to
		Desc: Interpolate a 3x3 orientation matrix to another 3x3 orientation matrix using spherical linear interpolation.
		Example:
local m_a = ItemGetRotationMatrix(item_a)
local m_b = ItemGetRotationMatrix(item_b)

// m_c will store a rotation halfway between the rotation stored in the m_a and m_b matrices.
local m_c = m_a.SlerpTo(0.5, m_b)
	#*/
_MEMBER_FUNCTION(Matrix3, SlerpTo, 3, _T("xnx"))
	/*#
		Func: AsEuler
		Proto: Vector:[RotationOrder method]
		Desc: Return a 3x3 orientation matrix as an Euler triplet.
	#*/
_MEMBER_FUNCTION(Matrix3, AsEuler, -1, _T("xi"))
_END_CLASS(Matrix3)
